ScriptedOrbit - referencing the SSC object

All about writing scripts for Celestia in Lua and the .cel system
Avatar
Topic author
Chuft-Captain
Posts: 1779
Joined: 18.12.2005
With us: 18 years 11 months

ScriptedOrbit - referencing the SSC object

Post #1by Chuft-Captain » 19.02.2013, 04:26

Does anyone know if there is a prescribed syntax for a scriptedorbit to refer directly to it's SSC object (so that the script could, for example, modify it's behaviour depending on which object has called it).

For example, given some SSC code similar to this:

Code: Select all

"myobject-01" "Sol/Earth"
{

   OrbitFrame
   {
      . . .
   }

    ScriptedOrbit
    {
        Module "myscripts"
      Function "location01"

      TimeBase 2451545.0
   }
}
   
"myobject-02" "Sol/Earth"
{

   OrbitFrame
   {
      . . .
   }

    ScriptedOrbit
    {
        Module "myscripts"
      Function "location01"

      TimeBase 2451545.0
   }
}


Obviously each instantiation of the script knows which object it's modifying (or it wouldn't work at all), but is there a standard syntax (eg. like "self:object()") to refer to the object of context from within the script?
ie.
What should <ssc-object> be replaced with, in the following...

Code: Select all

function location01(t)
   -- Create a new table
   local orbit = {};
   orbit.params = t;

   orbit.timebase = t.TimeBase

   -- Set the required fields boundingRadius and position; note
   -- that position is actually a function.
   orbit.boundingRadius = 1000
   
   function orbit:position(tjd)
      local    t = (tjd - self.timebase) * 86400;

      local x = 0
      local y = 0
      local z = 0
      
      if <ssc-object>:name() == "myobject-01" then
      . . .
      elseif <ssc-object>:name() == "myobject-02" then
      . . .
      else
      . . .
      end
      
      return x, y, z
   end

   return orbit
end



NOTE: I know that I could pass in the name of the SSC object as part of the parameter list, and then retrieve the object from it's name, but that seems a little messy to me and clutters the SSC needlessly, given that IMO the script should already know it's context.
Last edited by Chuft-Captain on 21.02.2013, 12:12, edited 1 time in total.
"Is a planetary surface the right place for an expanding technological civilization?"
-- Gerard K. O'Neill (1969)

CATALOG SYNTAX HIGHLIGHTING TOOLS LAGRANGE POINTS

Avatar
Fenerit M
Posts: 1880
Joined: 26.03.2007
Age: 17
With us: 17 years 8 months
Location: Thyrrenian sea

Re: ScriptedOrbit - referencing the SSC object

Post #2by Fenerit » 19.02.2013, 05:51

Not sure I've understood correctly... A ScriptedOrbit directive works like a whole; its instantialization is unique from start. What you can do is referring to different functions: i.e in your example the block inside the first If... can be part of function(1) for the first SSC object, while the second block elseif... can be part of function(2) for the second SSC object, instead of referring both SSC objects to the same function. In your example the if...elseif statements seems mutually exclusive, like one function per object.
Never at rest.
Massimo

Avatar
selden
Developer
Posts: 10192
Joined: 04.09.2002
With us: 22 years 2 months
Location: NY, USA

Re: ScriptedOrbit - referencing the SSC object

Post #3by selden » 19.02.2013, 12:37

One technique I use is to explicitly pass the name of the object as one of the arguments of the scripted orbit or scripted rotation function.

A scripted orbit function is a callable entry into a larger module which can contain data and other Lua functions. That module can include global variables which persist as long as Celestia runs and which are shared by all of the scripted orbit functions defined within the module. For an absurdly complex example, take a look at V3 of my Hale Telescope Addon.


Here's an example:

Code: Select all

# display the up-elevator button
"Ctl_button_CL09" "Sol/Earth/200in"
{
   Class "component"
   Mesh "buttonfix.cmod"
   Albedo 0.00001 Radius 0.000025
   OrbitFrame{ BodyFixed { Center "Sol/Earth/200in/_Button_CL09"}}
   ScriptedOrbit  # sets button state & maybe moves it
   {
      Module "hale_control"
      Function "RadioButton"
      ButtonRadio "Ctl_elevator"
      ButtonName "Ctl_button_CL09"
      ButtonMove -0.000006
      ButtonOn  "HRCL" # selectable object name
   }

   BodyFrame { BodyFixed { Center "Sol/Earth/200in/_Button_CL09"}}
   FixedRotation {}
}


and here's the scripted orbit's Lua code. It calls another function which dynamically creates named radio buttons as needed. I'll leave it to you to download the Hale Addon for more details.

Code: Select all

--======================================================
-- ScriptedOrbit function
--======================================================
RadioButton = function (sscvals)

   local orbit = {}
   orbit.params = sscvals
   orbit.boundingRadius = 1e-4

   function orbit:position (tjd)
      return 0, 0,  RadioState(
             self.params.ButtonRadio,
             self.params.ButtonName,
             self.params.ButtonMove,
             self.params.ButtonOff,
             self.params.ButtonOn,
             self.params.InitialState,
             self.params.InitialMove,
             tjd)
   end

return orbit
end


The Addon is available at http://www.lepp.cornell.edu/~seb/celest ... scope.html
Selden

Avatar
Topic author
Chuft-Captain
Posts: 1779
Joined: 18.12.2005
With us: 18 years 11 months

Re: ScriptedOrbit - referencing the SSC object

Post #4by Chuft-Captain » 19.02.2013, 12:44

I think you may have misunderstood, Fenerit.

It would help to have some understanding of what's likely to be happening behind the scenes in the C++ code.
I'll try to explain....

Underlying the "ScriptedOrbit" keyword will be a C++ "class" called (probably) "ScriptedOrbit", which defines the attributes and behavior (methods) of the statement.
At some point in the execution of the underlying C++ code, each individual declaration of a ScriptedOrbit in the SSC (in this example there's just 2 for clarity), results in the "instantiation" of a "concrete" copy of this class in memory (to put it simply, an instance is created) , along with any property values associated with that specific instance.
See: http://en.wikipedia.org/wiki/Instance_%28computer_science%29 to clarify this principle. (It's not the same as "initialization".)

So anyway, back to the issue of determining the SSC object...

My workaround for this would be to add a "RefObj" property to the definition.
Note that each SSC object specifies a different value for this property/parameter:

Code: Select all

"myobject-01" "Sol/Earth"
{

   OrbitFrame
   {
      . . .
   }

    ScriptedOrbit
    {
        Module "myscripts"
      Function "location01"

      TimeBase 2451545.0
      RefObj      "myobject-01"
   }
}
   
"myobject-02" "Sol/Earth"
{

   OrbitFrame
   {
      . . .
   }

    ScriptedOrbit
    {
        Module "myscripts"
      Function "location01"

      TimeBase 2451545.0
      RefObj      "myobject-02"
   }
}


which can then be accessed as follows...

Code: Select all

function location01(t)
   -- Create a new table
   local orbit = {};
   orbit.params = t;

   orbit.timebase = t.TimeBase
   orbit.refobj = t.RefObj

   -- Set the required fields boundingRadius and position; note
   -- that position is actually a function.
   orbit.boundingRadius = 1000
   
   function orbit:position(tjd)
      local    t = (tjd - self.timebase) * 86400;

      local x = 0
      local y = 0
      local z = 0
      
      local owner = celestia:find( self.refobj )
      if owner:name() == "myobject-01" then
      . . .
      elseif owner:name() == "myobject-02" then
      . . .
      else
      . . .
      end
      
      return x, y, z
   end

   return orbit
end


My point is that each C++ instance must already know which Celestia Object declared/called it (because it knows which "Celestia Object" to act upon). Therefore, the additional RefObj parameter should IMO be unnecessary. Instead we should have a LUA method to return the "object" of the SSC body from within the script itself, rather than having to pass in the name of the body in via the RefObj property, and then retrieve the object with a find().

It's this direct access to the Object from within the script, which I was hoping was possible, but I haven't looked at the actual C++ code, so maybe it's a little more abstract.

I hope that makes more sense to you.

CC
Last edited by Chuft-Captain on 22.02.2013, 13:24, edited 4 times in total.
"Is a planetary surface the right place for an expanding technological civilization?"
-- Gerard K. O'Neill (1969)

CATALOG SYNTAX HIGHLIGHTING TOOLS LAGRANGE POINTS

Avatar
Topic author
Chuft-Captain
Posts: 1779
Joined: 18.12.2005
With us: 18 years 11 months

Re: ScriptedOrbit - referencing the SSC object

Post #5by Chuft-Captain » 19.02.2013, 12:55

selden wrote:One technique I use is to explicitly pass the name of the object as one of the arguments of the scripted orbit or scripted rotation function.
Thanks Selden. That is in fact exactly what I've done as a workaround (see my cross-post above), but I still wish it wasn't necessary. :wink:

The whole point of this was to rewrite the Lagrange Points addon so that the Lagrange Point locations are calculated on the fly by the Scripted Orbit, instead of having hard-coded FixedPositions in the SSC. This removes the need to re-generate the SSC definitions whenever masses of solar-system bodies are revised. The addon will now automatically take into account any changes in the known Masses of the Solar System bodies, which are now provided as direct inputs to the addon.

Code: Select all

ReferencePoint   "Mercury-L1" "Sol/Mercury"
{
   Visible   true
   Clickable   true

   OrbitFrame
   {
      TwoVector
      {
         Center   "Sol/Mercury"
         Primary
         {
            Axis "x"
            RelativePosition { Target "Sol" }
         }
         Secondary
         {
            Axis "y"
            RelativeVelocity { Target "Sol" }
         }
      }
   }

   ScriptedOrbit
   {
      Module      "lagrange01"
      Function   "location01"

      TimeBase   2451545.0
      RefObj      "Mercury-L1"
   }
}


Unfortunately though, I'm finding this has a serious impact on frame-rates when there's 470 instances of this scripted orbit all running at the same time (one for each Lagrange Point in the Solar System). :o So, I think I'll have to abandon this idea, and we'll just have to live with the statically calculated Lagrange locations.

Just demonstrates how much slower LUA is than the compiled C++ code. :!:
Last edited by Chuft-Captain on 22.02.2013, 12:42, edited 2 times in total.
"Is a planetary surface the right place for an expanding technological civilization?"
-- Gerard K. O'Neill (1969)

CATALOG SYNTAX HIGHLIGHTING TOOLS LAGRANGE POINTS

Avatar
selden
Developer
Posts: 10192
Joined: 04.09.2002
With us: 22 years 2 months
Location: NY, USA

Re: ScriptedOrbit - referencing the SSC object

Post #6by selden » 19.02.2013, 13:20

My experience suggests that the performance hit isn't so much in the Lua code itself, but in the code which implements the call that invokes the Lua function. So, of course, it becomes more painful as more objects are involved. If the objects are out-of-view, then the functions don't get called. Obviously that condition is hard to meet if you're looking at an over-all view of the solar system.
Selden

Avatar
Fenerit M
Posts: 1880
Joined: 26.03.2007
Age: 17
With us: 17 years 8 months
Location: Thyrrenian sea

Re: ScriptedOrbit - referencing the SSC object

Post #7by Fenerit » 19.02.2013, 20:50

Chuft-Captain wrote:My point is that each instance must somehow know which Celestia Object declared/called it, so that the C++ instance knows which "Celestia Object" to act upon. Therefore, the additional RefObj parameter should be unnecessary.

Maybe now I've understood what you were in search for. Well... inheritances like below never works on my scripts:

Code: Select all

local owner {}
owner = "myobject-01", "myobject-02", ...

owner = celestia:find(self.owner)
if owner:name() == "myobject-01" then
...
elseif
owner:name() == "myobject-02" then
...
end
Never at rest.
Massimo

Avatar
Topic author
Chuft-Captain
Posts: 1779
Joined: 18.12.2005
With us: 18 years 11 months

Re: ScriptedOrbit - referencing the SSC object

Post #8by Chuft-Captain » 20.02.2013, 11:46

selden wrote:My experience suggests that the performance hit isn't so much in the Lua code itself, but in the code which implements the call that invokes the Lua function. So, of course, it becomes more painful as more objects are involved. If the objects are out-of-view, then the functions don't get called. Obviously that condition is hard to meet if you're looking at an over-all view of the solar system.
I'm inclined to agree with you, but I've got other scriptedorbit routines that do a lot more work than this one, for many more objects, and although as expected they have some impact on frame-rates, it's nowhere near the extreme impact that I'm seeing with this one.
This leads me to think there's an issue with one of the celx methods being called in the script itself, one of which, celestia:find(), was an obvious suspect ... as it performs a search.

I've constructed a bit of a benchmark to try and find out the relative expense of various types of operations used in this script, with interesting results.
NOTE that there may well be some internal caching or optimization going on behind the scenes, which may skew the results, and I don't exactly trust the fact that some results are always zero (which may be something wrong in the way I'm testing) but consistently it does seem to suggest that doing a celestia:find() of anything that's not a planet takes a comparitively long time, although as I said, I don't trust the fact that find(planet) seems to almost always return 0, no matter how many calls are made.

Typical results:
log_01.JPG
Last edited by Chuft-Captain on 20.02.2013, 17:25, edited 4 times in total.
"Is a planetary surface the right place for an expanding technological civilization?"
-- Gerard K. O'Neill (1969)

CATALOG SYNTAX HIGHLIGHTING TOOLS LAGRANGE POINTS

Avatar
selden
Developer
Posts: 10192
Joined: 04.09.2002
With us: 22 years 2 months
Location: NY, USA

Re: ScriptedOrbit - referencing the SSC object

Post #9by selden » 20.02.2013, 11:54

I guess I'm not surprised that find can be expensive in some circumstances. :(

Fortunately, if you keep the results in a global table you only have to do it once for each of the objects of interest.
Selden

Avatar
Topic author
Chuft-Captain
Posts: 1779
Joined: 18.12.2005
With us: 18 years 11 months

Re: ScriptedOrbit - referencing the SSC object

Post #10by Chuft-Captain » 20.02.2013, 12:23

I still would have expected that celestia:find() would search the octree(s), which would in theory ensure ~ O(logN) performance.

... However, maybe only static objects (eg, DSO's, stars), and planets, are placed in octrees. This would make sense, as moving objects would require constant maintenance of the octree structure as their location changed.
A celestia:find() of other more numerous orbitals (Moons, spacecraft, etc) would I assume have to resort to a linear search.

Only the DEV's can really confirm these assumptions though.
"Is a planetary surface the right place for an expanding technological civilization?"
-- Gerard K. O'Neill (1969)

CATALOG SYNTAX HIGHLIGHTING TOOLS LAGRANGE POINTS

Avatar
Topic author
Chuft-Captain
Posts: 1779
Joined: 18.12.2005
With us: 18 years 11 months

Re: ScriptedOrbit - referencing the SSC object

Post #11by Chuft-Captain » 20.02.2013, 14:26

Selden,

As mentioned in PM, I think I've gathered some evidence that confirms to some extent my conclusions in the previous post.
Note the FPS and the benchmark results in the 2 cases ...

Solar System populated with various addons (asteroids, spacecraft+components, etc):
log_03.JPG


Solar System devoid of all addons except Lagrange Points:
log_02.JPG
"Is a planetary surface the right place for an expanding technological civilization?"
-- Gerard K. O'Neill (1969)

CATALOG SYNTAX HIGHLIGHTING TOOLS LAGRANGE POINTS


Return to “Scripting”