Overview
As a middleground between unit testing and uploading our code to the aircraft to see if it works, we’re implementing simulations into our pipelines. At a very high level, the simulation code interacts with our ZeroPilot code and produces step by step graphs of various aircraft metrics over time, to give an idea of how a real airplane might behave.
What’s going on ?
You can think of the entire simulation setup as being made up of 4 components.
The DatCom files
The Simulink model
The generated C++ files
The ZeroPilot-SW hooks
The Datcom files
We need some way of translating an aircraft geometry into a usable description of how that aircraft behaves under different circumstances in the air. Digital DatCom (data compendium) is a program developed by the US air force that does just that. It was made open source for the public to use years ago.
The compiled digital datcom exe exists in Simulink-Sim\Spike\SimulinkModel\datcomFiles. Linux and MaCos versions exist, but only the windows executable is in our repo.
The program takes as input a “.in” file (at this time we are using cessna172.in) that describes the aircraft’s geometry and outputs a file named datcom.out which contains tables of the coefficients that describe the aerodynamics of the aircraft. these coefficients are calculated for multiple altitudes, angles of attack, mach numbers, actuator positions and a few other things. Matlab can import the datcom.out file into it’s workspace.
The Simulink model
Inside Simulink-Sim\Spike\SimulinkModel, is a file named Spike.slx. This file contains the Simulink model. open it with Matlab to see the block model. Here’s the summary of what’s going on:
Read ZeroPilot-SW commands
On the top left of the model, there are a series of blocks named read*. These blocks read the latest actuator and throttle commands that the autopilot produces and feed them into the model at every time step.
Figure out the appropriate coefficients.
You’ll notice that the read* blocks feed into a block named aerodynamic coefficients. If you double click it, you can take a look.The appropriate coefficients are determined by using the data about actuator position, altitude, mach number, etc, and performing a linear interpolation inside the datcom tables.
From those coefficients, determine the forces and moments
The coefficients that were just determined are fed into a block named aerodynamic forces and moments. This is a built in Simulink block. It doesent actually do anything special. Once you have the coefficients, getting the forces and moments is just a matter of multiplying each one with the wing area (or reference span or some other area) and the dynamic pressure. Now we know the 3D forces and moments that act on the aircraft as result of the actuators.
At the same time, the coefficients that occur as a result of non actuator related reasons are computed.
In the bottom left of the model, there’s a bunch more lookup tables that feed into another aerodynamic forces and moments block. This accounts for the forces that act on the aircraft that are not related to the actuators. Things like the lift produced by the wings and the drag force resulting from the aircraft flying through the air.
The actuator and non actuator forces and moments, aswell as the propulsion and gravity forces are summed together.
Couple notes here. The gravity vector needs to be converted from the inertial to the body reference frame, so it is multiplied by the appropriate direction cosine matrix. The throttle force always points “forward” as far as the aircraft is concerned so no adjustment is necessary. Also, since both the gravity and throttle vectors point through the center of gravity of the aircraft, neither force produces a moment.
The position, orientation, velocity vector, and all kinds of other stuff about the aircraft are computed.
The summed forces and moments are fed into the 6 dof block. This block is pretty magical. with all kinds of integration and other crap that doesent actually need to be known by the person using it, it figures out how that body behaves. THis block also contains the initial state of the body. Information like initial velocity, initial orientation, initial position, mass and moment of inertia tensor are specified here.
The information output by the 6 dof block is fed into the writeToFile block.
This block just writes all the important info that gets fed back into our ZeroPilot-SW to files.
Side note: there are a couple of blocks in the left middle of the model. They do very simple processing to calculate airspeed, mach number and dynamic pressure.
The generated C++ files
If you click the the generate code button on Simulink,
it outputs a zipped folder. The contents of that folder are unzipped and stored inside Simulink-Sim\Spike\GeneratedCCode. The only interesting files to look through are Simulink-Sim\Spike\GeneratedCCode\SimulinkModel\Spike_grt_rtw\Spike.h and Simulink-Sim\Spike\GeneratedCCode\SimulinkModel\Spike_grt_rtw\Spike.cpp. Although they are not very readable, so it’s not necessary to understand them, they do the same thing as the simulink model. And everytime Spike.step() is called, one step is performed. (The time that one step corresponds to can be changed inside the simulink model, before the code is generated).
The ZeroPilot-SW hooks
These “hooks” are c++ files that provide a way for the autopilot Sw to communicate with the simulation files without actually knowing that that it’s not talking to real hardware. They exist in Simulink-Sim\Spike\ZeroPilotSwHooks. They are implementations of the sensor classes and the SendToSafety functions. THey are pretty simple, so looking at the files should explain what they do, but long story short, the sendToSafetyIntercept implementation writes the actuator and throttle commands to files that the generated C++ files read and the sensor intercepts collect the data from the files that the generated C++ code writes to.
0 Comments