Jump to content

Celestia/Celx Scripting/CELX Lua Methods/CEL command orbit

From Wikibooks, open books for an open world

orbit

[edit | edit source]

orbit { duration <duration> rate <rate> axis <axisvector> }

Orbit the currently selected object during <duration> seconds at <rate> speed (in units of degrees per second), using the currently defined Coordinate System, around the specified <axisvector>. You must first use the select command to select an object, and optionally use the setframe command to define a Coordinate System, if one is not currently defined.

Arguments:

duration <duration>
Number of seconds to orbit the object. Default is 1.0.
rate <rate>
Speed at which to orbit the object, in units of degrees per second. Default is 1.0.
Positive and negative values are used to indicate the direction of orbit ("+" sign is not necessary).
axis <axisvector>
Define which axis to orbit around [x y z]. No default.
Set the x, y, or z value to 1 for yes, 0 for no. You may also specify multiple axes.


CELX equivalent-1 for Celestia version 1.6.1 and later:

Based on the 1.6.1 observer:orbit() method.

This equivalent orbits the reference object during about <duration> seconds over exactly <duration> * <rate> degrees.

  • Find and select the object with name <string> that must be orbited and store in "objectname".
objectname = celestia:find( <string> )
celestia:select(objectname)
  • Get observer instance of the active view and store in "obs".
obs=celestia:getobserver()
  • Make "objectname" the reference object in the "ecliptic" (follow) frame of reference.
obs:follow(objectame)
  • "duration" = <duration> = the duration of the orbit in seconds.
duration = <duration>
  • <rate> is the orbit velocity in degrees per second, which must be transformed in radians per second by multiplying the <rate> with math.pi (= 3.14159265) and divide by 180 and stored in "radiansrate". The Lua math.rad( <rate> ) function can also be used for this.
radiansrate = math.rad( <rate> )
  • Create a vector <axisvector> for the axis to orbit around.
axis_vector = celestia:newvector( <axisvector> )
  • Determine the orbit angle in radians by multiplying <duration> with "radiansrate".
orbitangle = duration * radiansrate
  • Split up the orbit in 30 steps per second and determine the orbit steptime for each single step.
    The factor 0.75 is an estimate and may depend on the speed of your computer.
orbitsteps = 30 * duration
orbitsteptime = 0.75*duration/orbitsteps
  • Create new rotation object of split up orbit angle around the specified axis.
rot = celestia:newrotation(axis_vector, orbitangle/orbitsteps)
  • Actually execute the orbit.
for i = 1, orbitsteps do
   obs:orbit(rot)
   wait(orbitsteptime)
end

Summarized:

objectname = celestia:find( <string> )
celestia:select(objectname)
obs=celestia:getobserver()
obs:follow(objectame)
duration = <duration>
radiansrate = math.rad( <rate> )
axis_vector = celestia:newvector( <axisvector> )
orbitangle = duration * radiansrate
orbitsteps = 30 * duration
orbitsteptime = 0.75*duration/orbitsteps
rot = celestia:newrotation(axis_vector, orbitangle/orbitsteps)
for i = 1, orbitsteps do
   obs:orbit(rot)
   wait(orbitsteptime)
end

Summarized as a function:

function orbit_object_angle(period, orbitrate, axis)
   local orbitangle = period * orbitrate
   local orbitsteps = 30 * period
   local orbitsteptime = 0.75*period/orbitsteps
   local rot = celestia:newrotation(axis, orbitangle/orbitsteps)
   local obs = celestia:getobserver()
   for i = 1, orbitsteps do
      obs:orbit(rot)
      wait(orbitsteptime)
   end
end

objectname = celestia:find( <string> )
celestia:select(objectname)
obs = celestia:getobserver()
obs:follow(objectame)
radiansrate = math.rad( <rate> )
axis_vector = celestia:newvector( <axisvector> )
orbit_object_angle( <duration> , radiansrate, axis_vector)


CELX equivalent-2 for Celestia version 1.6.1 and later:

Based on the 1.6.1 observer:orbit() method.

This equivalent orbits the reference object during exacly <duration> seconds over about <duration> * <rate> degrees.

  • Find and select the object with name <string> that must be orbited and store in "objectname".
objectname = celestia:find( <string> )
celestia:select(objectname)
  • Get observer instance of the active view and store in "obs".
obs=celestia:getobserver()
  • Make "objectname" the reference object in the "ecliptic" (follow) frame of reference.
obs:follow(objectame)
  • "duration" = <duration> = the duration of the orbit in seconds.
duration = <duration>
  • <rate> is the orbit velocity in degrees per second, which must be transformed in radians per second by multiplying the <rate> with math.pi (= 3.14159265) and divide by 180 and stored in "radiansrate". The Lua math.rad( <rate> ) function can also be used for this.
radiansrate = math.rad( <rate> )
  • Determine the orbit angle in radians by multiplying <duration> with "radiansrate".
orbitangle = duration * radiansrate
  • Create a vector <axisvector> for the axis to orbit around.
axis_vector = celestia:newvector( <axisvector> )
  • Split up the orbit in 30 steps per second and determine the orbit steptime for each single step.
    The factor 0.75 is an estimate and may depend on the speed of your computer.
orbitsteps = 30 * duration
orbitsteptime = 0.75*duration/orbitsteps
  • Create new rotation object of split up orbit angle around the specified axis.
rot = celestia:newrotation(axis_vector, orbitangle/orbitsteps)
  • Get the elapsed time in seconds since the script has been started and store in "t0".
t0 = celestia:getscripttime()
  • Actually execute the orbit.
while celestia:getscripttime() <= t0 + duration do
   obs:orbit(rot)
   wait(orbitsteptime)
end

Summarized:

objectname = celestia:find( <string> )
celestia:select(objectname)
obs=celestia:getobserver()
obs:follow(objectame)
duration = <duration>
radiansrate = math.rad( <rate> )
orbitangle = duration * radiansrate
axis_vector = celestia:newvector( <axisvector> )
orbitsteps = 30 * duration
orbitsteptime = 0.75*duration/orbitsteps
rot = celestia:newrotation(axis_vector, orbitangle/orbitsteps)
t0 = celestia:getscripttime()
while celestia:getscripttime() <= t0 + duration do
   obs:orbit(rot)
   wait(orbitsteptime)
end

Summarized as a function:

function orbit_object_time(period, orbitrate, axis)
   local orbitangle = period * orbitrate
   local orbitsteps = 30 * period
   local orbitsteptime = 0.75*period/orbitsteps
   local rot = celestia:newrotation(axis, orbitangle/orbitsteps)
   local obs = celestia:getobserver()
   local t0 = celestia:getscripttime()
   while celestia:getscripttime() <= t0 + period do
      obs:orbit(rot)
      wait(orbitsteptime)
   end
end

objectname = celestia:find( <string> )
celestia:select(objectname)
obs = celestia:getobserver()
obs:follow(objectame)
radiansrate = math.rad( <rate> )
axis_vector = celestia:newvector( <axisvector> )
orbit_object_time( <duration> , radiansrate, axis_vector)


CELX equivalent-3:

Based on an arithmetic sequence of methods.

Note: NO <axisvector> can be defined in this CELX equivalent.

  • Find and select the object with name <string> that must be orbited and store in "objectname".
objectname = celestia:find( <string> )
celestia:select(objectname)
  • "duration" = <duration> = the duration of the orbit in seconds.
duration = <duration>
  • <rate> is the orbit velocity in degrees per second, which must be transformed in radians per second by multiplying the <rate> with math.pi (= 3.14159265) and divide by 180 and stored in "radiansrate". The Lua math.rad( <rate> ) function can also be used for this.
radiansrate = math.rad( <rate> )
  • Get observer instance of the active view and store in "obs".
obs=celestia:getobserver()

  • "v1" is the vector from the viewer to "objectname", normalized to length 1.
    "up" is the camera up direction (standard Y-direction).
    "v2" is normal to both "v1" and "up", normalized to length 1.
now = celestia:gettime()
v1 = obs:getposition() - objectname:getposition(now)
distance = v1:length()
v1 = v1:normalize()
up = obs:getorientation():transform(celestia:newvector(0, 1, 0))
v2 = v1 ^ up
v2 = v2:normalize()
  • Determine the orbit angle in radians by multiplying <duration> with "radiansrate".
orbitangle = duration * radiansrate
  • Orbit in the plane containing "v1" and normal to the up direction in <duration> seconds
start = celestia:getscripttime()
t = (celestia:getscripttime() - start) / duration
while t < 1 do
   t = (celestia:getscripttime() - start) / duration
   theta = orbitangle * t
   v = math.cos(theta) * v1 + math.sin(theta) * v2
   obs:setposition(objectname:getposition() + v * distance)
   obs:lookat(objectname:getposition(), up)
   wait(0)
end

Summarized:

objectname = celestia:find( <string> )
celestia:select(objectname)
duration = <duration>
radiansrate = math.rad( <rate> )
obs=celestia:getobserver()
now = celestia:gettime()
v1 = obs:getposition() - objectname:getposition(now)
distance = v1:length()
v1 = v1:normalize()
up = obs:getorientation():transform(celestia:newvector(0, 1, 0))
v2 = v1 ^ up
v2 = v2:normalize()
orbitangle = duration * radiansrate
start = celestia:getscripttime()
t = (celestia:getscripttime() - start) / duration
while t < 1 do
   t = (celestia:getscripttime() - start) / duration
   theta = orbitangle * t
   v = math.cos(theta) * v1 + math.sin(theta) * v2
   obs:setposition(objectname:getposition() + v * distance)
   obs:lookat(objectname:getposition(), up)
   wait(0)
end

Summarized as a function:

function orbit_object(period, orbitrate)
   -- Period is the duration of the orbit in seconds
   -- Orbitrate is the orbit velocity in radians per second
   local obs = celestia:getobserver()
   local obsframe = obs:getframe()
   local center = obsframe:getrefobject()
   -- If there's no followed object, use the current selection
   if not center then
      center = celestia:getselection()
   end
   if not center then return end
   -- v1 is the vector from the viewer to the center
   -- up is the camera up direction
   -- v2 is normal to both v1 and up
   local now = celestia:gettime()
   local v1 = obs:getposition() - center:getposition(now)
   local distance = v1:length()
   v1 = v1:normalize()
   local up = obs:getorientation():transform(celestia:newvector(0, 1, 0))
   local v2 = v1 ^ up
   v2 = v2:normalize()
   -- Determine orbit angle in radians 
   local orbitangle = period * orbitrate
   -- Orbit in the plane containing v1 and normal to the up direction
   local start = celestia:getscripttime()
   local t = (celestia:getscripttime() - start) / period
   while t < 1 do
      t = (celestia:getscripttime() - start) / period
      local theta = orbitangle * t
      local v = math.cos(theta) * v1 + math.sin(theta) * v2
      obs:setposition(center:getposition() + v * distance)
      obs:lookat(center:getposition(), up)
      wait(0)
   end
end

objectname = celestia:find( <string> )
celestia:select(objectname)
radiansrate = math.rad( <rate> )
orbit_object( <duration>, radiansrate )


Example:
The following example orbits Saturn for 12 seconds.


CEL:

select { object "Sol/Saturn" }
center { }
goto   { time 3 distance 8 up [ 0 1 0 ] upframe "equatorial" }
wait   { duration 3 }
orbit  { axis [ 0 1 0 ] rate 30 duration 12 }


CELX with the 1.6.1 observer:orbit() method:

This equivalent orbits the reference object during about 12 seconds over exactly 12 * 30 = 360 degrees.

objectname = celestia:find("Sol/Saturn" )
celestia:select(objectname)
obs = celestia:getobserver()
obs:center(objectname, 1.0)
wait(1.0)
frame = celestia:newframe("equatorial", objectname)
obs:setframe(frame)
radius = objectname:radius()
distance = ( 8 + 1 ) * radius
obs:gotodistance(objectname, distance, 3.0)
wait(3.0)
duration = 12.0
radiansrate = math.rad( 30.0 )
axis_vector = celestia:newvector( 0, 1, 0 )
orbitangle = duration * radiansrate
orbitsteps = 30 * duration
orbitsteptime = 0.75*duration/orbitsteps
rot = celestia:newrotation(axis_vector, orbitangle/orbitsteps)
for i = 1, orbitsteps do
   obs:orbit(rot)
   wait(orbitsteptime)
end


CELX with the 1.6.1 observer:orbit() method in a function:

This equivalent orbits the reference object during about 12 seconds over exactly 12 * 30 = 360 degrees.

function orbit_object_angle(period, orbitrate, axis)
   local orbitangle = period * orbitrate
   local orbitsteps = 30 * period
   local orbitsteptime = 0.75*period/orbitsteps
   local rot = celestia:newrotation(axis, orbitangle/orbitsteps)
   local obs = celestia:getobserver()
   for i = 1, orbitsteps do
      obs:orbit(rot)
      wait(orbitsteptime)
   end
end

objectname = celestia:find("Sol/Saturn" )
celestia:select(objectname)
obs = celestia:getobserver()
obs:center(objectname, 1.0)
wait(1.0)
frame = celestia:newframe("equatorial", objectname)
obs:setframe(frame)
radius = objectname:radius()
distance = ( 8 + 1 ) * radius
obs:gotodistance(objectname, distance, 3.0)
wait(3.0)
radiansrate = math.rad( 30.0 )
axis_vector = celestia:newvector( 0, 1, 0 )
orbit_object_angle(12.0, radiansrate, axis_vector)


CELX with the 1.6.1 observer:orbit() method:

This equivalent orbits the reference object during exacly 12 seconds over about 12 * 30 = 360 degrees.

objectname = celestia:find("Sol/Saturn" )
celestia:select(objectname)
obs = celestia:getobserver()
obs:center(objectname, 1.0)
wait(1.0)
frame = celestia:newframe("equatorial", objectname)
obs:setframe(frame)
radius = objectname:radius()
distance = ( 8 + 1 ) * radius
obs:gotodistance(objectname, distance, 3.0)
wait(3.0)
duration = 12.0
radiansrate = math.rad( 30.0 )
axis_vector = celestia:newvector( 0, 1, 0 )
orbitangle = duration * radiansrate
orbitsteps = 30 * duration
orbitsteptime = 0.75*duration/orbitsteps
rot = celestia:newrotation(axis_vector, orbitangle/orbitsteps)
t0 = celestia:getscripttime()
while celestia:getscripttime() <= t0 + duration do
   obs:orbit(rot)
   wait(orbitsteptime)
end


CELX with the 1.6.1 observer:orbit() method in a function:

This equivalent orbits the reference object during exacly 12 seconds over about 12 * 30 = 360 degrees.

function orbit_object_time(period, orbitrate, axis)
   local orbitangle = period * orbitrate
   local orbitsteps = 30 * period
   local orbitsteptime = 0.75*period/orbitsteps
   local rot = celestia:newrotation(axis, orbitangle/orbitsteps)
   local obs = celestia:getobserver()
   local t0 = celestia:getscripttime()
   while celestia:getscripttime() <= t0 + period do
      obs:orbit(rot)
      wait(orbitsteptime)
   end
end

objectname = celestia:find("Sol/Saturn" )
celestia:select(objectname)
obs = celestia:getobserver()
obs:center(objectname, 1.0)
wait(1.0)
frame = celestia:newframe("equatorial", objectname)
obs:setframe(frame)
radius = objectname:radius()
distance = ( 8 + 1 ) * radius
obs:gotodistance(objectname, distance, 3.0)
wait(3.0)
radiansrate = math.rad( 30.0 )
axis_vector = celestia:newvector( 0, 1, 0 )
orbit_object_time(12.0, radiansrate, axis_vector)


CELX with an arithmetic sequence of methods:

objectname = celestia:find("Sol/Saturn" )
celestia:select(objectname)
obs = celestia:getobserver()
obs:center(objectname, 1.0)
wait(1.0)
frame = celestia:newframe("equatorial", objectname)
obs:setframe(frame)
radius = objectname:radius()
distance = ( 8 + 1 ) * radius
obs:gotodistance(objectname, distance, 3.0)
wait(3.0)
duration = 12.0
radiansrate = math.rad(30.0)
obs=celestia:getobserver()
now = celestia:gettime()
v1 = obs:getposition() - objectname:getposition(now)
distance = v1:length()
v1 = v1:normalize()
up = obs:getorientation():transform(celestia:newvector(0, 1, 0))
v2 = v1 ^ up
v2 = v2:normalize()
orbitangle = duration * radiansrate
start = celestia:getscripttime()
t = (celestia:getscripttime() - start) / duration
while t < 1 do
   t = (celestia:getscripttime() - start) / duration
   theta = orbitangle * t
   v = math.cos(theta) * v1 + math.sin(theta) * v2
   obs:setposition(objectname:getposition() + v * distance)
   obs:lookat(objectname:getposition(), up)
   wait(0)
end


CELX with an arithmetic sequence of methods in a function:

function orbit_object(period, orbitrate)
   -- Period is the duration of the orbit in seconds
   -- Orbitrate is the orbit velocity in radians per second
   local obs = celestia:getobserver()
   local obsframe = obs:getframe()
   local center = obsframe:getrefobject()
   -- If there's no followed object, use the current selection
   if not center then
      center = celestia:getselection()
   end
   if not center then return end
   -- v1 is the vector from the viewer to the center
   -- up is the camera up direction
   -- v2 is normal to both v1 and up
   -- Orbit in the plane containing v1 and normal to the up direction
   local now = celestia:gettime()
   local v1 = obs:getposition() - center:getposition(now)
   local distance = v1:length()
   v1 = v1:normalize()
   local up = obs:getorientation():transform(celestia:newvector(0, 1, 0))
   local v2 = v1 ^ up
   v2 = v2:normalize()
   local orbitangle = period * orbitrate
   local start = celestia:getscripttime()
   local t = (celestia:getscripttime() - start) / period
   while t < 1 do
      t = (celestia:getscripttime() - start) / period
      local theta = orbitangle * t
      local v = math.cos(theta) * v1 + math.sin(theta) * v2
      obs:setposition(center:getposition() + v * distance)
      obs:lookat(center:getposition(), up)
      wait(0)
   end
end

objectname = celestia:find("Sol/Saturn" )
celestia:select(objectname)
obs = celestia:getobserver()
obs:center(objectname, 1.0)
wait(1.0)
frame = celestia:newframe("equatorial", objectname)
obs:setframe(frame)
radius = objectname:radius()
distance = ( 8 + 1 ) * radius
obs:gotodistance(objectname, distance, 3.0)
wait(3.0)
radiansrate = math.rad(30.0)
orbit_object(12.0, radiansrate)


Back to CEL command index