Background
A hardware in the loop simulation uses the real ArduPilot, your radio control unit, the servos and motors in an aircraft but the autopilot outputs are passed to a flight simulator which returns simulated sensor data.
A few years ago I used a highly modified version of the Ardupilot to control a Flight Gear simulation, but had modified the code almost beyond recognition and was running it natively on my PC instead of on an Arduino.
Recently I wanted to test some code that was intended for a real UAV so this wasn't an option, I spent a lot of time looking for up to date instructions but couldn't find any. Luckily I managed to get it working and thought I'd share how I did it.
I'm running this on Ubuntu Linux 12.04, but most of it should work on Windows or Mac but i've not tested it. I also notice that both the APM Mission Planner on Windows and QGroundControl have GUIs that are supposed to launch a simulator and do all of this for you, but I couldn't get either of them to work properly.
Step 1 - Modifying FGShim
These instructions are based upon using Ubuntu 12.04 with GCC 4.6, but they should work on any modern Linux distribution and with a little modification on OSX and Windows.
I found that there is a program called FGShim in the Tools/FlightGear directory inside the Ardupilot source. This program is supposed to sit between the Ardupilot and Flightgear, reading control surface commands from the Ardupilot via serial/USB and then relaying them to Flightgear via UDP and taking back Flightgear's position, velocity and orientation outputs and sending them back to the Ardupilot to form sensor data. However I couldn't get the version of FGShim included with Ardupilot (in December 2013) to compile and the MAVLink formats it was sending differed from those the rest of the Ardupilot code was expecting.
FGShim depends upon other components of the Ardupilot so you need the entire source tree to build it. You can get an updated version from my Github at https://github.com/colinsauze/ardupilot . To compile it run the following commands:
git clone https://github.com/colinsauze/ardupilot.git
cd ardupilot/Tools/FlightGear
make
There are still a few warnings produced by the compile process, but it should produce an executable called FGShim.
Step 2 - Setup Flight Gear
FlightGear is really extensible and every internal variable can be accessed through its property tree. Anything from the property tree can be exported or imported over a network link which is defined by an XML file. Included in the Tools/FlightGear directory (from https://github.com/colinsauze/ardupilot/tree/master/Tools/FlightGear) there is an XML file called MAVLink.xml.
To setup flight gear:
- Install Flight Gear from the normal Ubuntu repository
- Copy the MavLink.xml file to /usr/share/games/flightgear/Protocol (you'll need root access)
- Download the Rascal 110 model and extract the zip to /usr/share/games/flightgear/Aircraft
Step 3 - Build and flash the HIL autopilot
The Ardupilot will need to be flashed with different autopilot to normal.
- Setup the build environment by running the Tools/scripts/install-prereqs-ubuntu.sh script in the ardupilot directory.
Build the HIL version of the ardupilot by running: cd ArduPlane && make config && make apm2-hilsensors
The resulting hex file is placed in /tmp/ArdPlane.build/ArduPlane.hex
Flash it to the ArduPilot by connecting the ArduPilot and running: avrdude -pm2560 -cstk500v2 -P/dev/ttyACM0 -Uflash:w:/tmp/ArduPlane.build/ArduPlane.hex:i
Step 4 - Setup parameters
To make the aircraft fly properly I had to adjust some of the autopilot settings. These can either be adjusted by connecting a terminal emulator such a minicom or the internal terminal in QGroundControl to the ArduPilot. On my system this was on /dev/ttyACM0, baud rate 115200, 8 data bits, no parity, 1 stop bit. After connecting press enter a few times and you should get a prompt saying "ArduPlane V2.76]". At this type "setup" and press enter and then type "set" followed by a space, the parameter name, another space and the new parameter value. QGroundControl also presents a graphical user interface under its "Software" screen or its "Onboard Parameters" tool widget for setting these.
I played around quite a lot with the gains, TECS and throttle settings. It still doesn't fly perfectly and I notice that small (less than 1 degree) changes in roll and pitch take a long time to compensate for. But this doesn't affect the ability to fly around a set of waypoints.
Here is the full list of my settings:
RC2_REV -1 (For my remote I had to change the direction of the elevators which are on channel 2. There were 2 ways I could have done this, one was to reverse them using the radio control unit's own settings or I could change RC2_REV to -1)
PTCH2SRV_P 1.25
PTCH2SRV_I 0.2
PTCH2SRV_D 0
PTCH2SRV_IMAX 4000
RLL2SRV_P 1.25
RLL2SRV_I 0.2
RLL2SRV_D 0
RLL2SRV_IMAX 4000
TECS_CLIMB_MAX 12
TECS_SINK_MIN 5
TECS_TIME_CONST 6
THR_MIN 0
THR_MAX 75
TRIM_THROTTLE 25
ARSPD_FBW_MIN 17
ARSPD_FBW_MAX 27 (i'm unsure if these are actually working as i'm not sure airspeed is being used)
HIL_SERVOS 1 (only set this if you want servos and motors to actually turn)
BATT_MONITOR 4 (only set this if you want the battery monitoring of current and voltage, don't expect completely realistic figures from these as there is no load on the motors.)
Step 5 - Using with QGroundControl
While FGShim is connected it will occupy the serial connection to the ArduPilot and will stop working if anything else tries to connect. However it will relay MAVLink data over UDP to localhost on port 14550 and this can be picked up with QGroundControl or any other MAVLink viewer that supports on UDP. It will also accept commands on port 14551 which allows for mission plans and parameter changes to be sent.
I couldn't find a pre-compiled Linux version of QGroundControl so I had to build it from source and followed these instructions.
Upon starting up QGroundContorl choose a UDP Link on port 14550 and click connect. A few seconds after FGShim and FlightGear are started data should start to appear. I have found that some of the QGroundControl configuration options in the "Software" tab cause FGShim to crash when they send through changes. However the "Onboard Parameters" tool widget seems to work fine as does the "Flight Plan" tab, although a few of the options (such as the takeoff/landing requests) in the mission planner don't seem to have any effect.
Step 6 - Running everything together
- Start FlightGear by running the "./start_flightgear.sh" script inside the Tools/FlightGear directory of the Ardupilot source.
- Start FGShim by running "./FGShim /dev/ttyACM0" from inside the Tools/FlightGear directory of the Ardupilot source.
- (Optional) start QGroundControl and connect a UDP Link to port 14550.
Issues
- In manual mode I find that the aircraft tries to veer left a lot and needs a lot of trim and it gets worse as you increase the throttle speed. Fly by wire mode doesn't have this problem as is a lot easier to control.
- Some parts of QGroundControl that send messages back to the autopilot crash FGShim. You can always connect QGroundControl via the serial port for configuring things, disconnect it, restart FGShim and reconnect via UDP.
- Waypoint 0 always seems to get missed out. Is this normal ardupilot behaviour?
- Sometimes the altimeter miscalibrates, this is where starting the aircraft on the ground and at sea level helps. If this happens just press the reset button on the ArduPilot and watch the altitude with QGroundControl, a few seconds after the reset it should go to zero. If it doesn't try resetting again.
Comments
thanks so much for this tutorial!
It should be possible, but you'd need to find a suitable flight gear model and might have to modify the protocol a bit to transfer data about each rotor's speed instead of the elevator, ailerons, rudder and just one motor.
Is this setup possible to use also with multicopters or only planes?
It was a problem with the orientation solution, not the PIDs. The aircraft was much more banked than what the board was perceiving, so it could not compensate for the death spiral.
In other news, here's a report from a mister J. Matthew Holt, related to ROS and APM. I don't know where I found it, it's not on the internet anymore. I provide a temporary dropbox link. If it is against copyright, please let me know.
https://dl.dropboxusercontent.com/u/8286935/ROS%20Setup%20for%20UAV...
I've not had any problem with death spirals on banking, have you tried limiting the maximum roll rate? As for the reflashing problem, I don't see any other way to do it. The firmware needs to be quite different to read the sensor states from the USB port instead of the real sensors. If you flash the HIL firmware and try to fly for real it won't work as the APM won't initalise without the sensor data coming through, so its not like you can accidentally fly with it enabled (although it might be possible to do a manual flight).
With regards to ROS i've not used it so can't comment, but can't see any reason in theory why it wouldn't be possible.
I had done some HIL under Win8 with FG with some success. I used the Rascal 110 model as well. I, too noticed that it "pulled" to one side, but I believe this has to do with the aerodynamics model description and is not related to the APM.
Basic functions where working well; Take off, stabilization, waypoints etc. However, I noticed that in great bank angles the orientation solution would wind up and get dizzy. As a result, tight turns ended with large overshoots or even death spirals.
My biggest beef with HIL is that it requires re-flashing of the board each time you switch from real-life to HIL. This is a very weak link in the chain of reliability, IMO. If I had a second APM board I might have dedicated it to HIL solely. I wanted to try some Python scripting, but I may end up doing it in Software-In-the-Loop, for the aforementioned reasons.
I have seen a couple of papers presenting ROS integration. I don't have the links with me right now, I'll try to remember to post them once I get home. Mostly they do the interface with the MAVLink, so that ROS nodes can read the MAV state, make decisions about it and post navigation commands back via MAVLink.
Here are a couple of packages that advertise doing this, however I have not tried any of them:
https://github.com/pixhawk/mavlink-ros-pkg
http://code.google.com/p/roscopter/
In general, there has been a lot of work done in ROS related to multirotors. On fixed-win, not so much.
Thanks for the detailed explanation and information. Indeed a need information for developers. My question is can you make hardware in the loop simulations with Robot Operating System(ROS) or do you have any information about it?