These notes were first written during the transition of Celestia from v1.2.4 to v1.2.5. Notes written later include a version number. For example, those written during the transition from v1.2.5 to v1.2.6 have "v1.2.6" associated with them. Most of them indicate features that are (or will be) new in the indicated version. If a section of notes does not include a recent version number, then most likely that's because I haven't reexamined the associated code since the indicated version, not because there were no changes.
Since Celestia is constantly undergoing rapid development, additional features may be available which are not mentioned here.
Back to Contents.
When Celestia starts, it reads the file "celestia.cfg" from the same directory where Celestia's executable resides. It specifies the names of some of Celestia's other database files.
line breaks are irrelevant must start with "Configuration {" and end with "}" FaintestVisibleMagnitude number (default = 6.0) FavoritesFile "favorites.cel" DestinationFile "guide.cel" InitScript "start.cel" DemoScript "demo.cel" AsterismsFile "data/asterisms.dat" BoundariesFile "data/boundaries.dat" DeepSkyCatalog "data/deepsky.dsc" StarDatabase "data/stars.dat" StarNameDatabase "data/starnames.dat" Font "helvbold12.txf" LabelFont "helv10.txf" [editorial: this is much too small] TitleFont "sansbold20.txf" LogoTexture "logo.png" RotateAcceleration number (default = 120.0) SolarSystemCatalogs [ "data/solarsys.ssc" "data/extrasolar.ssc" ] (must be an array of strings) ExtrasDirectories [ "extras" ] (must be an array or string) # Specify multiple extras directories like this: # ExtrasDirectories [ "extras" "rassilon" ] StarCatalogCrossReferences [ "data/hdxref.dat" ] (must be an array of strings) LabelledStars [strings] (must be an array of strings) (e.g. "Sirius" ) IgnoreGLExtensions [string: extension name] (must be an array of strings) (e.g. "GL_ARB_vertex_program" )
Note this change introduced in 1.2.5:
"ExtrasDirectories -- not just directory.
Add-on extras directories can contain all types of Celestia files,
including those which have traditionally gone into
/data/
and /models/
.
Back to Contents.
Writes to registry:
Back to Contents.
Back to Contents.
Guide.cel
,
Object components:
Name string
Target string
Description string
Distance number (default=0.0)
DistanceUnits string
Back to Contents.
Back to Contents.
Back to Contents.
Menu_ShowGalaxies = 2001, Menu_ShowOrbits = 2002, Menu_ShowConstellations = 2003, Menu_ShowAtmospheres = 2004, Menu_PlanetLabels = 2005, Menu_ShowClouds = 2006, Menu_ShowCelestialSphere = 2007, Menu_ShowNightSideMaps = 2008, Menu_MoonLabels = 2009, Menu_AsteroidLabels = 2010, Menu_StarLabels = 2011, Menu_GalaxyLabels = 2012, Menu_ConstellationLabels = 2013, Menu_PixelShaders = 2014, Menu_VertexShaders = 2015, Menu_ShowLocTime = 2016, Menu_ShowEclipseShadows = 2017, Menu_ShowStarsAsPoints = 2018, Menu_CraftLabels = 2019, Menu_ShowBoundaries = 2020, Menu_AntiAlias = 2021, Menu_AutoMag = 2022, Menu_ShowCometTails = 2023,
Back to Contents.
Here the keywords are in bold
.CEL
file,
command.cpp
)
// The geographic coordinate system has an origin at the center of the // body, y-axis parallel to the rotation axis, x-axis through the prime // meridian, and z-axis at a right angle the xy plane. An object with // constant geographic coordinates will thus remain fixed with respect // to a point on the surface of the body.
gotoloc { time 2 x "AAAAAMCrktOdILb5/////w" y "CkxgAADEXts7E7HX/////w" z "VcpQAAAAAAAAAMIy/////w" ow 0.090610 ox -0.494683 oy 0.860207 oz -0.084397 }
setposition { x "AAAAAMCrktOdILb5/////w" y "CkxgAADEXts7E7HX/////w" z "VcpQAAAAAAAAAMIy/////w" }
setorientation { ow 0.090610 ox -0.494683 oy 0.860207 oz -0.084397 }
multiple flags can be specified within a single set of quotes
(") when separated by a vertical bar (|)
NOTE:
"pointstars" has been eliminated
multiple flags can be specified within a single set of quotes (") when separated by a vertical bar (|)
Implemented in / celestia / celestia / src / celengine / command.cpp
July 17, 2006 (Posted to the Celestia Web Forum after 1.4.1 final, before 1.5.0)
A while ago, I added new event handling to Celestia's celx scripting system. It will be enabled in the next prerelease. Among other things, it will let you write a script that replaces Celestia's default keyboard handling with behavior of the script author's choice. There are two new functions added on the celestia object: registereventhandler and geteventhandler. registereventhandler takes two parameters: a string specifying the event type and the event handler. An event handler is a function that accepts a single table parameter and returns a boolean indicating whether or not it handled the event. If no event handler is registered, or if the registered event handler returns false, Celestia reverts to the default behavior for that event.
Here's a sample celx script that creates a keyboard handler:
-- A sample keyboard handling function function showmessage() celestia:flash("Key pressed") end -- The table mapping key names to handlers keyhandlers = { p = showmessage, q = showmessage, } function handlekey(k) -- k is a table containing the event properties; in this simple sample, -- we're only interested in char, the name of the key that was pressed. handler = keyhandlers[k.char] if (handler ~= nil) then handler() return true else return false end end
This sample binds the keys p and q to the handler showmessage(). The bindings will remain until either Celestia is restarted or another script is run to unbind them.
Here's a useful little handler function that I wrote to toggle cloud shadows on and off, because switching them on and off is not yet built into Celestia.
function togglecloudshadows() t = celestia:getrenderflags() celestia:setrenderflags{cloudshadows = not t.cloudshadows} end
There are also mouseup, mousedown, and tick events. I'll post more information about them soon.
--Chris
Back to Contents.
.SSC
file,
Implemented in / celestia / celestia / src / celengine / solarsys.cpp
Location data:
Surface data:
As posted to the developers' mailing list by Chris:
AltSurface <alt surface name> <object>
{
... surface properties ...
}
The surface properties are: Color, HazeColor, HazeDensity, SpecularColor, SpecularPower, Texture, BumpMap, NightTexture, SpecularTexture, NormalMap, OverlayTexture, BumpHeight, BlendTexture (deprecated), Emissive, CompressTexture. Whatever you do with a normal surface, you can do with an alternate surface. Since alternate surfaces are specified outside object definitions, add-ons can contain alternate surface definitions for objects in the base distribution. (thanks for the suggestion Christophe!)
Here's an example of a limit of knowledge surface for Pluto:
For the Mercury and Uranian satellites, it will be advantageous to use small, easily compressed mask textures for limit of knowledge surfaces. Here's an example:
AltSurface "limit of knowledge" "Sol/Pluto"
{
Texture "pluto-lok.jpg"
}
AltSurface "limit of knowledge" "Sol/Uranus/Ariel" { Texture "ariel.jpg" OverlayTexture "ariel-lok-mask.png" }
The general mechanism for selecting a surface is via the right-click context menu (Ctrl-click on a Mac). It's only implemented for Windows right now because of the small amount of platform-specific GUI code. The other method of selecting an alternate surface is specific to the limit of knowledge surfaces described in the Pluto discussion: pressing + toggles between normal and limit of knowledge surfaces. The limit of knowledge surface isn't special--it's just a standard name, nothing more. This selection method should work automatically on OS X and Linux. --Chris
orbit specification:
See http://cvs.sourceforge.net/viewcvs.py/celestia/celestia/src/celengine/orbit.cpp?rev=1.11&view=markup
Quote from comments on the Celestia forum:
Each row in a .xyz file is a Julian date followed by a Cartesian
coordinate. The units of the coordinates are kilometers. The
coordinate system is astrocentric; in our Solar System, this means
that the center of the Sun is at (0, 0, 0). The xy plane is the
ecliptic plane of the star system at the reference epoch J2000.0; in
our Solar System, this is the Earth's orbital plane on Jan 1, 2000.
The positive z axis is perpendicular to this plane in the directional
sense of Earth's north pole. The x axis points from the Sun to Earth's
ascending node, and the y axis completes the right handed coordinate
system.
[...]
What I said was actually not quite correct . . . The origin is the
center of the parent object, whether it's a star or a planet. If the
parent is a planet, the +z axis is the planet's north pole and the xy
plane is the planet's equatorial plane at the reference epoch J2000.
The x axis points at the ascending node of the equatorial plane on the
ecliptic.
The good thing is that these are exactly the same conventions used by JPL's Horizons system by default, so very little processing of Horizons generated ephemerides is necessary. For Sun orbiting objects, just select a center of @10 (Sun), vector output, and eclip for the reference plane.
--Chris
= 2 * pi / (mean motion)
mean motion being defined for hyperbolic orbits as well as
elliptical.
rotation elements:
misc object information:
winmain.cpp
)
planet surface data:
Added 8Aug06:
example for Earth
# ------------------- Mie 0.001 MieAsymmetry -0.15 Rayleigh [ 0.001 0.0025 0.006 ] Absorption [ 0 0 0 ] MieScaleHeight 12 # --------------------
I've implemented the Lunar-Lambert (aka Buratti) photometric model for Celestia and checked the code into CVS. This is a linear combination of the Lambert and Lommel-Seeliger models: (1 - k) * Lambert() + k * LommelSeeliger() The value of k is controlled via the new LunarLambert field for .ssc files. Setting it to 0 (the default) indicates a purely Lambertian surface, which is what Celestia has been using for every object (modulo the specular term.) Adding the following line for the Moon will give it a much more realistic appearance:
LunarLambert 1.0
You''ll see a much sharper crescent phase and no limb darkening at a 0 degree phase angle. There's much research to be done to figure out what value is appropriate for other solar system bodies.
--Chris
For more background on simulating atmospheric scattering in computer graphics, you can have a look at this paper by Tomoyuki Nishita:
http://nis-lab.is.s.u-tokyo.ac.jp/~nis/cdrom/sig93_nis.pdf
The code in Celestia is based upon this paper, though I've had to make some simplifications to make it fast enough for real-time. I'm still working on refining the code. The problem with skies being too dark at the zenith is one thing I'm trying to address. Another problem is that my approximations don't work so well with very thick atmospheres. I'll be able to overcome these limitations with some more effort (and hopefully not too much additional calculation in Celestia.)
The old atmosphere parameters--sky, lower, upper, and sunset colors--are ignored when the new atmosphere code is enabled. The new model is enabled for a model if the MieScaleHeight is set to something other than zero. I'll do something else for 1.5.0 final, possibly enabling new atmospheres for everything and having Celestia automatically convert the old parameters. Or rather, approximately convert them, since the two models are so different there's no way the new model can be made to give identical results to the old one.
I guess I should also mention that HazeColor isn't used when new
atmospheres are enabled. HazeColor is a hack that's no longer necessary
with physically based atmosphere modeling.
--Chris
Starting with Celestia v1.3.2, object definitions within an Addon's SSC files may have one of the three prefixes
"Add" just adds this new object definition to Celestia's database. This is the default. It's the same as Celestia has always done.
"Replace" deletes the preexisting object that has the same name as this object and inserts this new definition in its place.
"Modify" replaces individual declarations within the existing object of the same name by whatever declarations are mentioned in this new object definition.
These three options all assume that only one object already exists with the same name. If more than one object with the same name have been created with Add, then the results of Replace and Modify are unpredictable.
In other words, you can use following Addon SSC definition to put rings around Jupiter:
Modify "Jupiter" "Sol" { Rings { Inner 74500 Outer 140220 Texture "jupiter-rings-20040830.png" } }Of course, you'd want to specify different values for Inner and Outer and Texture.
Date: Mon, 12 Jul 2004 11:26:03 -0700 (PDT) From: Chris LaurelSubject: Re: SourceForge mailing list problem [Note: this replaces the "Mode" syntax briefly defined by Harald's update described below. ...s.] I added new syntax to the solar system loader for giving the disposition of an object definition. The Mode field is no more, and the disposition should now appear in front of the object type. For example: Replace "Earth" "Sol" { ... } You can also provide a disposition for location and alternate surface definitions: Replace Location "Seattle" "Sol/Earth" { ... } However, the only disposition for Locations and AltSurfaces that is currently supported more than just syntactically is the default, Add. I found a couple other small bugs too. Even when no rotation period is given in an Override definition, the object's rotation rate is set back to the default synchronous rotation. I understand what's going on in the code, but haven't fixed the problem yet. Override also seems to delete all child objects of the original. This seems bad . . .
Date: Wed, 30 Jun 2004 11:50:41 +0200 From: Harald SchmidtSubject: [Celestia-developers] Adding Add/Replace/Override for ssc-files I've implemented a change in the way ssc-files are loaded. This has been discussed some time ago, in this thread: http://www.shatters.net/forum/viewtopic.php?t=4300 Summary: When an object is defined twice, Celestia will create two objects with the same name. This makes it impossible to reliable change or replace default objects by files in extras. Now you can have a "Mode" line in the definition of an object. [Note: this syntax has been changed. See above. ...s.] When using 'Mode "Replace"' Celestia will replace an already existing object with the same name instead of adding a second one. Or you can use 'Mode "Override"' and only change a few settings, keeping the already existing object. Example: Putting this into a file in extras will change Earth's radius to 1000km. ------ "Earth" "Sol" { Mode "Override" Radius 1000 } ------ This can also be used to replace a default texture by one in extras, etc. The default Mode is "Add", which is the same as the current behaviour, there should be no change at all with existing ssc-files - IMHO "Replace" would be better, but not backward compatible. Replace still needs a little bit of work: this changes the position of an object, i.e. when using Replace with Earth, Earth will no longer be the third planet. As a small sideeffect of this change, the mass-field in bodies is now set. Please check if your existing ssc-files work as expected. Harald
Quoted from a posting to the developer's list:
I checked in an implementation of this orbit barycenters for ssc objects. It's effectively the same as using an invisible object, except that it avoids the UI and compatibility issues that I described in my message. It's also more consistent with the way orbits work for stars.
SSC objects get a new field called OrbitBarycenter, which sets the origin for the orbit. By default, the parent object is also the OrbitBarycenter. It is not permitted to set the OrbitBarycenter to an object in another star system. The SSC file read will generate an error and skip the object if you attempt it.
There is a new type of SSC object called a Barycenter. It can have any of the usual orbit types: EllipticalOrbit, SampledOrbit, or CustomOrbit. It may also have an OrbitBarycenter, which again defaults to the parent object. All other fields are ignored.
Here's how a barycentric definition of the Pluto-Charon system looks:
Barycenter "Pluto-Charon" "Sol" ***OBSOLETE*** { CustomOrbit "pluto" } "Pluto" "Sol" { Texture "pluto-lok.*" SpecularTexture "pluto-lok-spec.*" SpecularColor [ 0.135 0.12 0.08 ] SpecularPower 9.5 Radius 1151 OrbitBarycenter "Sol/Pluto-Charon" ***OBSOLETE*** EllipticalOrbit { Period 6.387246 SemiMajorAxis 1499 Eccentricity 0.0002 Inclination 115.602 AscendingNode 228.328 ArgOfPericenter 47.314 MeanAnomaly 93.440 } RotationPeriod 153.293904 Obliquity 115.60 EquatorAscendingNode 228.34 RotationOffset 320.75 Albedo 0.55 } "Charon" "Sol/Pluto" { Texture "charon-lok.*" SpecularTexture "charon-lok-spec.*" SpecularColor [ 0.135 0.12 0.08 ] SpecularPower 9.5 Radius 593 InfoURL "http://www.nineplanets.org/pluto.html#Charon" OrbitBarycenter "Sol/Pluto-Charon" ***OBSOLETE*** EllipticalOrbit { Period 6.3872304 SemiMajorAxis 17906 Eccentricity 0.0002 Inclination 115.602 AscendingNode 228.328 ArgOfPericenter 227.314 MeanAnomaly 93.440 } RotationPeriod 153.293904 Obliquity 1.0 EquatorAscendingNode 287.6 RotationOffset 213.3 Albedo 0.35 }
OrbitBarycenters are working quite well now. The only problems that I
currently know of with OrbitBarycenter is that the orbit rendering
code still always uses the position of the parent object as the origin
of the orbit. I will fix that tomorrow.
--Chris
Assuming that the orbits are identical, these two objects will be in exactly the same position:
"Spice_Saturn_1" "Sol/Spice_Sun/Spice_Saturn_Barycenter" { ... } "Spice_Saturn_2" "Sol" { OrbitBarycenter "Sol/Spice_Sun/Spice_Saturn_Barycenter" ... }
Modify "Saturn" "Sol" { OrbitBarycenter "Sol/SolarSystemBarycenter" SampledOrbit "barycentric-saturn.xyz" }
This allows you to redefine Saturn with an orbit referred to the solar
system barycenter without having to modify the name hierarchy. Scripts
and cel:// URLs that refer to "Sol/Saturn" will still work. Separating
the name hierarchy and orbit hierarchy is the reason for the existence
of OrbitBarycenter.
--Chris
I just added support for alternate orbit reference planes. The reference plane for an orbit may be set in an ssc file with the new field OrbitReferencePlane. Currently, just two are supported: equator (the default, and the only option prior to my change), and "ecliptic" (which indicates the J2000.0 ecliptic, not the ecliptic of date.)
It's more convenient to specify the orbits of some satellites relative to the ecliptic rather than the equatorial plane of the object they orbit. For example, JPL's lunar ephemeris is referred to the ICRF and not the Earth's equatorial plane.
The syntax is:
where string is either "ecliptic
" or "equatorial
" (for now)
--Chris
I've checked in support for SPICE in Celestia. Consider this preliminary, mostly a proof of concept so that I can talk about SPICE support in my presentation at the Astrodynamics conference. I had to make sure that integrating SPICE was really as easy as it appeared. And . . . it was! This is one of the easiest to use and best documented software libraries I've ever worked with. The documentation is comprehensive and very easy to read--a lot of it is worthwhile reading even if you're not writing code.
Here's how a SPICE orbit appears in an ssc file:
SpiceOrbit { Kernel "de403_2000-2020.bsp" Target "Pluto Barycenter" Origin "Sun" BoundingRadius 40 Period 248.0 Beginning ... Ending ... }
Note: Beginning and Ending declarations are now required. Their times must be within the time boundaries specified within the SPICE kernel. ...s.
The Kernel field is the name of a SPICE kernel file containing
ephemeris data. There's a repository of SPICE kernels here:
http://www.gps.caltech.edu/~marsdata/req/naif_ids.html
The reference plane for SpiceOrbits is always the J2000 ecliptic. For
moons, make sure that the OrbitReferencePlane is set to "ecliptic"
The BoundingRadius of the orbit needs to be supplied in order for
culling to work. As far as I can tell, there's no way to extract this
from the SPICE kernel file. Period is optional; it's used by Celestia
only for orbit path rendering. If it's set to zero or not given at
all, the orbit is assumed to be an aperiodic trajectory. The units for
BoundingRadius and Period are AU and years for bodies that directly
orbit a star, and kilometers and Earth solar days for other bodies.
The switch in units is for consistency with other Celestia orbits--I
wish I hadn't used two different unit systems in ssc files, but it's a
bit late to go back now.
Specifying a period for the spice orbit will cause just one orbit of
an object to get rendered. Other than being a hint for orbit path
rendering, the Period field has no effect. For example:
The current implementation should not be considered final, and I
welcome suggestions for improvements to the SPICE orbit ssc
definition.
Note: SPICE is no longer subject to ITAR. Celestia v1.5.0
now includes Spice support by default. ...s.
By default, Celestia builds without SPICE support. To enable it in
Windows, uncomment this line in src/winbuild.mak:
The required library for Windows and include files can be found here:
http://www.shatters.net/~claurel/celestia/spice/spice-win32.zip
Just unpack the file into your base Celestia build directory, fix the
Makefile, and you're ready to go . . . I haven't modified the Linux
or MacOS X Makefiles, but I imagine this should be straightforward.
There's also a simple example with SPICE versions of Mercury, Uranus, and Pluto:
http://www.shatters.net/~claurel/celestia/spice/spicetest.zip
The positions computed by SPICE match the VSOP87 calculated orbits
very closely in the timespan covered by the ephemeris. I will soon try
some more challenging cases involving spacecraft flybys.
ftp://naif.jpl.nasa.gov/pub/naif/
SpiceOrbit
{
Kernel "050825R_SCPSE_05186_05205.bsp"
Target "601"
Origin "6"
BoundingRadius 1e10
Period 0.9424218
Beginning ...
Ending ...
}
SPICE=enable
--Chris
I just checked in a change that requires Beginning and Ending fields to define the valid range of a SPICE orbit. I don't really like this very much--Beginning and Ending also need to be specified for the body that uses the SPICE orbit. Unfortunately, I'm not having much luck getting SPICE to tell me what the valid range of its data, and this data really has to be in the Celestia orbit structure.
I'm still trying to figure out something better to do . . . One possibility might be to make objects use the valid range of their orbits as their default beginning/ending. This would make it unnecessary to specify Beginning/Ending for both objects and the SPICE orbits. It would also be nice for bodies that use xyz orbits--the lifetime would automatically be set to the time span covered by the xyz file (though this could still be overridden in the body definition.) --Chris
This is expected behavior, because you're actually using two different time scales.
When you use the Set Time dialog box, you're entering the UTC time and date, whereas xyz files use barycentric dynamical time (TDB). TDB is the time measured by a clock at the solar system barycenter. It differs from Terrestrial Time (TT)--the time measured by a clock on the Earth--because of relativistic effects, but the difference between the two scales is always less than 0.002 seconds. They can be considered equivalent for most add-on development. TT is ahead of International Atomic Time (TAI) by constant factor of 32.184 seconds. And finally, the occasional insertion of leap seconds means that UTC differs from TAI by some integer number of seconds. The most recent leap second occurred at 23:59:60 on December 31, 2005 and made UTC 33 seconds behind TAI.
To briefly summarize the most important information:
TT = TAI + 32.184
TAI = UTC + <leap second count>
Thus:
TT = UTC + 32.184 + <leap second count>
UTC is used in the Celestia's Set Time dialog and it's also the time
displayed in the upper right of the screen. Everywhere else, the time
scale is TDB: xyz files, beginning, ending, and epoch times in ssc
files. Because UTC Julian day numbers can't be used for events that
occur during a leap second, it's important that the TDB scale be used
for xyz files. You could make a case that date strings in ssc files be
implicitly in UTC. However, that would be inconsistent with how Julian
day numbers are treated. What I'd rather do is update the date parser
to use the UTC time scale when it sees the suffic "UTC" at the end of
a date string.
--Chris
>
> This time I'm sure I'm not confused :-)
>
> Celestia's on-screen time is slow by 1 minute.
>
> I looked up the julian date for 11-Sep-1975 16:53.
> It's 2442667.203472222
> I used that time in some xyz files.
> When I used Celestia's Set Time menu option to set the simulation time
> to 11-Sep-1975 16:53, the actions displayed
> by those xyz files were already half-way done.
> When I recorded a URL at that time, the timestamp in the URL was
> one minute later than was shown on the screen.
>
> When I used the URL, the time shown on the screen was one minute earlier
> than the time in the URL.
>
> I have not tried to find some astronomical event that Celestia
> would show to that accuracy.
>
> s.
See also http://en.wikibooks.org/wiki/Celestia/JPL_Ephemerides
On 10/15/06, Selden E Ball Jrwrote: > Chris wrote, quoting me, > > > > This intersection is seen using Celestia's VSOP87 ephemeris and using > > > Swingby's default ephemeris, not Swingby's optional DE405 ephemeris. > > > Have you tried using DE405/406 support in Celestia? > > No, I haven't. > > Unfortunately, it isn't obvious to me how to specify DE405 > ephemerides to Celestia. I seem to recall that it's a different > CustomOrbit string. > > I also had the impression that one or more external ephemeris files > would be needed. Is that what you're describing below? > Where would I get them? >
Yes, you do need external ephemeris files. They are available here:
ftp://ssd.jpl.nasa.gov/pub/eph/export/unix/
The ones named unxpNNNN.406 are probably of most interest. They contain 300 year chunks of the DE406 ephemeris beginning at year NNNN. There's a utility on the same site that will merge multiple chunks of the ephemeris so that you can create a single file with the entire -3000 to 3000 span covered by DE406. DE405 is a larger and slightly more precise ephemeris, but DE406 should be more than accurate enough for Celestia. The differences are explained in this document:
ftp://ssd.jpl.nasa.gov/pub/eph/export/README.txt
To use JPL ephemeris, you need to place in your data directory and name it 'jpleph.dat'. Then, modify the CustomOrbits of the planets to use the JPL ephemeris instead of the default VSOP87 orbits. I just added some new names for the JPL ephemeris custom orbits to make their usage clearer. Here are the options:
Heliocentric orbits for the planets:
jpl-mercury-sun
jpl-venus-sun
jpl-earth-sun
jpl-mars-sun
jpl-jupiter-sun
jpl-saturn-sun
jpl-uranus-sun
jpl-neptune-sun
jpl-pluto-sun
Planet orbits relative to the solar system barycenter:
jpl-mercury-ssb
jpl-venus-ssb
jpl-earth-ssb
jpl-mars-ssb
jpl-jupiter-ssb
jpl-saturn-ssb
jpl-uranus-ssb
jpl-neptune-ssb
jpl-pluto-ssb
Position of the Earth-Moon barycenter relative to Sun and SSB:
jpl-emb-sun
jpl-emb-ssb
Position of the Earth relative to the Earth-Moon barycenter:
jpl-earth-emb
Geocentric and barycentric position of the Moon:
jpl-moon-earth
jpl-moon-emb
Position of the Sun relative to the SSB:
jpl-sun-ssb
I think that the above list covers all interesting configurations for describing the solar system in Celestia. In addition to adding the new names, I fixed a couple nasty bugs: the position of the Moon was wrong, and the CustomOrbit called 'jpl-earth' was actually the position of the Earth-Moon barycenter.
I verified two of the orbits (Earth and Uranus) against Horizons, which uses the DE405 ephemeris for planet positions. Celestia agrees almost exactly--as far as I can see, the only differences are due to the fact that when I did the comparison, I just paused the time at the input value I used for Horizons and didn't bother matching fractions of a second.
> And are they for the planets or the associated barycenters? > The names in jpleph.h seem to imply planets, but the numbering system > could be taken to imply barycenters.
The positions computed for jpl-mars, jpl-jupiter, jpl-saturn, jpl-uranus, jpl-neptune, and jpl-pluto are the barycenters of the systems. Venus and Mercury have no moons, so the barycenters are exactly the center of the planets. Although Mars does have moons, they're so tiny relative to Mars that Horizons appears to treat the Mars system barycenter and the center of Mars as identical. There's a slight inconsistency with jpl-earth: it gives the position of Earth. If you want the Earth-Moon barycenter, then use jpl-emb. I was curious as to how much the positions of the giant planets deviated from the system barycenters. A rough calculation for Uranus and Titania gives ~20km. I haven't done any other calculations; my guess is that Triton displaces Neptune much more than any of the giant planet moons.
> > Yesterday, I > > tested it against a SPICE orbit using the de406s.bsp kernel, and got > > positions that agreed within a kilometer. I think that the problems > > that we used to have with JPL ephemeris support were caused by > > misunderstanding about UTC versus the TDB time scale. > > That was my assumption, too, as soon as you started describing > the details of how the time changes affected things. > That's a relief!
When checking the positions against Horizons in 2006, make sure that the UTC time displayed by Celestia is 65 seconds behind the Horizons's CT time. Here's a script I use to check positions:
-- script to rebind the x key to display the heliocentric position of the selected object km = 9460730.4725808 function nextpart() local sel = celestia:getselection() local sun = celestia:find("Sol") local v = (sel:getposition() - sun:getposition()) * km celestia:flash("Position of " .. sel:name() .. ": " .. v.x .. ", " .. v.y .. ", " .. v.z, 20) end keyhandlers = { x = nextpart } function handlekey(k) handler = keyhandlers[k.char] if (handler ~= nil) then handler() return true else return false end end celestia:registereventhandler("key", handlekey)
I've almost completed my work on rotation models and want to give a quick overview of how they'll work internally and in ssc files. Suggestions are most welcome.
First of all, the old way of describing the rotation of a planet in an ssc file will still be supported. The alternative is to break almost every single add-on out there. The new scheme should be preferred, however.
An object that rotates about a fixed axis at a fixed rate is described by a UniformRotation:
UniformRotation { PeriodMeridianAngle Epoch Inclination AscendingNode }
All of the fields in a UniformRotation correspond to existing rotation fields:
Period => RotationPeriod
MeridianAngle => RotationOffset
Epoch => RotationEpoch
Inclination => Obliquity
AscendingNode => EquatorAscendingNode
The 'Rotation' prefix in front of most of the current field names is redundant when they appear inside a UniformRotation block. I changed Obliquity to Inclination because obliquity refers specifically to the angle between a planet's rotation axis and the normal to its orbital plane, whereas in Celestia the value is the angle between the rotation axis and the normal to a reference plane that is in general not planet's orbital plane.
There are three other rotation types currently defined:
PrecessingRotation
Same fields as a UniformRotation, but with a precession axis and period. I haven't decided what units to use for the precession; I'm not too happy with the degrees/day that is used now. I think that a period is a more natural and consistent way than a rate to describe the length of the precession cycle.
CustomRotation "name"
Bulitin rotation models. The most important one will be a detailed precession/nutation theory for Earth. Perhaps BuiltinRotation would be a better name, though it's not consistent with CustomOrbit.
SampledOrientation "samples.q"
Refers to a file of quaternions, potentially unevenly spaced in time like the positions in an .xyz file. These will primarily be used for specifying the attitude of spacecraft--they're the main reason I did all this work on rotations.
A big benefit to all this work is that the handling of orientation within Celestia is now *much* cleaner. For example there were about five different places where the rotation about the primary axis was calculated; now, it's done in just a single place. The code will be even better once I've completed work on reference frames.
--Chris
Date: Wed, 18 Oct 2006 02:50:14 -0700
From: Chris Laurel
Subject: [Celestia-developers] Rotation models update
I'm not done yet, but I've made a lot of progress with rotation models . . .
Here's what's working:
UniformRotation
PrecessingRotation
SampledOrientation
Backward compatibility with Celestia 1.4.1 rotation parameters
A few specifics . . . UniformRotation works exactly as I described in my message yesterday. PrecessingRotation has all of the fields of UniformRotation plus PrecessionPeriod, which is in units of Julian years. There's still not an option to set the precession axis--I'm trying to figure out the most sensible and standard (hopefully they're the same) way to describe it.
SampledOrientation works much like SampledOrbit. For example:
SampledOrientation "test.q"
Celestia will search for test.q in the add-on data directory first,
then the main data directory. The file itself is a time-stamped list
of quaternions stored as ASCII text. Here's my test file:
2454025 1 0 0 0
2454026 0 1 0 0
2454027 0 0 1 0
2454028 1 0 0 0
2454029 0 1 0 0
2454030 0 0 0 1
2454031 0 0 1 0
2454032 0 1 0 0
The first column contains Julian dates (from 17 Oct 2006 to 25 Oct 2006). The other four columns are unit quaternions representing orientations in three dimensional space. This particular file has rotations that are all 90 degrees from each other because hand-editing any other quaternions is too much trouble. In general, you'll want to use some sort of tool to produce these files.
Celestia uses spherical linear interpolation between keyframes. The nice thing about quaternion interpolation is that it always uses the shortest path between two orientations, so you don't get any of the extra twisting that occurs when interpolating Euler angles. At some point, I will add an option for cubic interpolation of quaternions so that the rotation is smoother. I think that can wait though.
Probably the most important thing is to validate the orientations with SPICE. Celestia uses a non-standard coordinate system internally, but I don't want creators of orientation files to have to know that. Some transformation needs be applied so that quaternions in the file orient bodies in the conventional way--I think that it's as simple as an additional 90 degree rotation about the x-axis.
--Chris
A new feature in Celestia 1.5.0 is a much more flexible scheme for describing an object's orientation, together with a cleaner syntax for rotations in ssc files. There are now different types of rotation, much like there are different types of orbits right now (CustomOrbit, SampledOrbit, EllipticalOrbit, etc.)
In Celestia 1.4.1 and earlier, the rotation parameters appeared at the top level of an ssc body definition. For example, here's part of the definition of Earth:
"Earth" "Sol" { Texture "earth.*" Radius 6378.140 CustomOrbit "vsop87-earth" RotationPeriod 23.9344694 Obliquity -23.4392911 RotationOffset 280.5 }
"Earth" "Sol" { Texture "earth.*" Radius 6378.140 CustomOrbit "vsop87-earth" UniformRotation { Period 23.9344694 Inclination -23.4392911 MeridianAngle 280.5 } }
Grouping the rotation parameters in the UniformRotation block keeps the object definition more organized, but more importantly the new syntax allows other types of rotations to be used. In addition to UniformRotation, there's PrecessingRotation, CustomRotation, and SampledRotation.
SampledRotation specifies a file of quaternion keys that are interpolated to compute the orientation of a body. I've heard a lot of requests for this feature, mostly from people interested in modeling spacecraft attitude more accurately than what Celestia 1.4.1 rotation parameters permitted.
A sampled orientation file is an ASCII text file with records of the form:
<time> <qw> <qx> <qy> <qz>
(qw qx qy qz) is a unit quaternion representing a rotation of theta =acos(qw)*2 radians about the axis (qx, qy, qz)*sin(theta/2). The time values are Julian days in Barycentric Dynamical Time (TDB). Here's a very simple example file:
2454025 0 0 1 0 2454026 0.707 0.707 0 0 2454027 0 0 1 0 2454028 1 0 0 0 2454029 0 0 1 0 2454030 0 1 0 0 2454031 0 0 0 1 2454032 1 0 0 0
This describes a series of 90 and 180 degree rotations over the time period from Oct 15-23, 2006. I created this file by hand for testing, but generally, orientation files will be created by some data conversion tool.
I took some time to make sure that Celestia uses the quaternions in an orientation file in a way that is consistent with the coordinate system in xyz files.
--Chris
Back to Contents.
In an SSC, one now can specify a coordinate reference frame
to be used for defining a body's location with the statement
OrbitFrame { ... }
and specify the coordinates of the body within that frame
with the statement
FixedPosition [...]
or
ScriptedPosition {...}
By default, the body is at the origin of its OrbitFrame.
One can make a body move in wonderous ways by specifying an appropriate OrbitFrame, including one that invokes a Lua script.
(In principle, I think it would make sense for there also to be a way to specify movement of a body with respect to its OrbitFrame, but I think Chris didn't want to introduce that confusing complication.)
In an SSC, one now can specify a coordinate reference frame
to be used for defining a body's orientation with the statement
BodyFrame { ... }
and specify the orientation of the body with respect that frame
with the statement
FixedRotation { ... }
or specify a changing orientation of the body with respect to the orientation frame
with the statement
UniformRotation { ... }
or
ScriptedRotation {...}
By default, the body's orientation is the same as its BodyFrame.
One can make a body rotate in wonderous ways by specifying an appropriate BodyFrame or ScriptedRotation.
Here are a few situations in which you may want more choices:
I'm reluctant to be doing any new feature work in 1.5.0, but I don't want to introduce the new OrbitBarycenter and OrbitReferencePlane SSC fields only have them made immediately obsolete by reference frames in 1.5.1. I am trying to limit the scope of this new feature somewhat, so the full flexibility of reference frames may not be immediately available in 1.5.0. Later today, I'll post some sample frame definitions for ssc files.
--Chris
The new reference frame code is enabled now. In addition to the default reference frames, two other frame types are supported in ssc files. The reference frame for the orbit and for the body itself may be specified separately. This is useful in some cases, necessary in others--for instance, when the reference frame for the orientation of a body is in part defined by its position.
The syntax is:
OrbitFrame <frame definition> BodyFrame <frame definition>
Where <frame definition> is either:
{ MeanEquator { Center <center> Object <equator obj> # defaults to center if not specified Freeze <date> # use mean equator of date if freeze epoch not specified } }
{ BodyFixed { Center <center> } }
There is also a new orbit type and a new rotation model:
FixedPosition [ <x> <y> <z> ] FixedRotation { Inclination <degrees> AscendingNode <degrees> MeridianAngle <degrees> }
--Chris
With a UniformRotation, the angle of rotation about the axis is computed as:
MeridianAngle + rotation_rate * (time - epoch)
Since rotation rate is by definition zero for a fixed rotation, the epoch is unnecessary.
--Chris
I should make it clear that the OrbitReferencePlane and OrbitBarycenter are completely replaced by reference frames. They were to be new 1.5.0 ssc fields, but reference frames are a much more general mechanism that can do everything that OrbitReferencePlane/OrbitBarycenter could and a lot more.
The change doesn't affect stars. I should have made it clear that I was only talking about SSC objects. I don't want to break everyone's star add-ons.
Eventually reference frames will be introduced for stc files too. I don't think that they'll be nearly as useful there; I'll mainly do it for the sake of consistency. And even when reference frames do appear in stc files, I'll make sure that OrbitBarycenter still works.
--Chris
Back to Contents.
Here's a sample ssc body definition that will place a sphere about 1500km above the surface of the Earth:
"BodyFixedTest" "Sol/Earth" { Radius 400 Texture "callisto.*" # 8000 km from center of Earth FixedPosition [ 8000 0 0 ] OrbitFrame { BodyFixed { Center "Sol/Earth" } } }
Even though the position of this object is fixed within it's reference frame, the frame is a body-fixed frame that rotates with the Earth. To observer on the surface of the Earth, the object does not appear to move; an observer in space will see the object in a synchronous orbit. My example doesn't demonstrate anything that you can't do with the Celestia 1.4.1--it's meant solely as a simple illustrative example.
You can set the frame for the body orientation separately. In the example below, we'll use the same frame as for the orbit:
BodyFrame { BodyFixed { Center "Sol/Earth" } } FixedRotation { }
The above example makes the rotation of the object fixed in the Earth body-fixed reference frame--it acts like a synchronous rotator.
Hopefully, this gives you some idea of how reference frames will work. I'll post some examples that do much more interesting things this weekend.
--Chris
Here's another reference frame example. This one uses the new two-vector reference frame to place an object at the Earth's leading triangular Lagrange point.
[example updated to use named blocks ...s.]
"Earth L4" "Sol" { Radius 4000 Color [ 1 0 0 ] OrbitFrame { TwoVector { Center "Sol/Earth" Primary { Axis "x" RelativePosition { Observer "Sol/Earth" Target "Sol" } } Secondary { Axis "y" RelativeVelocity { Observer "Sol/Earth" Target "Sol" } } } } FixedPosition [ 0.5 0.866 0 ] # units in AU }
Some explanation is required, though hopefully the SSC definition is at least somewhat self explanatory.
A two-vector reference frame defines a coordinate system based on two vectors. At the moment, Celestia supports two different vector types for two-vector frames: relative position and relative velocity. The primary points in the direction of the primary vector. The secondary axis point is at a right angle to the primary axis. It will not generally point in exactly the same direction as the secondary vector; rather, it points in the direction of the component of the secondary vector that is orthogonal to the primary axis. Finally, the remaining axis points in a direction orthogonal to both the primary and secondary axes and defines a right-handed coordinate system.
It will be helpful to show a diagram of the coordinate system described by my example frame, and I'll be preparing one soon. The x-axis in the example points from the Earth to the Sun. The y-axis is the Earth's velocity relative to the Sun. This is a very frame for specifying Lagrange points. All of the Lagrange points can be defined using the reference frame in the example and a different FixedPosition. The collinear Lagrange points L1, L2, and L3 will have zero y and z coordinates. These points aren't stable; however, there are stable orbits about the collinear Lagrange points, so for a realisitic scenario the orbit shouldn't just be a FixedPosition. In my L4 example, the FixedPosition is the vertex of an equiliateral triangle (in AU) in the reference frame. The L5 point would be at [ 0.5 -0.866 0 ].
If used as the reference frame for the body (rather than the orbit), the example frame can be used to keep an object constant oriented toward the Sun. I invite anyone who's building from CVS to try it (hint: use BodyFrame instead of OrbitFrame.) If no one does it first, I'll post the example ssc definition tomorrow. --Chris
More examples: the L1 and L2 Lagrange points, which each lie approximately 1.5 million km (0.01 au) from the Earth:
[example updated to use named blocks ...s.]
"Earth L1" "Sol" { Radius 4000 Color [ 1 0 0 ] OrbitFrame { TwoVector { Center "Sol/Earth" Primary { Axis "x" RelativePosition { Observer "Sol/Earth" Target "Sol" } } Secondary { Axis "y" RelativeVelocity { Observer "Sol/Earth" Target "Sol" } } } } # units in AU: they should be KM since this is relative to "Sol/Earth" # FixedPosition [ 0.01 0 0 ] # units in km FixedPosition [ 1500000 0 0 ] } "Earth L2" "Sol" { Radius 4000 Color [ 1 0 0 ] OrbitFrame { TwoVector { Center "Sol/Earth" Primary { Axis "x" RelativePosition { Observer "Sol/Earth" Target "Sol" } } Secondary { Axis "y" RelativeVelocity { Observer "Sol/Earth" Target "Sol" } } } } # units in AU: they should be KM since this is relative to "Sol/Earth" # FixedPosition [ -0.01 0 0 ] # units in km FixedPosition [ -1500000 0 0 ] }
Soon, named frames will be implemented, which will remove the need to redefine the Earth-Sun frame every time you want to use it. In the above example, the only different between the two objects is the sign of the x coordinate for the FixedPosition 'orbit'. --Chris
In an effort to make reference frames more comprehensible, I've made an image illustrating this frame used for the Earth Lagrange points:
[example updated to use named blocks ...s.]
OrbitFrame { TwoVector { Center "Sol/Earth" Primary { Axis "x" RelativePosition { Observer "Sol/Earth" Target "Sol" } } Secondary { Axis "y" RelativeVelocity { Observer "Sol/Earth" Target "Sol" } } } }
--Chris
> It seems to me that the FixedPosition statement should use the units > appropriate to block that the statement is in. > > For example > in > "Earth L4" "Sol" { ... FixedPosition [n n n] ... } > the units should be AU relative to Sol. > > while in > "Moon L4" "Sol/Earth" { ... FixedPosition [n n n] ... } > the units should be in km relative to the Earth.
I agree. I'll ignore the reference frame center and just choose the
units based on the parent object. The choice of units will apply to
all sub-blocks: FixedPosition, EllipticalOrbit, UniformRotation, etc.
[...]
I don't think I've explained reference frames well enough . . .
OrbitFrame defines the coordinate system for the orbit. FixedPosition is just another orbit type, like EllipticalOrbit, CustomOrbit, and SampledOrbit. Thus, FixedPosition doesn't belong inside the orbit frame. I'll admit that the terminology is a little confusing--an object with a fixed position doesn't really have a proper orbit. In Celestia, 'orbit' actually means any function that converts time to a position; a FixedPosition is just a constant function.
The BodyFrame defines the coordinate system for the orientation of an object. It can be the same as the coordinate system for the orbit, but it doesn't have to be. The example ssc definition that I posted to the forum [see section 5.10.8 below ] with the space shuttle in a local attitude frame demonstrates one situation where you want a body frame that differs from the orbit frame.
What the secondary block does:
A coordinate system has three orthogonal axes and a center point. Celestia only uses right-handed coordinate systems. The requirement that the coordinate system be right-handed means that the three axes can be determined by two non-collinear vectors, thus the TwoVector reference frame in Celestia.
The primary axis will point exactly in the direction of the primary vector. The secondary axis will not necessarily be parallel to the secondary vector, because the axes of the coordinate system need to be orthogonal to each other. The third axis is just the cross product of the primary and secondary axes. I'll try to make a diagram that shows the relationship between the primary and secondary vectors and the axes of the coordinate system that they define. The SPICE frames required reading document has an ASCII diagram of a two-vector coordinate system that might be helpful.
It's clear to me that reference frames are going to require some detailed documentation.
--Chris
Back to Contents.
Yet another reference frame example . . .
Here I'm defining a local frame for the orientation of the shuttle. The -z axis points from the shuttle toward the Earth and the y axis points in direction of the shuttle's velocity. The shuttle is assigned a fixed orientation within the reference frame, but since the reference frame itself is rotating, the overall effect is to orient the shuttle so that it always faces the Earth:
The ssc is slightly trickier than I'd like it to be. Since the
BodyFrame references the shuttle itself, I first need to define the
shuttle, and then have a second modifying definition that sets the body
frame. I chose -z as the Earth-pointing axis because of the way that
the Atlantis mesh was modeled.
[example updated to use named blocks ...s.]
"Atlantis LVLH" "Sol/Earth" { Mesh "atlantis.cmod" Radius 0.032 EllipticalOrbit { Epoch 2452562.41666667 Period 0.06415835 SemiMajorAxis 6769.712 Eccentricity 0.0019561 Inclination 51.6355 AscendingNode 171.6144 ArgOfPericenter 2.8715 } MeshCenter [ 0 0.31 -0.08 ] Albedo 0.50 FixedRotation { } } Modify "Atlantis LVLH" "Sol/Earth" { BodyFrame { TwoVector { Center "Sol/Earth" Primary { Axis "-z" RelativePosition { Observer "Sol/Earth/Atlantis LVLH" Target "Sol/Earth" } } Secondary { Axis "y" RelativeVelocity { Observer "Sol/Earth/Atlantis LVLH" Target "Sol/Earth" } } } } }
And to make things slightly more interesting, I can replace the FixedRotation with a UniformRotation like this:
UniformRotation { Period 0.03 }
This causes the shuttle to rotate about its z axis--that's the default if there's no inclination or ascending node--as it orbits the Earth. A more realistic shuttle mission would use a SampledOrientation to orient the shuttle.
Here's a page with some diagrams and an explanation of local attitudes: http://liftoff.msfc.nasa.gov/academy/rocket_sci/shuttle/attitude/lvlh.html
--Chris
Back to Contents.
One application of the EquatorJ2000 frame in Celestia is for using .xyz files with coordinates in the ICRF/J2000.0 equator reference frame. It's always been possible to write a program to transform the coordinates, but now that's no longer necessary. Selden mentioned a few days ago he was using an orbit tool called JAQAR ( http://www.jaqar.com/swingby.html) that generated heliocentric coordinates in J2000 equatorial frame. Here's how you'd use reference frames to import that trajectory into Celestia:
"Some Spacecraft" "Sol" { Mesh "spacecraft.cmod" Radius 0.002 SampledOrbit "jaqar.xyz" OrbitFrame { EquatorJ2000 { Center "Sol" } } }
The EclipticJ2000 frame is the default frame assumed by Celestia for objects that orbit a star. Thus, for a Sun-orbiting object, setting the orbit frame to EclipticJ2000 { Center "Sol" } is identical to omitting the orbit frame completely. For an object such as a moon that does not orbit a star, the default reference frame is the mean equatorial plane of the body. But, you can override this default with another frame such as EclipticJ2000, EquatorJ2000, or something else depending upon the plane that your orbital elements are referred to.
The application of reference frames that I've described in this post is mainly a convenience feature: instead of writing small scripts to transform trajectories and orbital elements into Celestia's default reference frames you can just let Celestia do the work for you.
--Chris
Question:
Would this also be the appropriate reference frame for the Earth-Moon lagrange points?
No. You would use something like the frame for the Earth/Sun Lagrange
points. For example:
[example updated to use named blocks ...s.]
"Moon L4" "Sol/Earth" { Radius 4000 Color [ 1 0 0 ] OrbitFrame { TwoVector { Center "Sol/Earth/Moon" Primary { Axis "x" RelativePosition { Observer "Sol/Earth/Moon" Target "Sol/Earth" } } Secondary { Axis "y" RelativeVelocity { Observer "Sol/Earth/Moon" Target "Sol/Earth" } } } } FixedPosition [ 192000 332600 0 ] }
I just took the Earth/Sun Lagrange point example and replaced Sol/Earth with Sol/Earth/Moon and Sol with Sol/Earth. And of course, I modified the fixed position so that x = earth-moon-distance/2 and y = earth-moon-distance*sqrt(3)/2. I used 384000 km as the Earth-Moon distance. This is an approximation which assumes that the Moon is in a perfectly circular orbit about the Earth. I need to learn a bit more about where the Lagrange points lie on a slightly elliptical orbit.
--Chris
Back to Contents.
> IMO, the simplest way (for the user) to define the Precession axis > is something like this, in the SSC file : > > PrecessionRate nnn > PrecessionAxis [n n n] > > with the precession axis defined relative to Earth's axis, or > relative to the object's orbit (normal to its orbit, actuallly).It won't work quite like that . . .
> Also, for the user which makes the SSC, it would be much easier to > define an object orientation is like this : > > OrientationLock "object name"
That may be easy, but it also doesn't completely define the orientation of the object. Just specifying a single direction vector leaves one free parameter: the rotation about the vector. Celestia could choose some arbitrary secondary vector so that the orientation would be completely determined, but that's undesirable. For one thing, if the second vector happens to be aligned with the first, the orientation of the object would be undefined.
One way to express an orientation lock with reference frames is this:
[example updated to use named blocks ...s.]
BodyFrame { TwoVector { Center "Sol/Object" Primary { Axis "z" RelativePosition { Observer "Sol/Object" Target "Sol" } } Secondary { Axis "x" RelativeVelocity { Observer "Sol/Object" Target "Sol" } } } }
In this example, the object called "Object" will be oriented so it's z-axis always points toward the Sun. There's a lot more typing required than your proposal (which I'm assuming is a reference frame, not a rotation model):
BodyFrame { OrientationLock "Sol" }
Why all the extra typing? First of all, it's necessary to define the secondary axis. My example chooses uses the velocity of Object relative to the Sun. Second, you're free to choose the axes of the reference frame, thus the Axis "z" and Axis "y"--perhaps Celestia could use some reasonable defaults so that you wouldn't always have to specify these. In general, the TwoVector reference frame is much more flexible than the OrientationLock frame, though it's obviously somewhat harder to use.
It would be possible to define an OrientationLock frame that is converted automatically to the appropriate TwoVector reference frame. But, creating such 'syntactic sugar' is only worthwhile if it simplifies a very common task, and I'm not sure how frequently you'll want to create an OrientationLock frame.
--Chris
Back to Contents.
I've made some changes to the TwoVector frame type that make it more consistent with how other SSC blocks work and also make it easier to use. The Type field is gone, replaced by a named block, so this:
Primary { Type "RelativePosition" Axis "z" Observer "Sol/Object" Target "Sol" }
becomes this:
Primary { Axis "z" RelativePosition { Observer "Sol/Object" Target "Sol" } }
Note:All of the examples above have been updated to use named blocks as described just above. ... s.
I've also made the frame center the default observer for observer-target vectors. This is a very common case. Here's how the sun-locked frame looks like with the modifications to two-vector frames:
BodyFrame { TwoVector { Center "Sol/Object" Primary { Axis "z" RelativePosition { Target "Sol" } } Secondary { Axis "x" RelativeVelocity { Target "Sol" } } } }
That's a little bit simpler . . .
--Chris
I have a new reference frame example. This one is more complex than previous ones. It defines a frame centered on an object, with the z-axis pointing from the center of the Earth through the object and the y-axis pointing northward perpendicular to z. This frame is most useful for an object on the surface of the Earth (or any planet.) The z-axis is up, the y-axis is local true north direction, and x is local east (the cross product of z and y.) It's very useful for orienting an object moving on the surface of a planet--the reference frame means that the up direction stays the same no matter where you position the object, and you can 'turn' it by changing the rotation about the z-axis.
BodyFrame { TwoVector { Center "Sol/Earth/Object" Primary { Axis "-z" RelativePosition { Target "Sol/Earth" } } Secondary { Axis "y" ConstantVector { Vector [ 0 0 1 ] Frame { BodyFixed { Center "Sol/Earth" } } } } } }
The slightly tricky part is the definition of the secondary direction. The ConstantVector {} block is just the north pole of Earth. In a planet's body-fixed reference frame, the vector (0, 0, 1) (+Z) is the north pole (that is, the pole about which the planet appears to rotate counterclockwise, so it will actually point south of the ecliptic for a retrograde rotator.) If it's useful, I could modify the ssc parser make:
NorthPole {
ConstantVector { Vector [ 0 0 1 ] Frame { BodyFixed { Center
But, I'll wait to see how often reference frames get used before introducing shortcuts. --Chris
The existing observer modes follow, sync orbit, chase, and phase lock will (after 1.5.0) be rewritten and implemented in terms of the new reference frames. Here's how they would look, given the objects target and reference.
Follow:
OrbitFrame { EclipticJ2000 { Center} } # Body frame is identical to orbit frame
Sync orbit:
OrbitFrame { BodyFixed { Center} } # Body frame is identical to orbit frame
Phase lock:
OrbitFrame { TwoVector { CenterPrimary { Axis "z" RelativePosition { Observer Target } } Secondary { Axis "y" ConstantVector { Frame { BodyFixed { Center } } Vector [ 0 0 1] } } } } # Body frame is identical to orbit frame
Chase:
OrbitFrame { TwoVector { CenterPrimary { Axis "z" RelativeVelocity { Observer Target } } Secondary { Axis "y" ConstantVector { Frame { BodyFixed { Center } } Vector [ 0 0 1] } } } } # Body frame is identical to orbit frame
Note that this is intended to be another reference frame example. I don't actually plan to have write the observer modes as ssc files Smile
All of the existing observer modes have an orbit frame (for position) that's identical to the body frame (for orientation.) But, this does not have to be the case for new modes . . . For example, track could be implemented by using BodyFrame that's different than the OrbitFrame. An implementation of track in terms of frames would behave much better than the way track does now. With the following frame, an 'up' vector is defined so that the camera won't roll with respect to the horizon. Here, the object reference is the planet that the observer is on, and target is the tracking target:
BodyFrame { TwoVector { Center# observer to target direction Primary { Axis "x" RelativePosition { Observer Target } } # up direction Secondary { Axis "-z" RelativePosition { Observer Target } } } }
You don't have to use any of this to build an SSC file. The current system is flexible enough that you can use it to define most of the reference frames used in astrodynamics and celestial mechanics. If you have an alternate proposal that offers just as much flexibibility but is easier to use, then I'd like to hear about it.
It's possible that the reference frames could be extended with some 'shortcuts' for situations like making one object maintain a fixed orientation with respect to another, but I'd rather wait until 1.5.0 to discover what the common usage cases will be.
--Chris
You [do not] need to do anything differently for stars; reference frames will eventually be supported for stars as well, but the the current OrbitBarycenter scheme will continue to be supported. Making a barycentric planet definition isn't difficult:
ReferencePoint "Pluto-Charon" "Sol" { CustomOrbit "pluto" } "Pluto" "Sol" { EllipticalOrbit { ... } OrbitFrame { EclipticJ2000 { Center "Sol/Pluto-Charon" } } }
That's not so bad, is it? Granted, it's not as easy as just making Pluto a child object of Sol/Pluto-Charon (which is still possible), but there are some advantages of doing it with a frame instead:
--Chris
Chris wrote
It turns out that I need ScriptedOrbits for a project that I'm working on . . .
hank wrote:
Ideally it would be possible to specify the Lua orbit in the .ssc file rather than using a hook in SampledOrbit. This would require a modification of the parser for .ssc files and a new ScriptedObject subclass of CachedOrbit. I don't plan to attempt that, but here's a suggestion as to how it might work:
A factory function for creating parameterized orbits would be defined in the Lua init file. For example, one could be defined for orbits that are midway between any two objects. It might look like this: Code: midpointOrbit = function(args) return { this.arg = args; computeposition = function(this,jd) if not this.sun then this.sun = celestia:find("Sol"); end; this.obj1 = celestia:find(this.arg.fromObject); this.obj2 = celestia:find(this.arg.toObject); local obj1Position = this.obj1:getposition(jd); local obj2Position = this.obj2:getposition(jd); local sunPosition = this.sun:getposition(jd); local objVector = obj1Position:vectorto(obj2Position); local newPos = obj1Position:addvector( objVector*0.5 ); local newVector = sunPosition:vectorto(newPos)*KM_PER_MLY; return newVector:getx(), newVector:gety(), newVector:getz(), true; end; end; The .ssc parser could be rewritten to accept the following syntax: Code: ScriptedOrbit "midpointOrbit" { fromObject "Sol/Earth" toObject "Sol/Mars" }
I implemented something very close to this proposal. Here's a sample usage:
"Scripted" "Sol/Ida" { Texture "io.*" Radius 500 ScriptedOrbit { Module "orbits" Function "lissajous" PeriodX 1 PeriodY 3.1 PeriodZ 2.4 PhaseX 0.5 PhaseY 0.2 PhaseZ 0.0 AmplitudeX 1000 AmplitudeY 800 AmplitudeZ 540 } }
Module gives the name of a package that will be loaded via Lua's require method. Presently, it searches some standard set of paths, but with a small bit of work it the package loader could be made to search the add-on directory too. Function is the name of a factory function that produces a table with the orbit properties, including a function that returns the position at a particular time. All of the ScriptOrbit properties other than Module and Function are passed on to the Lua factory function to create the orbit object.
Here's the implementation of a Lissajous orbit:
function lissajous(t) local orbit = {}; orbit.params = t; orbit.boundingRadius = math.sqrt(t.AmplitudeX * t.AmplitudeX + t.AmplitudeY * t.AmplitudeY + t.AmplitudeZ * t.AmplitudeZ) function orbit:position(tjd) local t = tjd - 2451545.0 local pi2 = math.pi * 2; local x = self.params.AmplitudeX * math.sin((t / self.params.PeriodX + self.params.PhaseX) * pi2) local y = self.params.AmplitudeY * math.sin((t / self.params.PeriodY + self.params.PhaseY) * pi2) local z = self.params.AmplitudeZ * math.sin((t / self.params.PeriodZ + self.params.PhaseZ) * pi2) return x, y, z end return orbit end
period, begin, and end are additional optional number properties that aren't used in my example. I've checked in the code, but it's disabled by default; I'm inclined to leave it that way until after 1.5.0, since this release is already suffering heavily from featuritis. I'm posting mostly to see if anyone has comments on Hank's and my ideas for ScriptedOrbits.
See this link if you're wondering what Lissajous curves are: http://mathworld.wolfram.com/LissajousCurve.html
In astrodynamics, Lissajous orbits are used for spacecraft stationed near the collinear Lagrange points--they're only semi-stable, but just minimal maneuvering is required to maintain one.
--Chris
Back to Contents.
from stardb.cpp:
Required keywords:
RA number (deg)
Dec number (deg)
Distance number (parallax)
SpectralType string
AbsMag number
if no AbsMag, then
AppMag number
and calc AbsMag.
name?
From star.cpp:
The following formulas were all replaced by table lookups as of Celestia v1.3.1pre4
temp calc: giants same as dwarfs Radius = sqrt (luminosity)* (solar temp/star temp)**2 White dwarfs and Neutron stars are arbitrarily set to 10,000 Black holes have a temp of 0 rotation period arbitrarily set to 25.4 days = solar rotation period changed in v1.3.1pre4 to use a lookup table with dependancies on the stellar type and luminosity class. catalog # position (3f = xyz = micro lightyears? Stellarclass Abs mag --> apparent mag, luminosity
Back to Contents.
Implemented in celestia / celestia / src / celengine / galaxy.cpp
(This description is partially redundant as of v1.2.6: distance and orientation were moved to the DeepSky module. See 11.0: DeepSky Objects.)
Notes on galaxy and nebula alignment:
Quote from Chris:
I oriented the Milky Way by eyeballing it . . . There's a semi-secret key in Celestia that lets you adjust the orientation of the selected galaxy and print out the axis angle rotation. However, using the galactic coordinate system is definitely preferable to my ad hoc method. You can edit galaxy orientation by pressing the ~ key and then
End Quote
----
(*) -- use the line-oriented command
./celestia --verbose >align.log
or the equivalent.
Back to Contents.
celestia / celestia / src / celengine / simulation.cpp // Choose a planet around a star given it's index in the planetary system. // The planetary system is either the system of the selected object, or the // nearest planetary system if no object is selected. If index is less than // zero, pick the star. This function should probably be in celestiacore.cpp. // Select an object by name, with the following priority: // 1. Try to look up the name in the star database // 2. Search the galaxy catalog for a matching name. // 3. Search the planets and moons in the planetary system of the currently selected // star // 4. Search the planets and moons in any 'nearby' (< 0.1 ly) planetary systems // Find an object from a path, for example Sol/Earth/Moon or Upsilon And/b // Currently, 'absolute' paths starting with a / are not supported nor are // paths that contain galaxies.As of Celestia v1.3.1pre3, "object name completion" is supported when typing a name to the [enter] object selection input. This changed to "tab completion" in v1.3.1pre4.
Back to Contents.
cel:// (new in v1.2.6)
Cel://
URL in Web document
Cel://
URL onto Celestia icon
Cel://
URL in "run Celestia" command
Some of the fields used by Cel://
URL
Back to Contents.
Back to Contents.
Do not add more objects to the file /data/deepsky.dsc
.
Instead, create your own Deep Sky Catalog files in
/extras/arbitrary.dsc
("Arbitrary
" means you can use whatever file
name you want.)
Types:
v380_neb.png
.
Parameters common to all DeepSky objects:
Back to Contents.
Ctrl-A | Show Atmosphere |
Ctrl-B | Show Boundaries |
<lf>or <cr> | TextEnterMode |
"\b" | (?) Set selection |
Ctrl-L | ShowNightMaps |
Ctrl-K | ShowMarkers toggle |
Ctrl-E | ShowEclipseShadows |
Ctrl-G | GotoSurface |
Ctrl-F | Set AltAz Mode |
<Del> | Delete current viewpane |
Ctrl-I (= <tab>) | Next viewpane |
Ctrl-P | FragmentShader toggle |
Ctrl-U | VerticalSplit viewpane |
Ctrl-R | HorizontalSplit viewpane |
Ctrl-D | Single Viewpane |
Ctrl-S | StarsAsPOints toggle |
Ctrl-T | ShowCometTails toggle |
Ctrl-W | WireFrame toggle |
Ctrl-X | ShowSmoothLInes toggle |
Ctrl-Y | ShowAutoMag toggle |
Ctrl-[ (= <esc>) | Cancel |
<Space > | Pause toggle |
! | if edit: current galaxy orientation > std.out else set time to 1Jan1970 |
* | reverse observer orientation (lookback) |
? | display light delay time to selection |
- | set light delay time to selection |
, | decrease fov |
. | increase fov |
/ | Show Constellation Diagrams toggle |
0-9 | select planet # (0=sun) |
; | ShowCelestialSphere toggle |
= | ConstellationLabels toggle |
B | StarLabels toggle |
C | Center selection |
D | run Demo Script |
E | GalaxyLabels toggle |
F | Follow selection |
G | GoTo selection |
H | Select Sol |
I | ShowCloudMaps toggle |
J | ReverseTime toggle |
K | DecreaseTimeRate |
L | IncreaseTimeRate |
M | MoonLabels toggle |
N | SpaceCraftLabels toggle |
O | ShowOrbits toggle |
P | PlanetLabels toggle |
Q | getTargetSpeed |
R | Use higher resolution texture |
r | Use lower resolution texture |
S | Stop: setTargetSpeed 0 |
T | Track selection |
U | ShowGalaxies toggle |
V | cycle HUD detail |
W | AsteroidLabels toggle |
X | set TargetSpeed |
Y | Sync Orbit selection toggle |
: | phaseLock selection toggle |
" | Chase selection toggle |
[ | decrease magnitude threshold |
\ | setTimeScale 0 |
] | increase magnitude threshold |
` | show frame/sec |
{ | increase ambient light level |
} | decrease ambient light level |
@ | edit mode toggle |
~ | console log toggle |
Some of these were snuck in for 1.3.0
Menu | GoTo LongLat | ||
Ctrl-F | AltAzimuth mode for Arrow Keys | ||
Ctrl-G | GotoSurface (Windows) | Ctrl-S | GotoSurface (Linux) |
* | LookBack | ||
y | Sync Orbit |
new in 1.2.6: (aka 1.3)
Back to Contents.
As of 1.3.1pre9, Celestia supports a feature I've been calling virtual textures. This message is a plea for you texture artists to test this feature out . . .
Virtual textures consist of multiple levels of detail, each one four times the size of the previous (twice the width, twice the height.) Every level of detail is composed of 2n x n texture tiles, where n must be a power of two. Celestia chooses the level of detail to use based on the size in pixels of the object to be textured. The levels of detail do not need to be fully populated; if a tile at the requested level of detail is not available, Celestia will fall back to a lower level of detail that is available. This allows you map planets with very high resolution at particular locations without forcing you to map the entire planet at such a resolution. In fact, since 1km/pixel maps of planets are cumbersome to distribute online, I expect these detail tiles will be the main application of virtual textures.
A virtual texture is identified by the extension .ctx. A ctx file is actually just a text file in the familiar ssc-like format. There are several fields describing the layout of the texture tiles. Here's my test example:
Code:
VirtualTexture { ImageDirectory "tiles" BaseSplit 0 TileSize 256 TileType "jpg" }The image directory gives the location of the individual texture files. BaseSplit determines the number of tiles in the lowest level of detail (2^(baseSplit + 1) tiles wide, 2^baseSplit tiles high.) TileSize gives the number of pixels in each dimension of the texture tiles. This value is used to figure out what level of detail to use. It is not enforced, and it could be very useful to have a higher resolution tile at the highest LOD (though it's not recommended elsewhere.)
Code:
foo/ foo.ssc textures/ medres/ foo.jpg hires/ foo.ctx tiles/ level0/ tx_0_0.dds tx_1_0.dds level1/ tx_0_0.dds tx_1_0.dds tx_2_0.dds tx_3_0.dds tx_0_1.dds tx_1_1.dds tx_2_1.dds tx_3_1.dds level8/ tx_300_59.ddsIn the above example, the planet is fully mapped at resolution levels 0 and 1, and there's one high detail tile at level 8. A few quick calculations . . . The base split here is 0. Let's assume that the tiles are 256x256. That means that the effective resolution at level 8 is 256*2*2^8 x 256*2^8, or 128k x 64k. For Earth, that's approximately 300m/texel. The general formula for the effective height of a virtual texture level is:
TileSize*2^(Level + BaseSplit)
The width is always double the height. I suppose that I should really make some sort of JavaScript calculator to compute sizes and the latitude and longitude ranges of tiles.
The main problem that I've had with creating virtual textures is finding high resolution data. I've got the 32k Earth texture split up into tiles, but I've been unable to find any higher resolution data. If anyone has some good links, please share them. Or better yet, go ahead and use it to create a virtual texture.
--Chris
Back to Contents.