Main Content

Overlaying Simulated and Actual Flight Data

This example shows how to visualize simulated versus actual flight trajectories with the animation object (Aero.Animation) while showing some of the animation object functionality. In this example, you can use the Aero.Animation object to create and configure an animation object, then use that object to create, visualize, and manipulate bodies for the flight trajectories.

Create the Animation Object

Create an instance of the Aero.Animation object.

h = Aero.Animation;

Set the Animation Object Properties

Set the number of frames per second. This controls the rate at which frames are displayed in the figure window.

h.FramesPerSecond = 10;

Set the seconds of animation data per second time scaling. This property and the 'FramesPerSecond' property determine the time step of the simulation. The settings in this example result in a time step of approximately 0.5s. The equation is (1/FramesPerSecond)*TimeScaling along with some extra terms to handle for subsecond precision.

h.TimeScaling = 5;

Create and Load Bodies

Load the bodies using createBody for the animation object, h. This example uses these bodies to work with and display the simulated and actual flight trajectories. The first body is orange and represents simulated data. The second body is blue and represents the actual flight data.

idx1 = h.createBody('pa24-250_orange.ac','Ac3d');
idx2 = h.createBody('pa24-250_blue.ac','Ac3d');

Load Recorded Data for Flight Trajectories

Using the bodies from the previous code, this code provides simulated and actual recorded data for flight trajectories in the following files:

  • The simdata file contains logged simulated data. simdata is set up as a 6DoF array, which is one of the default data formats.

  • The fltdata file contains actual flight test data. In this example, fltdata is set up in a custom format. The example must create a custom read function and set the 'TimeSeriesSourceType' parameter to 'Custom'.

To load the simdata and fltdata files:

load('simdata.mat','simdata')
load('fltdata.mat','fltdata')

To work with the custom flight test data, this code sets the second body 'TimeSeriesReadFcn'. The custom read function is located here: matlabroot/toolbox/aero/animation/CustomReadBodyTSData.m

h.Bodies{2}.TimeSeriesReadFcn = @CustomReadBodyTSData;

Set the bodies' timeseries data.

h.Bodies{1}.TimeSeriesSource = simdata;
h.Bodies{2}.TimeSeriesSource = fltdata;
h.Bodies{2}.TimeSeriesSourceType = 'Custom';

Camera Manipulation

This code illustrates how you can manipulate the camera for the two bodies.

The 'PositionFcn' property of a camera object controls the camera position relative to the bodies in the animation. The default camera 'PositionFcn' follows the path of a first order chase vehicle. Therefore, it takes a few steps for the camera to position itself correctly in the chase plane position. The default 'PositionFcn' is located here: matlabroot/toolbox/aero/animation/doFirstOrderChaseCameraDynamics.m

Set 'PositionFcn'.

h.Camera.PositionFcn = @doFirstOrderChaseCameraDynamics;

Display Body Geometries in Figure

Use the show method to create the figure graphics object for the animation object.

h.show();

Use the Animation Object to Play Back Flight Trajectories

Use the play method to animate bodies for the duration of the timeseries data. Using this method illustrates the slight differences between the simulated and flight data.

h.play();
h.updateCamera(5);

Wait

Wait for the animation to finish before editing the object properties.

h.wait();

The code can also use a custom, simplified 'PositionFcn' that is a static position based on the position of the bodies (i.e., no dynamics). The simplified 'PositionFcn' is located here: matlabroot/toolbox/aero/animation/staticCameraPosition.m

Set the new 'PositionFcn'.

h.Camera.PositionFcn = @staticCameraPosition;

Run the animation with new 'PositionFcn'.

h.play();

Wait

Wait for the animation to finish before editing the object properties.

h.wait();

Move Bodies

Move the bodies to the starting position (based on timeseries data) and update the camera position according to the new 'PositionFcn'. This code uses updateBodies and updateCamera.

t = 0;
h.updateBodies(t);
h.updateCamera(t);

Reposition Bodies

Reposition the bodies by first getting the current body position and then separating the bodies.

Get current body positions and rotations from the body objects.

pos1 = h.Bodies{1}.Position;
rot1 = h.Bodies{1}.Rotation;
pos2 = h.Bodies{2}.Position;
rot2 = h.Bodies{2}.Rotation;

Separate bodies using moveBody. This code separates and repositions the two bodies.

h.moveBody(1,pos1 + [0 0 -3],rot1);
h.moveBody(2,pos1 + [0 0  0],rot2);

Create Transparency in the First Body

Create transparency in the first body. The code does this by changing the body patch properties via 'PatchHandles'. (For more information on patches in MATLAB®, see the Introduction to Patch Objects section in the MATLAB documentation.)

Note: On some platforms utilizing software OpenGL® rendering, the transparency may cause a decrease in animation speed.

See the opengl documentation for more information on OpenGL in MATLAB.

To create a transparency, the code gets the patch handles for the first body.

patchHandles2 = h.Bodies{1}.PatchHandles;

Set desired face and edge alpha values.

desiredFaceTransparency = .3;
desiredEdgeTransparency = 1;

Get the current face and edge alpha data and changes all values to desired alpha values. In the figure, notice the first body now has a transparency.

for k = 1:size(patchHandles2,1)
    tempFaceAlpha = get(patchHandles2(k),'FaceVertexAlphaData');
    tempEdgeAlpha = get(patchHandles2(k),'EdgeAlpha');
	set(patchHandles2(k),...
        'FaceVertexAlphaData',repmat(desiredFaceTransparency,size(tempFaceAlpha)));
    set(patchHandles2(k),...
        'EdgeAlpha',repmat(desiredEdgeTransparency,size(tempEdgeAlpha)));  
end

Change Color of the Second Body

Change the body color of the second body. The code does this by changing the body patch properties via 'PatchHandles'.

patchHandles3 = h.Bodies{2}.PatchHandles;

Set the desired patch color (red).

desiredColor = [1 0 0];

The code can now get the current face color data and change all values to desired color values. Note the following points on the code:

  • The if condition keeps the windows from being colored.

  • The name property is stored in the geometry data of the body (h.Bodies{2}.Geometry.FaceVertexColorData(k).name).

  • The code only changes the indices in patchHandles3 with non-window counterparts in the body geometry data.

The name property might not always be available to determine various parts of the vehicle. In these cases, use an alternative approach to selective coloring.

for k = 1:size(patchHandles3,1)
    tempFaceColor = get(patchHandles3(k),'FaceVertexCData');
    tempName = h.Bodies{2}.Geometry.FaceVertexColorData(k).name;
    if ~contains(tempName,'Windshield') &&...
       ~contains(tempName,'front-windows') &&...
       ~contains(tempName,'rear-windows')
    set(patchHandles3(k),...
        'FaceVertexCData',repmat(desiredColor,[size(tempFaceColor,1),1]));
    end
end

Turn Off Landing Gear on Second Body

Turn off the landing gear for the second body. To do this, the code turns off the visibility of all vehicle parts associated with the landing gear. Note the indices into the patchHandles3 vector were determined from the name property in the geometry data. Other data sources might not have this information available. In these cases, you will need to know which indices correspond to particular parts of the geometry.

for k = [1:8,11:14,52:57]
    set(patchHandles3(k),'Visible','off')
end

Close and Delete Animation Object

Close and delete.

h.delete();
%#ok<*REPMAT>

See Also

| |

Related Topics