How to Orient a Model



In this entry, I'll explain how to orient a model primitive using its ReferenceFrame and Orientation properties.  We'll go through two examples.  The first one orients a launch pad model on the ground:

LaunchPadOrientation

The second example orients a satellite model in orbit:

SatelliteOrientations

Orienting using Reference Frames

In many cases, particularly those where a model is stationary on the ground, a model can be oriented by simply setting its ReferenceFrame property.  The following example loads a launch pad model at Cape Canaveral.  What is going on with its default orientation?

Cartographic position = new Cartographic(Trig.DegreesToRadians(-80.577778), Trig.DegreesToRadians(28.488889), 0);
ModelPrimitive model = new ModelPrimitive("delta4-lp.mdl");
model.PositionCartographic = position;
SceneManager.Primitives.Add(model);

LaunchPadCBF

Since the model primitive, like all primitives, has a default reference frame of the Earth's fixed frame.  The model is oriented using the Earth's fixed frame's axes.  In this case, the tower is aligned with +z.  How do I know that?  I used the handy ReferenceFrameGraphics helper class that is available in the HowTo:

EarthCentralBody earth = CentralBodiesFacet.GetFromContext().Earth;
PointCartographic origin = new PointCartographic(earth, position);
ReferenceFrame referenceFrame = new ReferenceFrame(origin, model.ReferenceFrame.Axes);
new ReferenceFrameGraphics(referenceFrame, 45);

LaunchPadCBFAxes

The ReferenceFrameGraphics object created a visualization of the primitive's reference frame's axes using the primitive's position as the origin.   If you're curious, the Earth's fixed frame with its normal origin, looks like this:

EarthFixedFrame

So if the model was positioned at the North Pole, it would be oriented correctly.  I'm no rocket scientist but last time I checked, no one launches from the North Pole, so we are going to stick with our current launch position and change the model's orientation.  A quick look at the AGI Components documentation shows that AxesEastNorthUp has the orientation we want.

To orient the model correctly, we create a reference frame with an origin of the model's desired position and east-north-up axes.  Note that the model's position is no longer explicitly set.  It is left as its default of Cartesian.Zero, since it is at the origin of its reference frame.

EarthCentralBody earth = CentralBodiesFacet.GetFromContext().Earth;
Cartographic position = new Cartographic(Trig.DegreesToRadians(-80.577778), Trig.DegreesToRadians(28.488889), 0);
PointCartographic origin = new PointCartographic(earth, position);
Axes axes = new AxesEastNorthUp(earth, origin);
ReferenceFrame referenceFrame = new ReferenceFrame(origin, axes);
new ReferenceFrameGraphics(referenceFrame, 45);

ModelPrimitive model = new ModelPrimitive("delta4-lp.mdl");
model.ReferenceFrame = referenceFrame;
SceneManager.Primitives.Add(model);

LaunchPadEastNorthUp

Other commonly used axes include AxesNorthEastDown and AxesAlignedConstrained.

Orienting using Rotations

Sometimes you don't want to use a primitive's ReferenceFrame alone to orient it.  Perhaps, you are concerned about performance, and you want several primitives to share the same ReferenceFrame; or you set the model's ReferenceFrame, but the model needs further adjustments to look right.  For these cases, use the model's Orientation property.

Let's say we're trying to orient a satellite model defined using AxesLocalVerticalLocalHorizontal, like the "Camera -> Follow an Earth orbiting satellite" example in the HowTo.  Our first attempt is probably something like:

AxesLocalVerticalLocalHorizontal lvlhAxes = new AxesLocalVerticalLocalHorizontal(earth.InertialFrame, propagator.CreatePoint());
ReferenceFrame lvlhFrame = new ReferenceFrame(satellitePoint, lvlhAxes);

ModelPrimitive satellite = new ModelPrimitive("globalstar.mdl");
satellite.ReferenceFrame = lvlhFrame;
SceneManager.Primitives.Add(satellite);

// Debug code for visualizing LVLH axes
new ReferenceFrameGraphics(lvlhFrame, 25, Color.Orange);

Since we've learned the usefulness of ReferenceFrameGraphics, we created one to see the model's reference frame:

SatelliteOne

LVLH axes are oriented such that +Y is toward the velocity vector and +X is along the position vector.  This model was originally modeled with its solar panels spanning along the Y axis so the model's orientation is incorrect in this frame.  We really want the model to be oriented like this:

SatelliteFour

We need two rotations to get the satellite oriented correctly in this frame.  First let's apply a -90 degree rotation around the LVLH Y axis.  This makes the tops of the solar panels that were originally facing -Z face +X, or "up."

AxesLocalVerticalLocalHorizontal lvlhAxes = new AxesLocalVerticalLocalHorizontal(earth.InertialFrame, propagator.CreatePoint());
ReferenceFrame lvlhFrame = new ReferenceFrame(satellitePoint, lvlhAxes);

EulerSequence eulerSequence = new EulerSequence(-Constants.HalfPi, 0, 0, EulerSequenceIndicator.Euler213);
UnitQuaternion invertedQuaternion = new UnitQuaternion(eulerSequence.Invert());

ModelPrimitive satellite = new ModelPrimitive("globalstar.mdl");
satellite.ReferenceFrame = lvlhFrame;
satellite.Orientation = invertedQuaternion;
SceneManager.Primitives.Add(satellite);

// Debug code for visualizing LVLH axes and axes after -90 degree rotation
UnitQuaternion quaternion = new UnitQuaternion(eulerSequence);
AxesFixedOffset rotatedAxes = new AxesFixedOffset(lvlhAxes, quaternion);
ReferenceFrame rotatedFrame = new ReferenceFrame(lvlhFrame.Origin, rotatedAxes);
new ReferenceFrameGraphics(rotatedFrame, 25, Color.White, Color.Black);
new ReferenceFrameGraphics(lvlhFrame, 15, Color.Orange);

SatelliteTwo

To rotate the model, first we create an EulerSequence with a -90 degree rotation around the Y axis.  The Euler sequence is then converted to a UnitQuaternion so it can be applied to the model's Orientation property.  Note that the Euler sequence is inverted when it is converted to the quaternion.  This is because we are determining the model's orientation by working from the LVLH frame to the model's frame, e.g. world to model.  The model's Orientation property expects a quaternion that goes from the model's frame to LVLH, e.g. model to world.

Also note that when the -90 degree rotation around Y is applied, the axes are also rotated.  The original LVLH axes are shown above in orange, and the rotated axes are shown in white.  Look at the rotated model, what rotation around what new axis is needed to get the model facing the desired direction?   90 degrees around Z:

AxesLocalVerticalLocalHorizontal lvlhAxes = new AxesLocalVerticalLocalHorizontal(earth.InertialFrame, propagator.CreatePoint());
ReferenceFrame lvlhFrame = new ReferenceFrame(satellitePoint, lvlhAxes);

EulerSequence eulerSequence = new EulerSequence(-Constants.HalfPi, 0, Constants.HalfPi, EulerSequenceIndicator.Euler213);
UnitQuaternion invertedQuaternion = new UnitQuaternion(eulerSequence.Invert());

ModelPrimitive satellite = new ModelPrimitive("globalstar.mdl");
satellite.ReferenceFrame = lvlhFrame;
satellite.Orientation = invertedQuaternion;
SceneManager.Primitives.Add(satellite);

// Debug code for visualizing LVLH axes and axes after -90 degree rotation
UnitQuaternion quaternion = new UnitQuaternion(eulerSequence);
AxesFixedOffset rotatedAxes = new AxesFixedOffset(lvlhAxes, quaternion);
ReferenceFrame rotatedFrame = new ReferenceFrame(lvlhFrame.Origin, rotatedAxes);
new ReferenceFrameGraphics(rotatedFrame, 25, Color.White, Color.Black);
new ReferenceFrameGraphics(lvlhFrame, 15, Color.Orange);

SatelliteThree

The model is now oriented correctly.  All that was required was two Euler angle rotations:  first -90 degrees around Y, then 90 degrees around Z.  Here is the final model without the rotated axes shown:

SatelliteFour

In summary, use a model's ReferenceFrame and Orientation property to get it oriented the way you want it.  When in doubt, experiment using ReferenceFrameGraphics to help visualize what is happening.

4 Responses to “How to Orient a Model”


  1. 1 Mustafa

    Hi, I am using AGI Components 2009 R6 and could not find ReferenceFrameGraphics class in the SDK. Is it included in R7?

  2. 2 Patrick Cozzi

    Hi Mustafa,

    This is a new feature in R7. ReferenceFrameGraphics is not in the core library but it is a small utility class you will find in the HowTo.

    You can download the latest version of AGI Components from ADN.

    Regards,
    Patrick

  3. 3 kkrv

    model.ReferenceFrame = referenceFrame;

    throws:

    “referenceFrame must be either centralBody.FixedFrame or centralBody.InertialFrame” on R8

  4. 4 kkrv

    Nevermind. references were incorrectly set to r3.

Leave a Reply