• Print view

## goto always to sunny face of planet

All about writing scripts for Celestia in Lua and the .cel system
Topic author
loberlat
Posts: 1
Joined: 16.06.2009
With us: 8 years 7 months

### goto always to sunny face of planet

Hello,
I have to write a script to show to children, the planets of our solar system.
First, I begin to place my observer at a zenital position of the sun and show the orbit of planets.
Second, I have to go to a planete, to its sunny side, ans accelerate time to make it one complete turn in 10 seconds.
and after, I return to my initial position, a zenital position of the sun.

My problem is that I can't place my obs near the selected planet with the sun in observer's back. I want to use the goto command but I don't know how to calculate the position point and the rotation of my observer. It's very hard for me to move in a 3D world... I worked to this problem for 3 days with no result... argh.....

Can someone illuminate me?

Thank a lot...

cpotting
Posts: 164
Joined: 18.03.2004
Age: 56
With us: 13 years 9 months

### Re: goto always to sunny face of planet

The below code is for a function I created some time ago called travel_to. It is definitely over-powered for what you want to do, but it will position your observer as you indicated with only a few parameter settings. Unfortunately, I am pressed for time at the moment and can't take the time to write out a smaller code snippet.

Once you include the function you will be able to position the observer to view the sunlit portion of Mars as follows:

Code: Select all

MARS  = celestia:find("Sol/Mars")travel_to{ body=MARS, location="over subsolar point"}

Look at the comments in the function for how to adjust the distance from the planet (e.g. try changing location to
• "above subsolar point"
• "viewing subsolar point"
• ".5AU above subsolar point"
• "5000KM above subsolar point"
You could also play with the duration parameter to speed up/slow down the trip:

Code: Select all

travel_to{ body=MARS, location="over subsolar point", duration=20}

You may also want to make sure you are facing Mars:

Code: Select all

travel_to{ body=MARS, location="over subsolar point", duration=20, tracking=MARS}
or

Code: Select all

travel_to{ body=MARS, location="over subsolar point", duration=20, final_tracking=MARS}

The code for the function is:

Code: Select all

--[[ Move observer to a given position using the parameters supplied as the table travel_parms.  Items in travel_parms     are:      adjust_time - Determines if travel_to() will use a shorter duration when the start and ending positions are close                    to each other.                       e.g. travel_to({ body=EARTH, duration=60, tracking=EARTH });wait(10)                           travel_to({ body=EARTH, duration=60, tracking=EARTH });wait(10)                           travel_to({ body=EARTH, duration=60, tracking=EARTH, adjust_time=false });wait(10)                      the second travel_to() only has to go a few km and will use a shorter value for duration.                      the third travel_to() also has to go a few km, but will take a full 60 seconds to do so.                      default: true      at          - The time (specified in julian days) that the simulation should be set to when the trip completes.                     default: the (current time + duration) * current timescale      body          - String or object indicating the body that placement will be relative to.                       default: the point indicated by the universal coordinates 0, 0, 0.      calc_only   - If present and set to true, then travel_to does not move the observer.  Instead the location that                    the observer would be moved to is calculated and returned as a position.                     default: false.        location    - Text description of where the observer will be placed.  May contain any of the following locales:                      "covisual"    - A position 10 degrees from the subcynthion antipodal point and 9 radii from the                                      body, from which it is possible to view both the body and the reference_body                                      (within a standard field of view of approximately 24 degrees).                     "pole"        - The approximate north pole of the body.  Note: a known bug in Celestia causes this                                      point to be calculated as vertical to the ecliptic, not the equator.  This means                                      that "pole" points to a point on the body's "arctic circle".                     "subcynthion" - The point on the surface of the body where the reference_body will appear at                                      zenith.  "subcynthion" is my own term derived from "subpolar point" (the point on                                      Earth directly under the Sun) and "pericynthion" (the closest point in an object's                                      orbit around an artificial body [the closest term I could find])                     "subsolar"    - Same as "subcynthion".  Provided for convienience since the most common usage of                                      "subcynthion" will be a reference to the "subsolar point".                         "terminator"  - A position 89 degrees from the line between the body and the reference_body.                                       Since the default location_reference will usually be a star (the Sun), this will                                      usually place the observer over the day-night terminator.                     "longlat x,y" - A position at longitude x, latitude y on the surface of the body.  Note: x any y                                     are given in degrees, may be negative and may include decimals.  x and y must be                                      seperated only by a comma - no spaces are allowed.                    and any combination of the following modifiers:                     "above"     - The observer will be placed 1.1 radii from the body.                     "antipodal" - Rotates the vector from the body to the observer by 180 degrees.                     "antipous"  - The same as "antipodal" ("anitpous" is the singular of "antipodes").                     "diagonal"  - Rotates the vector from the body to the observer by 45 degrees.                     "from"      - Ignored.  Provided to allow expressions such as "viewing terminator from 5AU".                       "left"      - Indicates that rotation of the vector from the body to the observer should be                                    "left-handed" (or clockwise as seen from 'above') (e.g. "over left terminator"                                    places the observer over the object's leading terminator (for prograde orbits).                       "over"      - The observer will be placed 6 radii from the body.                     "point"     - Ignored.  Provided to allow expressions such as "over subsolar point" and                                    "diagonal to subcynthion point".                       "right"     - Indicates that rotation of the vector from the body to the observer should be                                    "right-handed" (or counter-clockwise as seen from 'above') (c.f. "left").                     "to"        - Ignored.  Provided to allow expressions such as "diagonal to terminator".                     "viewing"   - The observer's distance from the body will be 98% of the distance to the                                    reference_body.                                   Note: "over" and "above" are ignored if "viewing" is used.                     "xAU"       - Where x is an number, the observer will be placed x astronomical units from body.                     "xKM"       - Where x is an number, the observer will be placed x kilometres from body.                     "xRADII"    - Where x is an number, the observer will be placed x times the radius of the body                                    from body.                    Note: "over", "above" and "viewing" become ignored words if "xAU", "xKM" or "xRADII" are used.                    Defaults are "subsolar", "right" and "over".        reference_body -                    - a second body which is used in calculating some locations (i.e. "terminator", "subcynthion").                       default: the primary of the system to which body belongs, or Sol if body is nil      position    - a position (in universal coordinates) to which the observer will be moved.                    Note: if position is specified, then body, location, and reference_body cannot be used.        observer      - indicates which observer should travel.                       default: the current observer.        duration      - the number of seconds this trip will take.                       default: 10.      initial_tracking                  - a body to be centred and remain centred on the screen at the start of the trip.  Note that up to                     1/10 of the trip time or 3 seconds (whichever is less) may be devoted to turning the observer                     towards the body before the actual movement begins.  The body will remain centred until the                     time specified by start_interpolation is reached.                    initial_tracking cannot be used with tracking or initial_orientation.                     default: no tracking.  The observer remains in its initial orientation until the                              start_interpolation time is reached.      final_tracking                  - a body to be centred and remain centred on the screen during the latter portion of the trip.  The                    observer will begin turning toward the body once the start_interpolation time is reached and be                    fully turned when the end_interpolation time is reached.                    final_tracking cannot be used with tracking or final_orientation                     default: no tracking.  The observer remains in the same orientation it was in at the                              start_interpolation time.      tracking      - a body to be used as both the initial_tracking body and the final_tracking body.                    tracking cannot be used with initial_tracking, initial_orientation, final_tracking or                    final_orientation.                    start_interpolation and end_interpolation are ignored when tracking is specified.      final_up    - a vector indicating which direction will be "up" (towards the top of the screen) when then journey                    is complete.  final_up cannot be used if final_orientation is given.                     default: "up" for the initial_orientation      initial_orientation                  - the orientation the observer should have at the start of the trip.  Note that up to 1/10 of the trip                    time or 3 seconds (whichever is less) may be devoted to truning the observer this orientation.  This                    orientation will be maintained until the time specified by start_interpolation is reached.                    initial_orientation cannot be used with tracking or initial_tracking.                     default: the current orientation for the observer.      final_orientation                  - the orientation the observer should have at the end of the trip.  The observer will begin turning                    toward the final_orientation once the start_interpolation time is reached and be fully turned when                     the end_interpolation time is reached.                    final_orientation cannot be used with tracking, final_tracking or final_up                     default: no orientation change.  The observer remains in the same orientation it was in at the                              start_interpolation time.      start_interpolation                  - the point in the trip (expressed as a percent) at which the observer should begin turning from the                    the initial_orientation or intial_tracking body to the final_orientation or final_tracking body.                     default: 0.25      end_interpolation                  - the point in the trip (expressed as a percent) at which the observer should finish turning from the                     initial_orienation or intial_tracking body and now fully face the final_orientation or                     final_tracking body.                     default: 0.75      accelTime   - indicates (as a percentage) how much of the trip should be spent accelerating away from the initial                    location.  Also represents the amount of time that will be spent decelerating towards the final                    location.  The remainder of the trip is spend cruising.                     default: 0.25.  minimum: 0.01  maximum 0.5      jerk         - indicates whether acceleration and deceleration should be at constant value (jerk=false) or at                    an accelerating amount (jerk=true).  Jerk is the term for the rate of change of acceleration.                     default: true   The following constants may also be defined before calling travel_to():      TRAVEL_TO_DURATION: when specified, this becomes the default value for travel_parms.duration.      TRAVEL_TO_JERK:     when specified, this becomes the default value for travel_parms.jerk     Note: control is not returned until the trip is complete, so wait() is not necessary with travel_to() ]]function travel_to(travel_parms)   -- obs = which of the open observers is to be moved   local obs = travel_parms.observer   if obs == nil then      obs = celestia:getobserver()   elseif not(obs:isvalid()) then      obs = celestia:getobserver()   end      -- travel_time = seconds spent moving from start position to end position   local travel_time = travel_parms.duration   if travel_time == nil then      travel_time = TRAVEL_TIME_DURATION      if travel_time == nil then         travel_time = 10      end   end      -- endtime = simulation time once the journey is complete   local endtime = travel_parms.at   if endtime == nil then      endtime = obs:gettime() + travel_time * celestia:gettimescale() /  SEC_PER_JDAY   end      -- initial_tracking = which object is to be tracked at the start of the journey   -- final_tracking   = which object is to be tracked at the end of the journey   -- start_interpolation = when to start switching from intial_tracking/_orientation to final_tracking/_orientation   -- end_interpolation   = when to complete switching from intial_tracking/_orientation to final_tracking/_orientation   -- centre_time = time devoted to reorienting the observer to the proper initial orientation   local initial_tracking       = nil   local initial_orientation    = nil   local final_tracking       = nil   local final_orientation    = nil   local start_interpolation    = .25   local end_interpolation      = .75   local centre_time          = 0   local vpixels_per_sec = 200 -- max turn rate while reorienting   local radians_per_sec = 1   -- max roll rate while reorienting   local final_up = travel_parms.final_up   if final_up ~= nil and travel_parms.final_orientation ~= nil then      celestia:flash("Illegial combination of parameters: final_up may not be used with final_orientation", 60);wait(60)      error(1)   end   if travel_parms.tracking == nil then      initial_tracking = travel_parms.initial_tracking      if initial_tracking == nil then         initial_orientation = travel_parms.initial_orientation      elseif travel_parms.initial_orientation ~= nil then         celesita:flash("Illegial combination of parameters: initial_orientation may not be used with initial_tracking",                        60);wait(60);error(1)      end      final_tracking = travel_parms.final_tracking      if final_tracking == nil then         final_orientation = travel_parms.final_orientation      elseif travel_parms.final_orientation ~= nil then         celesita:flash("Illegial combination of parameters: final_orientation may not be used with final_tracking",                        60);wait(60);error(1)      end   else      -- tracking means we are to track one object through the entire journey      if travel_parms.initial_tracking ~= nil or travel_parms.final_tracking ~= nil then         celestia:flash("Illegial combination of parameters: initial_/final_tracking may not be used with tracking", 60)         wait(60);error(1)      elseif travel_parms.start_interpolation ~= nil or travel_parms.end_interpolation ~= nil then         celestia:flash("Illegial combination of parameters: start_/end_interpolation may not be used with tracking",                        60);wait(60);error(1)      elseif travel_parms.initial_orientation ~= nil or travel_parms.final_orientation ~= nil then         celestia:flash("Illegial combination of parameters: initial_/final_orientation may not be used with tracking",                        60);wait(60);error(1)      end      -- set the tracking object as both the intial_tracking and final_tracking objects      initial_tracking = travel_parms.tracking      final_tracking   = travel_parms.tracking      -- since we are tracking a single object, if there is no final_up parameter then there is no need for an       -- interpolation phase      if final_up == nil then         start_interpolation = 0         end_interpolation = 0      end   end      -- goto_position = destination is a specific set of coordinates in space in the universal frame of reference   local goto_position = travel_parms.position   if goto_position == nil then      goto_position = celestia:newposition(0, 0, 0)   elseif travel_parms.body ~= nil then      celestia:flash("Illegial combination of parameters: body may not be used with position", 60);wait(60);error(1)   elseif travel_parms.location ~= nil then      celestia:flash("Illegial combination of parameters: location may not be used with position", 60);wait(60);      error(2)   elseif travel_parms.reference_body ~= nil then      celestia:flash("Illegial combination of parameters: reference_body may not be used with position", 60);      wait(60);error(3)   end      -- body = destination will be a point located relative to the given body   -- body_radius = size of the body   -- body_up = direction from the body's centre to its north pole   local body = travel_parms.body   if type(body) == "string" then      body = celestia:find(body)   end   local body_radius, body_up   if body == nil then      body_radius = 0      body_up     = celestia:newvector(0, 1, 0)   else      goto_position = body:getposition(endtime)      body_radius   = body:radius()      body_up       = celestia:newframe("equatorial", body):from(celestia:newposition(.001, 1, 0), endtime) -                       goto_position   end      -- reference_position = coorinates of a second body sometimes needed to specify the desired destination   local reference = travel_parms.reference_body   local reference_position   if type(reference) == "string" then      reference = celestia:find(reference)   elseif reference == nil then      if body == nil then         reference = celestia:find("Sol")      else         reference = find_system_parent(body)         if body == reference then            reference = nil         end      end   end   if reference == nil then      reference_position = celestia:newposition(0, 0, 0)   else      reference_position = reference:getposition(endtime)   end      -- parse the locale and modifiers   local action = ""   local angle = 0   local angle_factor = 1   local distance_factor = 6   local viewing = false   local viewing_AU = goto_position:distanceto(reference_position) * .98 / KM_PER_AU   local ignore_tokens = { from=0, over=0, point=0, right=0, subcynthion=0, subsolar=0, to=0 }   local token, token_value   local token_is_longlat = false   if travel_parms.location ~= nil then      for token in string.gfind(travel_parms.location, "([%w%.,%-]+)%s*") do         token = string.lower(token)         token_value = tonumber(string.sub(token, 1, -3))         if token_is_longlat then            for long, lat in string.gfind(token, "([%d%.%-]+),([%d%.%-]+)") do               local distance = reference_position:distanceto(goto_position)               local x = - distance * math.cos(math.rad(long)) * math.cos(math.rad(lat))               local y = distance * math.sin(math.rad(lat))                local z = distance * math.sin(math.rad(long)) * math.cos(math.rad(lat))               reference_position =                  celestia:newframe("planetographic", body):from(celestia:newposition(x, y, z), endtime)            end            token_is_longlat = false         elseif token == "above" then            distance_factor = 1.1         elseif token == "antipodal" or token == "antipous" then            angle = angle + 180         elseif token == "covisual" then            angle = angle + 173            distance_factor = 9         elseif token == "diagonal" then            angle = angle - 45         elseif token == "left" then            angle_factor = -1         elseif token == "longlat" then             token_is_longlat=true         elseif token == "pole" then            if body == nil then               celestia:flash("Illegial location: pole without body\in: " .. travel_parms.location, 60);wait(60);               error(2)            end            local distance = reference_position:distanceto(goto_position)            reference_position =               celestia:newframe("planetographic", body):from(celestia:newposition(.001, distance, 0), endtime)         elseif token == "terminator" then            angle = angle - 89         elseif token == "viewing" then            viewing = true         elseif string.sub(token, -2) == "au" and token_value ~= nil then            viewing = true            viewing_AU = token_value         elseif string.sub(token, -2) == "km" and token_value ~= nil then            viewing = true            viewing_AU = token_value / KM_PER_AU         elseif string.sub(token, -1) == "r" and tonumber(string.sub(token, 1, -2)) ~= nil then            viewing = true            viewing_AU = body_radius * tonumber(string.sub(token, 1, -2)) / KM_PER_AU         elseif ignore_tokens[token] == nil then            celestia:flash("Unknown location word: " .. token .. "\nin: " .. travel_parms.location, 60);wait(60);            error(3)         end      end   end      -- calculate the endposition: coordinates to travel to   local vector_endpoint_to_reference = reference_position - goto_position   local normalised_vector_endpoint_to_reference = vector_endpoint_to_reference:normalize()   local vector_from_endpoint_towards_reference   if viewing then      vector_from_endpoint_towards_reference = viewing_AU / AU_PER_uLY * normalised_vector_endpoint_to_reference   else      vector_from_endpoint_towards_reference =         (body_radius * distance_factor) / KM_PER_uLY * normalised_vector_endpoint_to_reference   end   local desired_rotation = celestia:newrotation(body_up, math.rad(angle * angle_factor))   local endposition = goto_position + desired_rotation:transform(vector_from_endpoint_towards_reference)      -- calc_only = don't travel, just return the destination coordinates   if travel_parms.calc_only == true then      return endposition   end      -- intial_tracking = object to watch as we start the journey   if initial_tracking ~= nil then      if type(initial_tracking) == "string" then         initial_tracking = celestia:find(initial_tracking)      end   end      -- determine what direction we should face at the start of the journey, and how long to devote to turning to that   -- direction   if initial_tracking ~= nil or initial_orientation ~= nil then      -- shave up to 3 seconds or 10% off the the total travel time to spend turning to the initial_tracking object or      -- initial_orientation      local look_vector = celestia:newvector(0,0,-1)      local current_look_vector   = (obs:getorientation():transform(look_vector)):normalize()      local current_up_vector      = (obs:getorientation():transform(UP)):normalize()      local desired_look_vector      local desired_up_vector      if initial_tracking == nil then         desired_look_vector   = (initial_orientation:transform(look_vector)):normalize()         desired_up_vector      = (initial_orientation:transform(UP)):normalize()      else         desired_look_vector   = (initial_tracking:getposition() - obs:getposition()):normalize()         desired_up_vector      = current_up_vector      end      -- see if we are looking in the desired direction, if not, determine how much we have to turn and how long      -- to allow in doing so      local screenh, screenv = celestia:getscreendimension()      if (current_look_vector - desired_look_vector):length() > 1e-8 then         local vpixels_from_centre = screenv * math.acos(current_look_vector * desired_look_vector) / obs:getfov()         centre_time = math.min(vpixels_from_centre / vpixels_per_sec, travel_time * 0.1, 3)      end      -- see if we need to roll.      if (current_up_vector - desired_up_vector):length() > 1e-8 then         local radians_to_roll = math.acos(current_up_vector * desired_up_vector)         local roll_time = math.min(radians_to_roll / radians_per_sec, travel_time * 0.1, 3)         centre_time = math.max(centre_time, roll_time)      end   end      -- final_tracking = object to watch as we end the journey   if final_tracking ~= nil then      if type(final_tracking) == "string" then         final_tracking = celestia:find(final_tracking)      end   end   -- recalculate the time to actually be spent travelling   travel_time = travel_time - centre_time      -- if we are already near the endpoint and there is no timetravel involved then shorten the journey time.   if travel_parms.at == nil and travel_parms.adjust_time ~= false then      local tolerance      if body == nil then         tolerance = obs:getposition():distanceto(celestia:newposition(0,0,0)) * .02      else         tolerance = obs:getposition():distanceto(body:getposition()) * .02      end      local travel_distance = obs:getposition():distanceto(endposition)      if travel_distance < tolerance then         local new_travel_time = travel_distance / tolerance         if new_travel_time < travel_time then            travel_time = new_travel_time         end      end   end      -- start applying changes to the observer   -- first, display data about the body   if body ~= nil then      celestia:select(travel_parms.body)   end   -- centre the body to be initially tracked on the screen   if initial_tracking ~= nil then      initial_tracking:preloadtexture()      if initial_tracking:getinfo().parent ~= nil then         -- to load the planet for moons, satellites, etc.         initial_tracking:getinfo().parent:preloadtexture()      end      obs:track(nil)      obs:center(initial_tracking, centre_time)      wait(centre_time)      obs:track(initial_tracking)   end   -- turn to the initial_orientation   if initial_orientation ~= nil and centre_time > 0 then      local start_orientation = obs:getorientation()      local end_reorient_scripttime = celestia:getscripttime() + centre_time      local reorient_percent = 1      while reorient_percent > 0 do         wait(0.0)         reorient_percent = math.max((end_reorient_scripttime - celestia:getscripttime()) / centre_time, 0)         obs:setorientation(initial_orientation:slerp(start_orientation, reorient_percent))      end   end      -- final calculations before we travel...      -- Note: Measurements are made relative to the endstate, not the startstate.  This is so that multiplicative      --       errors will reduce to 0 as we approach the endstate, rather than increase as we get farther from the      --         startstate      -- Note: accel/decel math is implemented as follows      --         j:      jerk (acceleration of acceleration)      --         a:      acceleration                         ia:   initial acceleration      --         s:      speed                                 is:   initial speed      --         d:      distance from origin                  id:   initial distance from origin      --         acceleration at time t:       --            a[t] = j t + ia      --         the antiderivative of acceleration is speed s (not velocity):      --            s[t] = .5 j t^2 + ia t + is      --         the antiderivative of speed is displacement (which I am calling distance for convenience):      --            d[t] = j t^3 / 6 + .5 ia t^2 + is t + id      --         (can someone please check my unused-for-20-years calculus?)      --         since we are considering the observer's current position as the starting point of the journey: id = 0      --         since we are not accounting for the observer's current motion: is = 0      --         therefore:      --            s[t] = .5 j t^2 + ia t + 0 = .5 j t^2 + ia t      --            d[t] = j t^3 / 6 + .5 ia t^2 + 0 t + 0 = j t^3 / 6 + .5 ia t^2      --       D:    total travel distance               T:      total travel time      --         da:   total distance spent accelerating   ta:   total time spent accelerating      --         dc:   total distance spent cruising         tc:   total time spent cruising      --         dd:   total distance spend decelerating   td:   total time spent decelerating       --         d[t]:   distance covered by time t      --         da[t]: distance covered in acceleration phase by time t   ta[t] = total time spent accelerating at time t      --         dc[t]: distance covered in cruising phase by time t      tc[t] = total time spent cruising at time t      --         dd[t]: distance covered in deceleration phase by time t   td[t] = total time spent decelerating at time t      --            tc = T - ta - td ; td = ta ; tc = T - 2 ta      --            da = d[ta] = j ta^3 / 6 + .5 ia ta^2      --            dc = cruising speed * time cruising = speed after acceleration * time cruising      --               = s[ta] tc = (.5 j ta^2 + ia ta) tc = .5 j tc ta^2 + ia tc ta      --            dd = d[ta] = j ta^3 / 6 + .5 ia ta^2      --            D = da + dc + dd = j ta^3 / 6 + .5 ia ta^2 + .5 j tc ta^2 + ia tc ta + j ta^3 / 6 + .5 ia ta^2      --         if constant acceleration is to be used ( { accel=true } ), then j = 0 and ia is determined as follows:      --          D = 0 + .5 ia ta^2 + 0 + ia tc ta + 0 + .5 ia ta^2 = ia ta^2 + ia tc ta = ia (ta^2 + tc ta)      --          ia = D / (ta^2 + tc ta)      --       if accelerating acceleration is to be used ( { jerk=true } ), then ia = 0 and j is determined as follows:      --            D = j ta^3 / 6 + 0 + .5 j tc ta^2 + 0 + j ta^3 / 6 + 0      --            = j (ta^3 / 3 + .5 tc ta^2)      --            j = D / (ta^3 / 3 + .5 tc ta^2)      --         when d and t are percentages of D and T then D = 1 and T = 1, therefore      --            tc = 1 - 2 ta      --          ta[t] = min(t, ta)      --            tc[t] = min(max(t - ta, 0), tc)      --            td[t] = max(t - ta - tc, 0) = max(t - ta - (1 - 2 ta), 0) =  max(t - 1 + ta, 0)      --            da[t] = j ta[t]^3 / 6 + .5 ia ta[t]^2      --            dc[t] = .5 j tc[t] ta[t]^2 + ia ta tc[t]      --          dd[t] = dd - (j (td - td[t])^3 / 6 + .5 ia (td - td[t])^2)      --                = j ta^3 / 6 + .5 ia ta^2 - j (td - td[t])^3 / 6 - .5 ia (td - td[t])^2      --                = j (ta^3 - (td - td[t])^3) / 6 + .5 ia(ta^2  - (td - td[t])^2)      --            d[t] = da[t] + dc[t] + dt[t] > 0 ? dd[t] : 0      --       when t is changed to measure from 1 (start of journey) to 0, end of journey, then      --            ta[t] = 1 - max(1 - ta, t)      --            td[t] = td - min(td, t) = ta - min(ta, t)      --            tc[t] = 1 - t - ta[t] - td[t]   local accel_percent = travel_parms.accelTime   -- = ta   if accel_percent == nil then      accel_percent = .25   end   accel_percent = math.min(math.max(accel_percent, .001), .5)   local cruise_percent = 1 - 2 * accel_percent   -- = tc   local jerk, acceleration                     -- = j, ia   local use_jerk = travel_parms.jerk   if use_jerk == nil then      use_jerk = TRAVEL_TO_JERK      if use_jerk == nil then         use_jerk = true      end   end   if use_jerk then      jerk = 1 / ((accel_percent^3) / 3 + .5 * cruise_percent * accel_percent^2)      acceleration = 0   else      jerk = 0      acceleration = 1 / (accel_percent^2 + cruise_percent * accel_percent)   end   local current_up_vector = (obs:getorientation():transform(UP)):normalize()   local timechange = endtime - obs:gettime()   local end_scripttime = celestia:getscripttime() + travel_time   local travel_vector = obs:getposition() - endposition   local start_interpolation_orientation, end_interpolation_orientation   local time_percent = 1                                                   -- = t   local accel_time_percent, cruise_time_percent, decel_time_percent         -- = tat, tct, tdt   local accel_dist_percent, cruise_dist_percent, decel_dist_percent         -- = da[t], dc[t], dd[t]   local distance_percent                                                   -- = dt   -- end_ and start_interpolation are measured from the start of the journey, change them to measure from the end   end_interpolation = 1 - end_interpolation   start_interpolation = 1 - start_interpolation   -- final rotational calculations   local interpolation_started = false   local interpolation_ended = false   local need_final_up = (final_up ~= nil)   if final_orientation == nil then      if final_tracking == nil or end_interpolation == 1 then         end_interpolation_orientation = obs:getorientation()      else         -- where will we be when it is time to stop turning the observer (ei), and where should the observer point to?         accel_time_percent = math.min(end_interpolation, accel_percent)                                       -- ta[ei]         cruise_time_percent = math.min(math.max(end_interpolation - accel_percent, 0), cruise_percent)         -- tc[ei]         decel_time_percent = math.max(end_interpolation - 1 + accel_percent, 0)                                 -- td[ei]         accel_dist_percent = (jerk * accel_time_percent^3) / 6 + .5 * acceleration * accel_time_percent^2      -- da[ei]         cruise_dist_percent = .5 * jerk * cruise_time_percent * accel_time_percent^2 +                               acceleration * accel_percent * cruise_time_percent                              -- dc[ei]         decel_dist_percent = jerk * (accel_percent^3 - (accel_percent - decel_time_percent)^3) / 6 +          -- dd[ei]                                 .5 * acceleration * (accel_percent^2  - (accel_percent - decel_time_percent)^2)         distance_percent = accel_dist_percent + cruise_dist_percent + decel_dist_percent                        -- dt[ei]         local end_interpolation_position = endposition + travel_vector * distance_percent         local end_interpolation_time         if travel_parms.at == nil then            -- no at given: time change is linear            end_interpolation_time = endtime - timechange * end_interpolation         else            -- with at, time change will accel/cruise/decel            end_interpolation_time = endtime - timechange * distance_percent         end         local final_up_vector = current_up_vector         if need_final_up then            final_up_vector = final_up            need_final_up = false         end         end_interpolation_orientation =            end_interpolation_position:orientationto(final_tracking:getposition(end_interpolation_time),                                                     final_up_vector)      end      if need_final_up then         -- we still need to rotate the final orientation so that final_up will point to the top of the screen         local origin = celestia:newposition(0,0,0)         local look_vector = celestia:newvector(0,0,-1)         local final_look_vector   = (end_interpolation_orientation:transform(look_vector)):normalize()         end_interpolation_orientation = origin:orientationto(origin + final_look_vector, final_up)      end   else      end_interpolation_orientation = final_orientation   end   local interpolation_duration = start_interpolation - end_interpolation      -- do the actual travelling   while time_percent > 0 do      time_percent = math.max((end_scripttime - celestia:getscripttime()) / travel_time, 0)               -- t      accel_time_percent = math.min(time_percent, accel_percent)                                          -- ta[t]      cruise_time_percent = math.min(math.max(time_percent - accel_percent, 0), cruise_percent)            -- tc[t]      decel_time_percent = math.max(time_percent - 1 + accel_percent, 0)                                 -- td[tei]      accel_dist_percent = (jerk * accel_time_percent^3) / 6 + .5 * acceleration * accel_time_percent^2   -- da[t]      cruise_dist_percent = .5 * jerk * cruise_time_percent * accel_time_percent^2 +                            acceleration * accel_percent * cruise_time_percent                           -- dc[t]      decel_dist_percent = jerk * (accel_percent^3 - (accel_percent - decel_time_percent)^3) / 6 +         -- dd[t]                            .5 * acceleration * (accel_percent^2  - (accel_percent - decel_time_percent)^2)      distance_percent = accel_dist_percent + cruise_dist_percent + decel_dist_percent                     -- dt[t]      --celestia:flash(string.format("j=%3.3f a=%3.3f\nt[%1.4f] = %1.4f + %1.4f + %1.4f\ndt[%1.4f] = %1.4f + %1.4f + %1.4f",      --                       jerk, acceleration,      --                       time_percent, accel_time_percent, cruise_time_percent, decel_time_percent,      --                       distance_percent, accel_dist_percent, cruise_dist_percent, decel_dist_percent))      obs:setposition(endposition + travel_vector * distance_percent)      if travel_parms.at == nil then         celestia:settime(endtime - timechange * time_percent) -- no at given: time change is linear      else         celestia:settime(endtime - timechange * distance_percent) -- with at, time change will accel/cruise/decel      end      if time_percent > end_interpolation then         if start_interpolation > time_percent then            if interpolation_started == false then               start_interpolation_orientation = obs:getorientation()               obs:track(nil)               interpolation_started = true            end            obs:setorientation(end_interpolation_orientation:slerp(start_interpolation_orientation,                               (time_percent - end_interpolation) / interpolation_duration))         end      elseif interpolation_ended == false then         obs:setorientation(end_interpolation_orientation)         obs:track(final_tracking)         interpolation_ended = true      end      wait(0.0)   end      -- re-set the endstates (for accuraccy)   celestia:settime(endtime)   obs:setposition(endposition)   wait(0.0)   obs:track(nil)   if body ~= nil then      obs:follow(body)   endend -- travel_to()
Clive Pottinger

cpotting
Posts: 164
Joined: 18.03.2004
Age: 56
With us: 13 years 9 months

### Re: goto always to sunny face of planet

oops. I missed the definition of some constants that are needed:

Code: Select all

   KM_PER_AU     = 149597870.7   KM_PER_uLY    = 9466411.842   AU_PER_uLY    = (KM_PER_uLY / KM_PER_AU)   SEC_PER_JDAY  = 86400    DAYS_PER_YR   = 365.2624   c_uLY_PER_SEC = 1000000 / (SEC_PER_JDAY * DAYS_PER_YR)   UP            = celestia:newvector(0,1,0)   ALMOST_UP     = celestia:newvector(0.000001,1,0) -- used to avoid positioning an observer so it is looking in the                                                    -- exact direction of a frame's UP vector (which causes display                                                    -- problems)   ALMOST_ABOVE  = celestia:newposition(0.000001,1,0) -- ALMOST_UP described as a position - useful in limited cases
Clive Pottinger

Vincent
Posts: 1356
Joined: 07.01.2005
With us: 13 years
Location: Nancy, France

### Re: goto always to sunny face of planet

loberlat wrote:Second, I have to go to a planete, to its sunny side, ans accelerate time to make it one complete turn in 10 seconds.
Hi,

The following celx script moves the observer to a position located on the Planet-Sun axis.
Just replace Earth with the needed planet in the first line of the script.

Code: Select all

target = celestia:find("Sol/Earth")star = celestia:find("Sol")distance = target:radius() * 5v = (star:getposition() - target:getposition()):normalize()coeff = distance / 1e7pos = celestia:newposition(v.x * coeff, v.y * coeff, v.z * coeff)obs = celestia:getobserver()celestia:select(target)obs:gotodistance(target, distance, 5)wait(5)obs:track(target)obs:gotolocation(pos, 5)wait(6)obs:track(nil)
@+
Vincent

Celestia Qt4 SVN / Celestia 1.6.1 + Lua Edu Tools v1.2
GeForce 8600 GT 1024MB / AMD Athlon 64 Dual Core / 4Go DDR2 / XP SP3