1 Create a Personal Workspace - api.ning.comapi.ning.com/.../CustomArduinoCodeWikiDraft.docx · Web...

21
Rick Calder [email protected] Forrest Frantz [email protected] Ver: June 30, 2013 *****DRAFT***** THE HOW-TO FOR CUSTOM CODE Mission Planner, MP, upon user direction, uploads the correct pre- compiled firmware to your computer and then downloads that code to the APM on your copter. But, what if you need to tweak the firmware before uploading it to the APM? Maybe the layout of your motors do not form a regular polygon. This document describes how to get, modify, compile, and upload the ArduCopter source files. The example used is for motor mapping when motor layout deviates from standard. It is based on the AC3.0-rc5 release. The following instructions are for a Windows system. The topics discussed are: 1. Creating your personal workspace for the code. 2. Downloading the source files to create custom firmware. 3. Modify the code (an example is given on how to change the motor definitions for a custom frame). 4. Downloading the firmware compiler. 5. Configuring the compiler to your workspace. 6. Verifying code. 7. Compiling and uploading code to your multi-copter’s APM. 8. Validating the code. 9. Maintaining the code. 1 Create a Personal Workspace

Transcript of 1 Create a Personal Workspace - api.ning.comapi.ning.com/.../CustomArduinoCodeWikiDraft.docx · Web...

Page 1: 1 Create a Personal Workspace - api.ning.comapi.ning.com/.../CustomArduinoCodeWikiDraft.docx · Web viewFor the best read of the file, within Word Pad you might also want to do File»Page

Rick Calder [email protected]

Forrest Frantz [email protected] Ver: June 30, 2013

*****DRAFT*****

THE HOW-TO FOR CUSTOM CODE

Mission Planner, MP, upon user direction, uploads the correct pre-compiled firmware to your computer and then downloads that code to the APM on your copter. But, what if you need to tweak the firmware before uploading it to the APM? Maybe the layout of your motors do not form a regular polygon.

This document describes how to get, modify, compile, and upload the ArduCopter source files. The example used is for motor mapping when motor layout deviates from standard. It is based on the AC3.0-rc5 release. The following instructions are for a Windows system.

The topics discussed are:

1. Creating your personal workspace for the code.2. Downloading the source files to create custom firmware.3. Modify the code (an example is given on how to change the motor definitions for a custom frame).4. Downloading the firmware compiler.5. Configuring the compiler to your workspace.6. Verifying code.7. Compiling and uploading code to your multi-copter’s APM.8. Validating the code.9. Maintaining the code.

1 Create a Personal Workspace

Create a new, empty folder for your work. This workspace can be anywhere, but it is best if it is under your documents, not the program directory. For example, under My Documents, create a directory called Copter and under that a directory called ArduCopter Code. The result would be

My DocumentsCopterArduCopter Code

This is where you will upload and maintain your custom code.

Page 2: 1 Create a Personal Workspace - api.ning.comapi.ning.com/.../CustomArduinoCodeWikiDraft.docx · Web viewFor the best read of the file, within Word Pad you might also want to do File»Page

2 Download the Source Code

Download the source files from the git repository.

Go to the git repository at

https://github.com/diydrones/ardupilot/ Select the latest version in the branch: master selection. Click on the Download ZIP button, to

download of a single zip file containing all of the source directories and files.

The downloaded file will be called ardupilot-ArduCopter-[ver].zip.

Unzip and Save the file to your new folder after the download is complete. o After the download, the file may end

up in your Download directory.o Double click ardupilot-arduCopter-

3.0.zip to Extract All. In Windows 8, if you click on the folder ‘Downloadardupilot-ArduCopter-3.0’, you will see at the top of the Windows Explorer screen, ‘Compressed Folder Tools’. Just under that click on Extract»Extract All»Browse to your workspace (in this case CopterArduCopter Code), and then, OK»Extract, which also completes the next copy or move step.

o You will then have these directories and files.

Page 3: 1 Create a Personal Workspace - api.ning.comapi.ning.com/.../CustomArduinoCodeWikiDraft.docx · Web viewFor the best read of the file, within Word Pad you might also want to do File»Page

If the files unzipped in the Download directory, move or copy the ardupilot-ArduCopter-3.0 directory to your work space. The following shows moving the directory using Windows Explorer from the Download directory to the previously created work space (in this case to My DocumentsCopterArduCopter Code).

Page 4: 1 Create a Personal Workspace - api.ning.comapi.ning.com/.../CustomArduinoCodeWikiDraft.docx · Web viewFor the best read of the file, within Word Pad you might also want to do File»Page

3 Modify the Source Code

If you are a professional C++ programmer and are not modifying code for a custom motor configuration, skip to Chapter 4.

An example is used to demonstrate how to modify the source code. This example is the case where the motor locations are custom and the pilot needs to modify the motor definitions for an octa-multicopter.

Locate the two files of interest: ‘AP_MotorsOcta.h’ and ‘AP_MotorsOcta.cpp’, the file that defines each motor parameter. It is this latter file that needs to be changed.

Open the Ardupilot-ArduCopter-3.0librariesAP_Motors directory. Ensure that Windows Explorer is showing the file extensions because

each configuration has two associated files, one with a ‘.cpp’ extension and the other with a ‘.h’ extension. To tell Windows to show all extensions, change the file viewing options in Windows Explorer to see the file extensions. In Windows Explorer 7, Organize»File and search options (in Explorer 8, View»Options), then in the View tab uncheck ‘Hide extensions for known file types’. Click Ok and then you will see the file extensions (in Explorer 8, Apply to Folders»Apply to All Folders).

You should see the two files with their extensions. Open AP_MotorsOcta.cpp—Right –click on the file, select ‘Open with’

and choose WordPad. You may have to ‘Choose default program…’ in order to then select WordPad. If you select Notepad, you will probably see just one or two long lines along the top – Notepad cannot handle the text format of these files.

For the best read of the file, within Word Pad you might also want to do File»Page Setup and change the orientation to landscape and margins to 0.3.

Page 5: 1 Create a Personal Workspace - api.ning.comapi.ning.com/.../CustomArduinoCodeWikiDraft.docx · Web viewFor the best read of the file, within Word Pad you might also want to do File»Page

You will see the following C code (don’t panic): [TBD code edit to accept quads, hexas, and octas].

// -*- tab-width: 4; Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*-/* * AP_MotorsOcta.cpp - ArduCopter motors library * Code by RandyMackay. DIYDrones.com * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. */

#include "AP_MotorsOcta.h"

// setup_motors - configures the motors for a octavoid AP_MotorsOcta::setup_motors(){ // call parent AP_MotorsMatrix::setup_motors();

// hard coded config for supported frames if( _frame_orientation == AP_MOTORS_PLUS_FRAME ) { // plus frame set-up add_motor(AP_MOTORS_MOT_1, 0, AP_MOTORS_MATRIX_YAW_FACTOR_CW, 1); add_motor(AP_MOTORS_MOT_2, 180, AP_MOTORS_MATRIX_YAW_FACTOR_CW, 5); add_motor(AP_MOTORS_MOT_3, 45, AP_MOTORS_MATRIX_YAW_FACTOR_CCW, 2); add_motor(AP_MOTORS_MOT_4, 135, AP_MOTORS_MATRIX_YAW_FACTOR_CCW, 4); add_motor(AP_MOTORS_MOT_5, -45, AP_MOTORS_MATRIX_YAW_FACTOR_CCW, 8); add_motor(AP_MOTORS_MOT_6, -135, AP_MOTORS_MATRIX_YAW_FACTOR_CCW, 6); add_motor(AP_MOTORS_MOT_7, -90, AP_MOTORS_MATRIX_YAW_FACTOR_CW, 7); add_motor(AP_MOTORS_MOT_8, 90, AP_MOTORS_MATRIX_YAW_FACTOR_CW, 3);

}else if( _frame_orientation == AP_MOTORS_V_FRAME ) { // V frame set-up add_motor_raw(AP_MOTORS_MOT_1, 1.0, 0.34, AP_MOTORS_MATRIX_YAW_FACTOR_CW, 7); add_motor_raw(AP_MOTORS_MOT_2, -1.0, -0.32, AP_MOTORS_MATRIX_YAW_FACTOR_CW, 3); add_motor_raw(AP_MOTORS_MOT_3, 1.0, -0.32, AP_MOTORS_MATRIX_YAW_FACTOR_CCW, 6); add_motor_raw(AP_MOTORS_MOT_4, -0.5, -1.0, AP_MOTORS_MATRIX_YAW_FACTOR_CCW, 4); add_motor_raw(AP_MOTORS_MOT_5, 1.0, 1.0, AP_MOTORS_MATRIX_YAW_FACTOR_CCW, 8); add_motor_raw(AP_MOTORS_MOT_6, -1.0, 0.34, AP_MOTORS_MATRIX_YAW_FACTOR_CCW, 2); add_motor_raw(AP_MOTORS_MOT_7, -1.0, 1.0, AP_MOTORS_MATRIX_YAW_FACTOR_CW, 1); add_motor_raw(AP_MOTORS_MOT_8, 0.5, -1.0, AP_MOTORS_MATRIX_YAW_FACTOR_CW, 5);

}else { // X frame set-up add_motor(AP_MOTORS_MOT_1, 22.5, AP_MOTORS_MATRIX_YAW_FACTOR_CW, 1); add_motor(AP_MOTORS_MOT_2, -157.5, AP_MOTORS_MATRIX_YAW_FACTOR_CW, 5); add_motor(AP_MOTORS_MOT_3, 67.5, AP_MOTORS_MATRIX_YAW_FACTOR_CCW, 2); add_motor(AP_MOTORS_MOT_4, 157.5, AP_MOTORS_MATRIX_YAW_FACTOR_CCW, 4); add_motor(AP_MOTORS_MOT_5, -22.5, AP_MOTORS_MATRIX_YAW_FACTOR_CCW, 8); add_motor(AP_MOTORS_MOT_6, -112.5, AP_MOTORS_MATRIX_YAW_FACTOR_CCW, 6); add_motor(AP_MOTORS_MOT_7, -67.5, AP_MOTORS_MATRIX_YAW_FACTOR_CW, 7); add_motor(AP_MOTORS_MOT_8, 112.5, AP_MOTORS_MATRIX_YAW_FACTOR_CW, 3); }}

Page 6: 1 Create a Personal Workspace - api.ning.comapi.ning.com/.../CustomArduinoCodeWikiDraft.docx · Web viewFor the best read of the file, within Word Pad you might also want to do File»Page

Familiarize yourself with the layout of the code. o There are comment lines that help explain what each line of code does.

Lines starting with // starts a comment that ends on that line. Lines starting with /* starts a comment that continues for several lines until a */, which ends

the comment. Sometime coders start with a * before the lines in between to improve looks.o There are variables with friendly pet names (usually lower case), like _frame_orientation, which

you’ve wisely guessed is the setting you choose to describe copter orientation (+ or X or V).o There are constant definitions with formal names (normally upper case), like

AP_Motors_Plus_Frame. This allows code to compare _fruit (a variable that can be 1 for apples or 2 for bananas) to APPLES (a constant that may = 1) to see if the fruit really is an apple. Also, constants might be used to help translate code compiler talk. A human naturally calls the first motor 1, but a code compiler wants the first item called zero. So the coder defines a variable _MOT_1 (what we see in code) as equaling 0, what the compiler sees.

o Then there is code to respond properly to each frame type (like what to do for a + or a X or a V frame). In this program, the author uses ‘if’ statements to do that. ‘If’ statements look like:

if ( this is true ) { do what is between the first set of brackets }

else if ( this other thing is true ) { do what is between the second set of brackets }

else ( in all other cases ) { do what is between the third set of brackets }

o Note that after each ‘if’ section that there are 8 lines of code—one for each motor of the octa copter. That is what needs to be changed for a custom copter with motors that either: Have angles that are not the same between them (modify the X code). Have distances from the center of gravity that are not the same (modify the V code even if

the copter is a +, X, H, U or other non-coaxial ship).o For the X and + frame sections of code, the lines of code are ADD_MOTOR commands that have

the following format (you will only need to change what is in red): [TBD may eliminate since this is somewhat redundant to the real issue of distances from CG in favor of add_motor_raw] add_motor(O, A, C, T) where:

O = the APM output pin,

A = the angle from forward in degrees,

C = the prop spin direction _CW (clockwise) or _CCW (counter clockwise),

T = the test order used by the CLI when spinning the motors during test which is usually its physical position on the copter starting with forward or forward right as 1 and the going

clockwise around the copter for 2 through 8); for example, add_motor(AP_MOTORS_MOT_1, 22.5, AP_MOTORS_MATRIX_YAW_FACTOR_CW,1),

defines a CW motor being driven by output pin 1 that is 22.5 degrees right of forward, and is to be spun first during test.

See Excel Worksheet Motor Definition Calculations for Custom Copters, the Custom Octa X sheet, if you want to convert copter motor x/y coordinates to angles from forward.

Page 7: 1 Create a Personal Workspace - api.ning.comapi.ning.com/.../CustomArduinoCodeWikiDraft.docx · Web viewFor the best read of the file, within Word Pad you might also want to do File»Page

o The term ‘frame’ is used here to capture the locations [TBD is spin direction still an option?) of the motors, not the shape that the motor boom or platform makes. For example, a quad could use two diagonal motor booms looking like an X or use two parallel motor booms connected by a center platform to look like a H. Both, however, if the motors form a regular polygon (angles between all motors are the same and distances to the center of gravity are the same) would be called a standard quad X. If the motor locations were irregular for any reason, the copter would be called a quad V for variant, or a hexa V, or an octa V. V is for variant, not the shape of the physical frame.

o For any variant from a regular polygon motor layout, the firmware uses the ADD_MOTOR_RAW subroutine to set the roll, pitch, and yaw factors using the following format:

add_motor_raw(O, the roll factor, the pitch factor, C, T); add_motor_raw(AP_MOTORS_MOT_1, 1.0, 0.45, -0.6, 1), defines a motor being driven by output

pin 1 using a roll factor of 1, a pitch factor of 0.45, a yaw factor of -0.6 (CW), and to be spun first during test.

See Excel Worksheet Motor Definition Calculations for Custom Copters the Custom Octa X or Custom Octa sheet, to convert x/y coordinates to the yaw and pitch factors [TBD for all frame types if this is the correct direction arducopter wants to take].

Page 8: 1 Create a Personal Workspace - api.ning.comapi.ning.com/.../CustomArduinoCodeWikiDraft.docx · Web viewFor the best read of the file, within Word Pad you might also want to do File»Page

Change the motor definitions in the file. There are 8 lines of code in each section, corresponding to each of the 8 motors of an Octa configuration. [TBD since these lines of code would be different with the new direction]o Change the original lines to comments by adding // in from of each line of original code. It’s

smart to keep the original lines of code around in case you need to reference or revert back to it. If not using the Excel worksheet to create the new lines of code (i.e., you are making the changes manually), first copy the lines before adding the double hashes. For example your code might look like the following with a custom Octa +

o Next copy and paste in the code generated in the Excel worksheet (see explanation in Excel). The code might look like the following for an Octa V.

// hard coded config for supported frames if( _frame_orientation == AP_MOTORS_PLUS_FRAME ) { // plus frame set-up add_motor(AP_MOTORS_MOT_1, 0, AP_MOTORS_MATRIX_YAW_FACTOR_CW, 1); add_motor(AP_MOTORS_MOT_2, 180, AP_MOTORS_MATRIX_YAW_FACTOR_CW, 5); add_motor(AP_MOTORS_MOT_3, 45, AP_MOTORS_MATRIX_YAW_FACTOR_CCW, 2); add_motor(AP_MOTORS_MOT_4, 135, AP_MOTORS_MATRIX_YAW_FACTOR_CCW, 4); add_motor(AP_MOTORS_MOT_5, -45, AP_MOTORS_MATRIX_YAW_FACTOR_CCW, 8); add_motor(AP_MOTORS_MOT_6, -135, AP_MOTORS_MATRIX_YAW_FACTOR_CCW, 6); add_motor(AP_MOTORS_MOT_7, -90, AP_MOTORS_MATRIX_YAW_FACTOR_CW, 7); add_motor(AP_MOTORS_MOT_8, 90, AP_MOTORS_MATRIX_YAW_FACTOR_CW, 3);

}else if( _frame_orientation == AP_MOTORS_V_FRAME ) { // V frame set-up ****original settings**** // add_motor_raw(AP_MOTORS_MOT_1, 1.0, 0.34, AP_MOTORS_MATRIX_YAW_FACTOR_CW, 7); // add_motor_raw(AP_MOTORS_MOT_2, -1.0, -0.32, AP_MOTORS_MATRIX_YAW_FACTOR_CW, 3); // add_motor_raw(AP_MOTORS_MOT_3, 1.0, -0.32, AP_MOTORS_MATRIX_YAW_FACTOR_CCW, 6); // add_motor_raw(AP_MOTORS_MOT_4, -0.5, -1.0, AP_MOTORS_MATRIX_YAW_FACTOR_CCW, 4); // add_motor_raw(AP_MOTORS_MOT_5, 1.0, 1.0, AP_MOTORS_MATRIX_YAW_FACTOR_CCW, 8); // add_motor_raw(AP_MOTORS_MOT_6, -1.0, 0.34, AP_MOTORS_MATRIX_YAW_FACTOR_CCW, 2); // add_motor_raw(AP_MOTORS_MOT_7, -1.0, 1.0, AP_MOTORS_MATRIX_YAW_FACTOR_CW, 1); // add_motor_raw(AP_MOTORS_MOT_8, 0.5, -1.0, AP_MOTORS_MATRIX_YAW_FACTOR_CW, 5);

// X2 frame set-up *****Frantz V 9/19/2013*****add_motor_raw(AP_MOTORS_MOT_5, 1.000, 1.000, -1.000, 1);add_motor_raw(AP_MOTORS_MOT_7, -1.000, 1.000, 1.000, 2);add_motor_raw(AP_MOTORS_MOT_1, 0.546, 0.504, 1.000, 3);add_motor_raw(AP_MOTORS_MOT_6, -0.546, 0.504, -1.000, 4);add_motor_raw(AP_MOTORS_MOT_3, 0.379,-0.504, -1.000, 5);add_motor_raw(AP_MOTORS_MOT_2, -0.379,-0.504, 1.000, 6);add_motor_raw(AP_MOTORS_MOT_8, 0.834,-1.000, 1.000, 7);add_motor_raw(AP_MOTORS_MOT_4, -0.834,-1.000, -1.000, 8);

}else { …

o Save the file. Select yes to Text Only Format if it asks.

Page 9: 1 Create a Personal Workspace - api.ning.comapi.ning.com/.../CustomArduinoCodeWikiDraft.docx · Web viewFor the best read of the file, within Word Pad you might also want to do File»Page

Define the number of motors on the ship. In this example, we set it to an Octao Edit APM_Config.h in the ArduCopter-[ver] directory. Right–click on the file, select “Open with”

and choose WordPad.o Find the comment line that says //#define FRAME_CONFIG …o Delete the // and change the define to the followingo #define FRAME_CONFIG OCTA_FRAME

Summary of the code modification process. As can be seen in the code, there are default parameters given for the most common variants of a quad, hexa, and octa. If the ship does not deviate from those defaults, then there is no reason to custom program these values. Simply go to MP, select quad, hexa, or octa, then set the frame type to V for variant and that’s it. But if the ship deviates significantly from those defaults then programming may be needed. o The ArduCopter code is complex, but well organized.o To learn more about the code, its basic architecture is describe in [TBD?].o Do not assume that a change won’t impact something else somewhere else.o Multiple files might be involved in a small change.o Multiple lines of code in different areas might be involved in a small change o When in doubt, ask the forum. One forum is the Learning to Program the Ardupilot Mega at

http://diydrones.com/group/learning-to-program-the-ardupilot-mega

Page 10: 1 Create a Personal Workspace - api.ning.comapi.ning.com/.../CustomArduinoCodeWikiDraft.docx · Web viewFor the best read of the file, within Word Pad you might also want to do File»Page

4 Download the Firmware Compiler

Go to the ardupilot mega site. https://code.google.com/p/ardupilot-mega/downloads/detail?name=ArduPilot-Arduino-1.0.3-windows.zip#makechanges (not the Arduino site as it does not have the special modification to talk to the APM 2.x board).

Click on the ArduPilot-Arduino-1.0.3-windows.zip to download. Wait until the download ends. Click on the download to unzip.

o Use Windows Explorer to move or copy the ArduPilot_Arduino_1.0.3_windows directory to C:\Program Files (x86). In Windows 8, if you click on the downloaded file, you will see at the top of the Windows Explorer screen, ‘Compressed Folder Tools’. Just under that click on Extract»Extract All»Browse to C:Program Files (x86), and then, OK»Extract, which also completes the copy.

Create a shortcut for Arduino. o Find arduino.exe in Program Files (x86)

ArduPilot_Arduino_1.0.3_windows directory.o Right click and Send to Desktop (create shortcut).o In your desktop you can then right-click the shortcut to create another shortcut to pin it to the

Start Menu.

Page 11: 1 Create a Personal Workspace - api.ning.comapi.ning.com/.../CustomArduinoCodeWikiDraft.docx · Web viewFor the best read of the file, within Word Pad you might also want to do File»Page

5 Configure the Compiler to Your Workspace

Launch Arduino (in the Start Menu or Desktop) Set the board type

o Click on ArduPiloto Select the board type (e.g., ArduPilot Mega 2.x)

Set the default directory for the code. o Click File – Preferenceso Browse to change the location of your codeo In this example, My DocumentsCopter

ArduCopter Codeardupilot-ArduCopter-3.0.o Uncheck Check for updates on startupo Uncheck Update sketch files to new ext…

Set the Serial Port to the port used by Mission Planner by clicking Tools – Serial Port

File-Quit Arduino for the setting to take effect. o

Page 12: 1 Create a Personal Workspace - api.ning.comapi.ning.com/.../CustomArduinoCodeWikiDraft.docx · Web viewFor the best read of the file, within Word Pad you might also want to do File»Page

6 Verify the Custom Firmware Code

Launch Arduino (the setup changes made prior will not take effect) Load your code: File -> Sketchbook -> ArduCopter A pop-up screen will appear showing the code in various tabs. On the far right is a down arrow that

lists all the tabs. Go to the second tab, APM_Config.h, and you should see the modification that you made to the #define FRAME_CONFIG OCTA_FRAME

In the upper left of the screen, you will see something like . Click the to verify the code. It will then compile the code. The compiler will say ‘Compiling Sketch’ and then ‘Done Compiling’ The compiler shouldn’t give any error messages. If language errors are found, the compiler will

point them out. Fix any errors if it does. The compiler does not fix errors in logic.

7 Compile and Upload the Custom Firmware

Make sure that your copter is plugged into your computer using the USB port and that Mission Planner isn’t using the port (isn’t connected).

Now click to compile and upload. It will say ‘Compiling sketch’, then ‘Uploading’, then ‘Done Uploading’.

Page 13: 1 Create a Personal Workspace - api.ning.comapi.ning.com/.../CustomArduinoCodeWikiDraft.docx · Web viewFor the best read of the file, within Word Pad you might also want to do File»Page

8 Validate the Custom Firmware

Sometimes it is necessary to validate that the changes made were in fact made. For example, in the case of the motor modifications, the pilot might want to make certain that the new definitions are in fact being used by the code. This can be done by special programming to visually or audibly alert the pilot that the changes are gold.

TBD Maybe changing the motor test order or some other change that is visible. It is now ready to fly. Enjoy.

9 Maintain the Custom Firmware

It is not necessary to stay current with every release of code from the github library. If you are happy with your copter, how it flies, and what it can do, then there is no reason to upgrade and recompile your code. This is true for your code as it is with staying current with every new release of your computer operating system or Word upgrade. If it ain’t broke, why fix it.

But, as the source code from the Github library is updated with new features or fixes that you want, it may become necessary to update the code in your workspace without having to completely start from scratch. The following describes one best practice on how to stay current.

TBD … maybe something like the following is one approach Copy (don’t move) the two files you changed to the directory above where the code is for safe

keeping. For example, ardupilot_ArduCopter_3.0 might be a subdirectory to ArduCopter Code. So copy APM_Config.h and AP_MotorsOcta.cpp to the ArduCopter Code directory.

When a new release occurs that you wish to use, upload it to the directory ArduCopter Code (maybe the new release will be in a directory ardupilot_ArduCopter_4.0).

Then copy APM_Config.h and AP_MotorsOcta.cpp to the new code to their respective directories. If applicable, set Arduino to go to the new directory and file-quit to make the change stick. Compile and upload using Arduino. Test the basic mode functions of the copter (stabilize, loiter and acro if used) before running

complex or difficult missions to ensure copter behavior hasn’t changed.