Runar,
How did you calculate the values that you have?
Usually a ScriptedRotation would use that calculation rather than the values.
Here's a relatively simple example of a ScriptedRotation taken from my Hale Telescope Addon. I like to separate the calculation functions (BridgeRot in this example)
from the Lua ScriptedRotation functions (BridgeRotate in this example).
This is primarily to help me when I'm editing them.
It helps to limit the damage when I make typos.
Debugging Scripted functions is extremely difficult.
The usual symptom is just that they do nothing.
In some cases, when the code structure is invalid,
there will be an error message in Celestia's console output,
but usually there's nothing: the syntax is valid but there's a typo somewhere.
Code: Select all
-- Bridge up/down
BridgeRot = function ( date )
local Angle;
if (date < Bridge.T0)
then Angle = Bridge.Th0
elseif (date < Bridge.T1)
then Angle = Bridge.Th0 + Bridge.V*(date-Bridge.T0)
else Angle = Bridge.Th1
end
return zPi * celestia:newrotation( xAxis, Angle)
end
-- ==========================================================
-- BridgeRotate -- rotate mirror Bridge
BridgeRotateProto = { } -- no args
-- constructor method
function BridgeRotateProto:new(o)
o = o or {}
setmetatable (o, self)
self.__index = self
o.period = 1
return o
end
-- orientation function
function BridgeRotateProto:orientation(tjd)
local qNow = BridgeRot( tjd )
return qNow.w, qNow.x, qNow.y, qNow.z
end
-- create new rotation object
function BridgeRotate(sscvals)
return BridgeRotateProto:new(sscvals)
end
Using this code,
the telescope's Coude bridge stays at its initial orientation (Bridge.Th0)
while the current date is less than the time when it's supposed to start moving,
moves while the current date is less than the time when it's supposed to stop moving,
and stays at the final orienation (Bridge.Th1) otherwise,
i.e. while the current date is greater than or equal to the time when it's supposed to stop moving.
Here's the Bridge's SSC declaration:
Code: Select all
# the arch which carries a flat to divert light back toward the yoke's axis
# when the direct path is blocked
"hale_coude_bridge" "Sol/Earth/hale_telescope" {
Mesh "hale_coude_bridgefix.cmod"
Radius 0.03
OrbitFrame { BodyFixed { Center "Sol/Earth/hale_yoke" } }
FixedPosition [0 0.001875 -0.00731]
BodyFrame { BodyFixed { Center "Sol/Earth/hale_yoke" } }
ScriptedRotation
{
Module "hale_control"
Function "BridgeRotate"
}
Albedo 0.00001
}
Background for the SSC declaration:
The Bridge is carried around by the telescope's Yoke, which is defined elsewhere.
The ScriptedRotation "BridgeRotate" only has to worry about how the bridge turns relative to the yoke.
Background for the ScriptedRotation:
The current orientation angle of the bridge is calculated from its initial orientation angle and its velocity using the formula taught in introductory physics:
x = x0 + v*t
(the current position of a body is the body's initial position plus
the velocity it's moving multiplied by the amount of time that it's been moving.)
The "coude bridge" is rotating in a single plane around its X axis.
The values used in the calculation are globals defined elsewhere.
Bridge.T0 is when it started moving
Bridge.Th0 is its starting orientation angle
Bridge.V is its rotational velocity
Bridge.Th1 is its final orientation angle.
I precalculated the velocity from Th0 and Th1.
I decided the values for Th0 and Th1 in advance by knowing where the bridge had to be in order to reflect the light in the correct direction.
The time is arbitrary: it's how long I wanted the movement to take.
It happens to be 10 seconds, which is unrealistically fast,
but is an amount of time that I think people will be willing to watch things move.
V = distance/time = (Th1-Th0)/(duration of motion)
(This movement function is a simplification, since there really should be accelerations at the start and end of the bridge's movement.
I decided not to include them since nobody would notice.)
zPi is a quaternion defining a 180 rotational offset around the Z axis to compensate for an offset in the model's orientation.
You may or may not need to include an offset like this depending on how your models are designed.
xAxis a vector defining the direction of the X axis, which is what the Bridge rotates around.
Here are the definitions I used for the globals.
You'll want to determine yours some other way, I'm sure, and should structure your code differently, too.
I'm not a very good OO programmer: I'm an old Fortran programmer.
Code: Select all
-- initial global values
second = 0.11574074051168E-04
-- arbitrary duration for all movements. For some it's too slow, for others it's too
fast.
dT = 10*second
-- axes and fixed rotations around them
xAxis = celestia:newvector( 1, 0, 0)
yAxis = celestia:newvector( 0, 1, 0)
zAxis = celestia:newvector( 0, 0, 1)
xPi = celestia:newrotation( xAxis, math.pi)
yPi = celestia:newrotation( yAxis, math.pi)
yR0 = celestia:newrotation( yAxis, 0)
zPi = celestia:newrotation( zAxis, math.pi)
Bridge = {}
Bridge.T0 = 1e18
Bridge.T1 = 0
Bridge.Down = math.rad(90.0)-math.rad(180)
Bridge.Up = math.rad(-20) -math.rad(180)
Bridge.Th1 = Bridge.Up
Bridge.Th0 = Bridge.Down
Bridge.V = 0
RaiseBridge = function (mydate)
Bridge.Th0 = Bridge.Down
Bridge.Th1 = Bridge.Up
Bridge.V = (Bridge.Th1 - Bridge.Th0)/ dT
Bridge.T0 = mydate
Bridge.T1 = mydate+dT
end
LowerBridge = function (mydate)
Bridge.Th0 = Bridge.Up
Bridge.Th1 = Bridge.Down
Bridge.V = (Bridge.Th1 - Bridge.Th0)/ dT
Bridge.T0 = mydate
Bridge.T1 = mydate+dT
end
For my functions, the starting time (mydate) is learned at runtme when the user types a command. If the timings of your objects' motions are predetermined, then you could code them in as constants or pass them as arguments to the ScriptedFunction.