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.