This blog post contains my notes to run an instance of the Software In The Loop (SITL) flight simulator in Docker and how to connect Mission Planner to monitor and interact with vehicle status and data of flight during simulated missions.

The entry also describes how to plan an arbitrary test mission through the flight plan interface offered by Mission Planner.

The MAV Tools, a number of command-line and visual tools for real-time and offline data analysis and plotting, are also used on the data generated by the test mission.

Running the SITL in Docker

The SITL simulator allows you to simulate a vehicle (plane, helicopter or rover) without any hardware.

The SITL is a build of the autopilot code that uses an ordinary C++ compiler. The output of the compilation is a native executable that can be used to test the behavior of the code without hardware.

In our case, we are interested in running the SITL in Docker with the intention of decoupling the operating system from the application and leveraging some of the benefits of this container technology (simplicity, rapid deployment, isolation, CI/CD, testing, etc.)

There are several projects supporting the SITL in Docker. In this entry I will use the Docker4SITL project.

You can run the following commands to pull and build Docker4SITL:

$ git clone https://github.com/mickaelbaron/docker4sitl.git
Cloning into 'docker4sitl'...
remote: Counting objects: 35, done.
remote: Total 35 (delta 0), reused 0 (delta 0), pack-reused 35
Unpacking objects: 100% (35/35), done.
$ cd docker4sitl
~/docker4sitl$ docker build -t docker4sitl src/.
[...]
~/docker4sitl$

The Docker4SITL image is built on top of Ubuntu 16.04:

~/docker4sitl$ docker images
REPOSITORY        TAG               IMAGE ID          CREATED           SIZE
docker4sitl       latest            9dd024a3bfb9      11 seconds ago    2.05GB
ubuntu            16.04             5e8b97a2a082      7 days ago        114MB

We will use the following command to start a simulation of a 'plane' vehicle with 'console' and 'map' support in Docker:

~/docker4sitl$ ./startSITLSimulator_Linux.sh plane --console --map

We can type the following commands to run the 'CMAC-toff-loop.txt' mission:

MANUAL> wp load ../Tools/autotest/ArduPlane-Missions/CMAC-toff-loop.txt
MANUAL> arm throttle
MANUAL> mode auto
AUTO>

The virtual aircraft will takeoff and follow the planned waypoints in a loop.

After the simulation two interesting directories are available on the host: 'build_sitl' and 'logs'.

The 'build_sitl' directory contains the compilation result for the targeted vehicle, while the 'logs' directory contains the state and logs.

$ ls logs
2018-06-08
$ ls logs/2018-06-08/
flight1
$ ls logs/2018-06-08/flight1
flight.tlog  flight.tlog.raw  mav.parm  way.txt

Setting up Mission Planner

At this point we are interested in configuring Mission Planner as the Ground Control Station. This will allow us to have a powerful graphical user interface not only to monitor the missions and flight parameters but also the state of the vehicle. In general, we will work with the flight data and flight plan interfaces.

We will connect the SITL to Mission Planner over UDP/IP. If we are running the Mission Planner in a box with IP 10.10.10.10 and default UDP port 14550, we will add the proper output in the SITL side:

AUTO> output
2 outputs
0: 127.0.0.1:14550
1: 127.0.0.1:14551
AUTO> output add 10.10.10.10:14550
Adding output 10.10.10.10:14550
AUTO> output
3 outputs
0: 127.0.0.1:14550
1: 127.0.0.1:14551
2: 10.10.10.10:14550
AUTO>

In the Mission Planner side, we will click on "Connect" in the upper right corner. Then we accept the default local port 14550 in the pop-up window.

In this point SITL is connected to Mission Planner by using MAVProxy. The graph shows how Mission Planner tracks the loop mission ('CMAC-toff-loop.txt') used in the previous point.

The Mission Planner source code is available here.

Planning a mission with waypoints and events

We are not only interested in inspecting and interacting with flight data through Mission Planner. The capabilities of this GCS to design and plan missions in graphic form are also very interesting.

With Mission Planner it is very easy and straightforward to plan an arbitrary mission with waypoints and events at the same time that you inspect and iterate over the details until you meet the required requirements.

The following screenshot shows the plan for the 'CMAC-toff-loop.txt' mission with which we are working on the GCS flight plan interface.

In particular, it is interesting to observe how the commands and the different values of the flight plan parameters are available for inspection and modification through the waypoints table.

As a test, we will extend the current mission based on an infinite loop between waypoints 2 and 5 so that this loop consists of only three iterations.

We will also add an extra waypoint to do an altitude test in which the vehicle descends to 50 meters and then ascend again to 100 meters.

The last two modifications to the flight plan consist of the vehicle making three turns at an altitude of 25 meters and a loitering ratio of 50 meters before landing.

The new waypoints and events for the mission are the following:

The new flight path in graphic form:

The output of the 'wp list' command in MAVProxy for this new mission is available here.

The new mission saved in the recommended waypoint file format is available here.

Loading and executing the mission

To load the test mission planned in the previous point we can do it from the flight plan interface. In the right part of this window we can use the options 'Load WP File' and 'Write WPs' to make the mission available to the simulator from the GCS.

We should see something similar to the following:

To execute the mission in Mission Planner the high level actions 'Arm' and 'Auto' start the process.

Visually we can verify that the new mission crosses all the waypoints established in the flight path.

We can also check that the vehicle descends at an altitude of 50 meters to go through waypoint 3 and then go back up to 100 meters.

The three turns are also observed at an altitude of 25 meters with a loitering ratio of 50 meters around the coordinates of waypoint 6.

To finally take land as planned.

MAV Tools

As we mentioned in the beginning of this entry, PyMAVLink provides a number of command-line and visual tools for real-time and offline data analysis and plotting. You can get the latest pymavlink code as part of the mavlink source here.

In our case, the MAV Tools are already installed and available in Docker4SITL:

root@0b6b28faf497:/ardupilot/ArduPlane# mav
mavextract.py      mavgen.py          mavmission.py      mavsigloss.py
mavfft.py          mavgpslock.py      mavparmdiff.py     mavsummarize.py
mavfft_isb.py      mavgraph.py        mavparms.py        mavtogpx.py
mavflightmodes.py  mavkml.py          mavplayback.py     mavtomfile.py
mavflighttime.py   mavlogdump.py      mavproxy.py
mavflightview.py   mavloss.py         mavsearch.py

Note that to use the MAV Tools in Docker4SITL you may need to modify startSITLSimulator_Linux.sh to obtain an interactive shell. This modification in the configuration of the script should be enough.

Some of the most versatile and interesting MAV Tools are the following:

  • mavextract.py. Allows to extract one flight mode from the rest of the log
  • mavflightmodes.py. Prints out the timestamp and name of each flight mode change in a logfile
  • mavflighttime.py. Prints out the total time spent in the air
  • mavflightview.py. Allows to show the GPS position in an image
  • mavgraph.py. Graph any of the flight data
  • mavlogdump.py. Allows to convert a binary log into a readable file
  • mavparms.py. Finds the flight parameters in a logfile and displays them on the console.
  • mavproxy.py. Minimalist, portable and extendable GCS for any UAV supporting the MAVLink protocol
  • mavtogpx.py. Exports the GPS data from a logfile and create a GPX file, which can be read by Google Earth
  • mavtomfile.py. Converts a MAVLink log file to a MATLab mfile

Some examples of these tools running on the log of our test mission:

$ mavsummarize.py flight.tlog
Processing log flight.tlog
Log started at about 2018-06-08 21:44:44
Travelled from (-35.3632608, 149.1652351) to (-35.3641824, 149.1656157)
Total distance : 9550.21m
Total time (mm:ss):  33:50
Autonomous sections: 1
Autonomous time (mm:ss):   9:54
===============================
Num Flights : 1
Total distance : 9550.21m
Total time (mm:ss):  33:50
$ mavflightmodes.py flight.tlog
Processing log flight.tlog
Fri Jun 8 21:44:45 2018 MAV.flightmode=INITIALISING (MAV.timestamp=1529012685 0%)
Fri Jun 8 21:44:47 2018 MAV.flightmode=MANUAL       (MAV.timestamp=1529012687 0%)
Fri Jun 8 21:47:37 2018 MAV.flightmode=AUTO         (MAV.timestamp=1529012857 9%)
Fri Jun 8 21:56:31 2018 MAV.flightmode=MANUAL       (MAV.timestamp=1529013391 38%)

Time per mode:
INITIALISING 0:00:01 0.20%
AUTO         0:08:53 58.23%
MANUAL       0:06:21 41.57%
$ mavflighttime.py flight.tlog
Processing log flight.tlog
In air at Fri Jun 8 21:47:38 2018 (percent 10% groundspeed 3.4)
On ground at Fri Jun 8 21:55:07 2018 (percent 33.9% groundspeed 2.9  time=449.0 seconds)
Flight time : 7:29
Total time in air: 7:29
Total distance travelled: 9550.2 meters
$ mavflightview.py flight.tlog

$ mavparms.py flight.tlog > mavparms.txt
$ cat mavparms.txt | wc -l
922

The full mavparms.py output is available here.

$ mavlogdump.py flight.tlog
[...]
2018-06-08 22:17:33.68: AHRS {omegaIx : -0.00177069276106,
                              omegaIy : -0.00169478484895,
                              omegaIz : -0.00163174816407,
			      accel_weight : 0.0,
			      renorm_val : 0.0,
			      error_rp : 0.0023727833759,
			      error_yaw : 0.00149314152077}
2018-06-08 22:17:33.68: HWSTATUS {Vcc : 5000,
                                  I2Cerr : 0}
2018-06-08 22:17:33.68: WIND {direction : 148.563568115,
                              speed : 0.849624335766,
			      speed_z : 0.0}
2018-06-08 22:17:33.68: SYSTEM_TIME {time_unix_usec : 1529014640720000,
                                     time_boot_ms : 1956735}
2018-06-08 22:17:33.68: TERRAIN_REPORT {lat : -353641822,
                                        lon : 1491656153,
					spacing : 100,
                                        terrain_height : 583.031311035,
					current_height : -0.190122067928,
					pending : 0,
					loaded : 504}
2018-06-08 22:17:33.68: BATTERY_STATUS {id : 0,
                                        battery_function : 0,
					type : 0,
                                        temperature : 32767,
					voltages : [65535,
					            65535,
						    65535,
						    65535,
						    65535,
						    65535,
					            65535,
						    65535,
						    65535,
						    65535],
				        current_battery : 0,
					current_consumed : 2885,
					energy_consumed : 1270,
					battery_remaining : 12}
2018-06-08 22:17:33.68: EKF_STATUS_REPORT {flags : 831,
                                           velocity_variance : 0.00928787514567,
                                           pos_horiz_variance : 0.00381638645194,
					   pos_vert_variance : 0.00595173519105,
					   compass_variance : 0.00369726493955,
					   terrain_alt_variance : 0.0}
2018-06-08 22:17:33.68: VIBRATION {time_usec : 1956735326,
                                   vibration_x : 0.00578315602615,
                                   vibration_y : 0.00582167133689,
				   vibration_z : 0.0055188969709,
				   clipping_0 : 0,
				   clipping_1 : 0,
				   clipping_2 : 0}
2018-06-08 22:17:33.76: HEARTBEAT {type : 1,
                                   autopilot : 3,
				   base_mode : 81,
				   custom_mode : 0,
                                   system_status : 3,
				   mavlink_version : 3}
2018-06-08 22:17:33.76: HOME_POSITION {latitude : -353641822,
                                       longitude : 1491656153,
                                       altitude : 583570,
				       x : 0.0,
				       y : 0.0,
				       z : 0.0,
				       q : [1.0,
				            0.0,
					    0.0,
					    0.0],
				       approach_x : 0.0,
				       approach_y : 0.0,
				       approach_z : 0.0}

Finally we can use the MAVExplorer tool, also included in Docker4SITL, to visualize the mission from a point of view of the altitude of the vehicle with respect to the time along the automatic flight mode.

In the graphic you can identify the most characteristic stages and events of the mission. A fast ascent at takeoff, followed by a loop stage with three steep peaks at 50 meters (waypoint 3) and corresponding circle turns at an altitude of 25 meters (waypoint 6 coordinates) prior to descent and landing.

Wrapping up

Having SITL and Docker working in tandem allows not only to program aspects of the autopilot in isolation but also to have control over the configuration of the environment and the context in which the mission will be carried out.

The execution of SITL in Docker increases the flexibility in the development and testing of new guidance, navigation and control algorithms. This approach can also be very useful for the execution of simulated missions and the collection of data generated by them.

In relation to Mission Planner, the graphical user interfaces related to the flight data and the mission plan are really intuitive and easy to use. This GCS covers the need to have a good graphic tool that speeds up and makes mission planning viable manually.

Finally MAV Tools provides a mature analysis toolkit that has the ability to automate the extraction and processing of mission data in real-time and off-line.

Comments

comments powered by Disqus

Recent Entries