Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Overview

As a middleground middle ground 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 when controlled by our flight computer.

...

intercepts all calls Autopilot makes to external hardware devices and puts them through the Simulink model instead. Every iteration of the Path Manager and Attitude Manager state machines corresponds to 1 “time step” and thus produces 1 piece of data that contains the aircraft’s position, attitude, airspeed and a few other pieces of info. Once a given number of time steps are run, we can then piece together the aircraft’s response to the given commands and thus tweak the autopilot software accordingly (For instance adjust the PID gains for a particular aircraft). To avoid too many crashes and frustrations, before autopilot flies the aircraft for real, it needs to fly it in Simulation.

Image Added

The above diagram shows how the Simulink model interacts with Autopilot (as opposed to the diagram in Autopilot architecture that shows what Autopilot looks like for real). As can be seen, there is no hardware anywhere here. All actuator commands are sent into the model, which figures out how the plane behaves and reinjects the data of the plane’s current behavior into Autopilot as if it was sensor data. The flight path needs to be hard coded ahead of time, however, but may be screwed around with depending on what you want to Simulate (holding patterns, way point navigation, back flips, attacks on Isis, etc).

User’s perspective (how to use the Simulation)

After cloning the Simulink-Sim repo into the same directory as ZeroPilot-SW, downloading FlightGear , and moving the FlightGear protocol file into the appropriate directory (protocol directory of FlightGear ) all you need to do is start FlightGear with the start script in Simulink-Sim/FlightGear and run the usual build script with the -s option. This will execute the simulation and send everything over to FlightGear for display of the results.

If you wish to change the simulation parameters, you may modify the the flight path file as you wish. Doing something like simulating takeoff or landing would require some minor modification of the Simulink model (as its currently rigged to initialize the airplane in level flight at cruising speed).

Ok, so what the hell is going on under the hood ?

You can think of the entire simulation setup as being made up of 4 5 components.

...

Table of Contents

The

...

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\SpikeInfinion\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 cessna172Infinion.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 These coefficients are calculated for multiple altitudes, angles of attack, mach numbers, actuator positions and a few other things. Scroll through this file to see the tables, it’s pretty cool. Matlab can import the datcom.out file into it’s its workspace.

A quick explanation of what these coefficients are:

...

Reading through that second link should allow you to understand what’s going on. The couplethings 2 things that are missed are the SYMFLP and ASYFLP (synchronous and asynchronous flaps) that are used to describe the elevator and ailerons. Unfortunately, datcom does not provide this capabillity for rudderscapability for rudders but we currently get around this by modelling a second “elevator” with the dimensions of our rudder, then we substitute angle of attack for side slip angle and feed in rudder commands rather than elevator commands and that achieves acceptable functionality.

The other thing you might find weird is that our datcom file has 2 3 cases even though we are just describing 1 aircraft. This was a hack; for some reason, having aileron, elevator, and elevators rudder in the same case did not give out all the coefficients, so I created 2 3 cases, one with ailerons, one with elevators and one with elevators. matlab knows about second elevator (rudder). The simulink model considers this, that’s why the lookup tables that use rudder reference aero{3}, those that use aileron reference aero{2} and those that use elevator reference aero{1}.

The Simulink model

Inside Simulink-Sim\SpikeInfinion\SimulinkModel, is a file named SpikeInfinion.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:

  • Import Datcom file into the workspace

    • This is currently a manual process and needs to be done once everytime every time the model is opened. TO To do it, cd into Simulink-Sim\Spike\SimulinkModel\Utilities from the matlab comand line, and run “aero = importAndFixDatcomData()” from the matlab command line.

    • For curiosity’s sake, the “fix” part of the function is there because for some bizarre reason, Datcom fails to generate a very few number of coefficients. So in those cases, the coefficients that fail to generate are replaced with the coefficient of the previous altitude or mach number or angle of attack or whatever.

  • 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. The whole SeperateYawAndPitch block is there because our code thinks it’s controling Spike, which is an airplane with ruddervators, while the model models a cessna 172, which is an aircraft with a conventional tail.

  • 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 to get the closest coefficient to the circumstances.

  • 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 doesn't 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. I just didnt didn't put these in a clean simulink subsystem yet, which is why the lookup tables are exposed rather than in a block.

  • The actuator and non actuator forces and moments, as well 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 doesn't actually need to be known by the person using it, it figures out how the body behaves. (You’l learn a bit about how this kind of block numerically solves differential equations if you ever take a numerical analysis course). 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, sideslip angle, angle of attack, mach number and dynamic pressure.

  • Side note 2, there is a block between 6 dof and writeToFile that takes care of figuring out the gps coordinates based on the position.

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\SpikeInfinion\GeneratedCCode. The only interesting files to look through are Simulink-Sim\SpikeInfinion\GeneratedCCode\SimulinkModel\SpikeInfinion_grt_rtw\SpikeInfinion.h and Simulink-Sim\SpikeInfinion\GeneratedCCode\SimulinkModel\SpikeInfinion_grt_rtw\SpikeInfinion.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 SpikeEverytime Infinion.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).

...

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\SpikeInfinion\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++ code reads and the sensor intercepts collect the data from the files that the generated C++ code writes.

The flight gear communication channel

Once the simulation has finished running and all the data points are produced, we need some way of visualizing what happened. We do so in the open source FlightGear program, which takes as input aircraft attitude and position and provides an actual visualization of an aircraft flying over scenery.

We send this data over via UDP packets. The data contained in these packets is in a custom format specified by Simulink-Sim\FlightGear\WargFGPacketStructure.xml. The program that collects the data from the Simulation’s output files, encodes them in UDP packets and transmits those packets to flight gear exists in Simulink-Sim\FlightGear\SendToFlightGear. It gets compiled and run as part of the -s option.

At this time, it sends the packets to a certain port at the localhost IP address. There is potential for sending them to some remote computer in the future, if the need arises.