
Guest Writer: Ken Deeley
Ken is an application engineer in Cambridge, UK, supporting MathWorks users with their technical computing projects. Ken joined the MathWorks customer training team in 2011 after research work in mathematics with applications to motion planning for autonomous guided vehicle (AGV) robotics. Ken specializes in software development, machine learning, and financial applications, with a particular focus on graphics and app development. He enjoys training MathWorks users on best practices, working with customers on consulting projects, and capturing common customer workflows and requirements to inform future MathWorks development activities.

Overview
MATLAB provides a large suite of visualization functions tailored to scientific and engineering applications. In addition, MATLAB enables you to develop domainspecific visualizations. These can be embedded in all data analytics workflows, ranging from smallscale interactive
tasks to more complex
reports,
apps and
web apps such as dashboardlike front ends.
Let's assume that we've been tasked with developing a custom dashboard for monitoring an aircraft during a flight. Over the course of this threepart blog series, we'll see how to put together this dashboard by breaking it down into several simpler steps.
Here's a rough sketch of what we'll be laying out. We'll be including visualizations for tracking the aircraft during its flight, and flight instruments to display the flight data. There will also be some controls for configuring the appearance of the dashboard.
In this first blog post, we'll focus on creating an important part of the dashboard  a visualization to display a model of the aircraft together with its current attitude (roll, pitch, and yaw). We'll learn some general visualization techniques such as working with stereolithography (STL) files, 3D surfaces, and transforming 3D graphics.
In the next post in this series, we'll see how to encapsulate the 3D graphics and helper functions in a custom aircraft chart. This approach is more suited to modular application development. In the third and final post, we'll see how to connect the aircraft chart with other controls and displays in the final dashboard.
Let's get started!
Import and visualize a 3D aircraft model.
We need a 3D aircraft model for our dashboard, so let's download one. We'll download a generic airplane design by Yorchmur on
printables.com [1]. It's common for 3D models to be saved in
STL (stereolithography) files. These contain a surface triangulation (vertices, edges and faces) in a structured format. MATLAB provides the
stlread function for importing data from STL files.
The output of this function is a
triangulation, containing vertices, edges, and faces. A triangulation is an efficient way to represent a large or complex surface. The
Points property of the triangulation stores the vertices. The
ConnectivityList property specifies how the vertices are connected within the triangulation  each row of this matrix represents a triangle.
url = "https://files.printables.com/media/prints/34767/stls/343468_b085a064c28f4861b1a06a559929a7e2/avion31.stl";
opts = weboptions("ContentReader", @stlread);
disp(tr)
triangulation with properties:
Points: [261401×3 double]
ConnectivityList: [519617×3 double]
It's easy to visualize the 3D surface defined by this triangulation. Triangulations have several dedicated visualization functions, including
trisurf,
trimesh, and
triplot. We'll use
trisurf to render our aircraft using a smooth surface plot. In fact,
trisurf creates a
patch for optimal performance.
Improve the default 3D visualization of the aircraft.
We can see an aircraftshaped blob in our axes, but this visualization won't win any prizes. Let's improve our aircraft visualization by customizing some
axes and
patch properties. These objects are highly customizable  see
Axes Properties and
Patch Properties for further details.
We'll paint the aircraft, add lighting to the scene from directly above, and make the aircraft skin extra shiny using the
material function.
The lighting properties for
patch and
surface objects are only activated when there is a
light object in the axes. See
Lighting Overview for further details.
First, we'll create a twocolor scheme for painting the aircraft, using gray and blue. The colormap will have 500 points, comprising 250 gray and 250 blue points. This means that any point on the aircraft with zcoordinate below 500 will be colored gray, whereas any point with zcoordinate above 250 will be blue. The choice of 250 corresponds to the zcoordinate of the base of the aircraft's tail.
blue = [0, 0.447, 0.741];
gray = 0.95 * ones(1, 3);
onesMatrix = ones(250, 3);
paintJob = [gray .* onesMatrix; blue .* onesMatrix];
Here, the units are arbitrary and could be rescaled if needed.
Create the figure and axes.
ax = axes("Parent", f, ...
"Colormap", paintJob, ...
"DataAspectRatio", [1, 1, 1], ...
aircraft = trisurf(tr, "Parent", ax, ...
"FaceColor", "interp", ...
"FaceLighting", "gouraud");
title("Aircraft Attitude")
light(ax, "Position", [0, 0, 1])
Prepare the aircraft for geometric transformation.
Great, now we have a visualization of the aircraft that looks reasonable. However, the aircraft has a fixed attitude, with zero pitch, roll, and yaw. To visualize the changing attitude of the aircraft during a flight, we need the ability to set the pitch, roll, and yaw angles to any value.
We'll approach this task using a transform. In this context, a transform is a geometric operation such as a rotation, scaling, or translation applied to a graphics object within a 3D axes.
MATLAB provides the
hgtransform function to create transform objects. The idea is that the transform is a container in which we can place any number of 3D graphics objects. When we apply a geometric transformation on this container, it takes care of moving all its constituent graphics objects.
Rather than perform the calculations needed to update the coordinates of each graphics object when we want to apply a transform, we instead manipulate the Matrix property of the transform. This is a 4by4 matrix representing the required transform, with default value equal to the 4by4 identity matrix, representing the null transform.
For further details on how this matrix is used to transform objects in 3D coordinate systems, see Cleve's excellent blog posts (
[2] and
[3]) describing his interactive
Grafix tool.
Let's create a new transform in the axes, and place our aircraft inside.
tf = hgtransform("Parent", ax);
Adjust the aircraft's attitude using the transform.
We're now ready to adjust the aircraft's attitude. We'll use the three functions roll, pitch, and yaw defined below to do this. For example, here is the code listing for the roll function, which in turn relies on the rotate helper function.
The
roll function accepts the aircraft triangulation and an angle (specified in degrees). These values are passed onto the
rotate function, together with the string
"y", representing a rotation around the
yaxis. The
rotate function then converts the angle from degrees to radians (using
deg2rad) for compatibility with
makehgtform. This is a convenience function for creating the required 4by4 transformation matrix for a broad range of common operations, including the rotations we need to implement attitude adjustments to the aircraft. The
pitch and
yaw functions are implemented in a similar way.
As an example, the following code creates the transformation matrix representing a rotation of 15 degrees about the zaxis. This corresponds to changing the aircraft's yaw.
yawAdjustment = makehgtform("zrotate", deg2rad(15));
disp("Transformation matrix for a 15 degree rotation about the zaxis:")
Transformation matrix for a 15 degree rotation about the zaxis:
disp(yawAdjustment)
0.96593 0.25882 0 0
0.25882 0.96593 0 0
0 0 1 0
0 0 0 1
Next, apply this transformation to our aircraft. Note that if we want to apply a sequence of transformations represented by the matrices $ T_1, T_2, \dots, T_n $ to our aircraft, we multiply the transformation matrices on the right ($ T_1T_2\cdots T_n $) to accumulate the changes. This property of transformation matrices makes it easy to adjust the aircraft's attitude thoughout the flight.
tf.Matrix = tf.Matrix * yawAdjustment;
Finally, we'll use the roll function to create an animation of our aircraft performing a loop.
Summary
We've seen how to import STL model data into MATLAB and create a customized visualization of the corresponding 3D surface. We also introduced the concept of transforms, and how to use these to move 3D graphics objects around in a convenient way.
In the next post, we'll see how to encapsulate the 3D graphics and roll, pitch, and yaw functions in a custom aircraft chart. This approach is more suited to modular application development, and enables us to share the visualization with colleagues or embed it in a larger application.
Roll, pitch, and yaw functions.
function roll(aircraft, theta)
rotate(aircraft, theta, "y")
function pitch(aircraft, theta)
rotate(aircraft, theta, "x")
function yaw(aircraft, theta)
rotate(aircraft, theta, "z")
function rotate(aircraft, theta, rotationAxis)
aircraft(1, 1) matlab.graphics.primitive.Patch
theta(1, 1) double {mustBeReal, mustBeFinite}
rotationAxis(1, 1) string {mustBeMember(rotationAxis, ["x", "y", "z"])}
tf.Matrix = tf.Matrix * makehgtform(rotationAxis + "rotate", theta);
References
Comments
To leave a comment, please click here to sign in to your MathWorks Account or create a new one.