00001 // Ardrone.h 00002 // 00003 // Remote Control module for AR.Drone 00004 /// 00005 /// \mainpage Remote Control module for AR.Drone 00006 /// 00007 /// This is the Ardrone library. 00008 /// It provides a class for easy interfacing to Parrot AR.Drone quad-copter http://www.parrot.com via WiFi. 00009 /// 00010 /// The version of the package that this documentation refers to can be downloaded 00011 /// from http://www.open.com.au/mikem/arduino/Ardrone/Ardrone-1.2.zip 00012 /// You can find the latest version at http://www.open.com.au/mikem/arduino/RF22 00013 /// 00014 /// \par Prerequisites 00015 /// 00016 /// - WiShield or Yellowjacket (http://asynclabs.com) WiFi interface hardware 00017 /// - WiShield library 00018 /// 00019 /// You MUST alter the WiShield library header files to enable the UDP app support in Wishield that Ardrone needs. 00020 /// See below. 00021 /// 00022 /// You MUST pre-configure the AR.Drone to accept WiShield or Yellowjacket connections. 00023 /// See below. 00024 /// 00025 /// \par WiShield Library Configuration 00026 /// Requires the Asynclabs WiShield library. See http://asynclabs.com/wiki/index.php?title=WiShield_library 00027 /// Install the WiShield library in the libraries directory of your arduino IDE installation, 00028 /// then follow the configuration steps below: 00029 /// 00030 /// Support of RSSI (receiver signal strength indicator) requires mods to WiShield library g2100.c as per 00031 /// http://asynclabs.com/forums/viewtopic.php?f=10&t=385&start=0. You dont have to add this but its a 00032 /// good feature. 00033 /// 00034 /// Correct operation of the WiShield requires you to set the jumper on the WiShield to INT0 or DIG8 to select 00035 /// the arduino pin to use for WiShield interrupts, and also to make sure it agrees with the settings of 00036 /// USE_DIG0_INTR or USE_DIG8_INTR in spi.h in the WiShield library (which defaults to 00037 /// using Arduino digital pin 2, and which means setting the WiShield jumper to INT0 setting). Yes, the naming 00038 /// conventions are inconsistent :-(. In summary: 00039 /// \code 00040 /// WiShield jumper spi.h Arduino 00041 /// INT0 USE_DIG0_INTR Digital pin 2 00042 /// D8 USE_DIG8_INTR Digital pin 8 00043 /// \endcode 00044 /// 00045 /// For YellowJacket (which has no jumper), leave it as USE_DIG0_INTR. 00046 /// 00047 /// In order for WiShield library to support UDP (as needed by this module), 00048 /// you MUST set UIP_CONF_UDP to 1 in uip-conf.h. This is an unfortunate but necessary requirement, 00049 /// otherwise UDP support will not be compiled into the WiShield library. 00050 /// Further, you must edit apps-conf.h and make sure the only APP_* defined is APP_UDPAPP. 00051 /// Failure to do this will cause compile errors. A modified version of the WiShield library already 00052 /// edited for use with Ardrone and Arduino 1.0 is available at 00053 /// http://www.open.com.au/mikem/arduino/WiShield-v1.3.0-0-mikem-RCKit.zip 00054 /// 00055 /// WiShield will work with Arduino Mega, but with difficulty. The problem is that with the Mega, the SPI 00056 /// pins that are required for interface with WiShield come out on different pins to the smaller form 00057 /// factor arduinos like Diecimila and Duemilanove. So, to make the Mega work with the WiShield, you 00058 /// have to reroute the SPI pin to different Arduino pins, as per 00059 /// http://asynclabs.com/forums/viewtopic.php?f=13&t=19&hilit=mega&start=10 00060 /// 00061 /// \par AR.Drone pre-configuration 00062 /// 00063 /// As delivered, the AR.Drone does not support the 1Mbit/sec data rate which is the only data rate WiShield supports. 00064 /// Without this Ardrone module will associate correctly with the AR.Drone. Experienced Linux users can follow these steps. 00065 /// If you are inexperienced unsure of some steps, more detail is at: 00066 /// http://www.rcgroups.com/forums/showthread.php?t=1335257&pp=50#post16498030 00067 /// Caution: if you do not follow these steps precisely, you may make your AR.Drone uncontactable by WiFi. 00068 /// 00069 /// - Establish an ad-hoc WiFi connection from your computer to your drone 00070 /// - Telnet to the drone at 192.168.1.1. Should get a BusyBox prompt 00071 /// - Edit Wifi initialisation script, with vi /bin/wifi_setup.sh 00072 /// - Alter the line which reads: 00073 /// \code 00074 /// wmiconfig -i ath0 --setfixrates 3 8 11 00075 /// \endcode 00076 /// to read 00077 /// \code 00078 /// wmiconfig -i ath0 --setfixrates 1 3 8 11 00079 /// \endcode 00080 /// - Stop editing and save the file with: 00081 /// \code 00082 /// :wq 00083 /// \endcode 00084 /// Save the changes to flash with 00085 /// \code 00086 /// sync 00087 /// \endcode 00088 /// and wait a minute or so 00089 /// - Make sure the script is still working with: 00090 /// \code 00091 /// # /bin/wifi_setup.sh 00092 /// bmiloader: ath0: Operation not permitted 00093 /// bmiloader: ath0: Operation not permitted 00094 /// bmiloader: ath0: Operation not permitted 00095 /// bmiloader: ath0: Operation not permitted 00096 /// sh: 0x0: unknown operand 00097 /// ...... 00098 /// \endcode 00099 /// - Unplug the drone battery and restart it. 00100 /// 00101 /// \par Example programs 00102 /// 00103 /// Example Arduino programs are included to show the main modes of use. 00104 /// 00105 /// The following example programs are provided: 00106 /// - ardrone_test: Simple demonstration that shows how to create and initialise an Ardrone instance 00107 /// - usbjoystick_test: Shows how to use both Ardrone and USBJoystick libraries to control an AR.Drone 00108 /// using a USB Joystick or game pad. Requires USB Host Shield hardware, USB_Host_Shield library USB Joystick, 00109 /// along with the USBJoystick library from http://www.open.com.au/mikem/arduino/USBJoystick 00110 /// 00111 /// \par Installation 00112 /// 00113 /// Install in the usual way: unzip the distribution zip file to the libraries 00114 /// sub-folder of your sketchbook. 00115 /// 00116 /// \author Mike McCauley (mikem@open.com.au) 00117 /// 00118 /// This software is Copyright (C) 2011 Mike McCauley. Use is subject to license 00119 /// conditions. The main licensing options available are GPL V2 or Commercial: 00120 /// 00121 /// \par Open Source Licensing GPL V2 00122 /// This is the appropriate option if you want to share the source code of your 00123 /// application with everyone you distribute it to, and you also want to give them 00124 /// the right to share who uses it. If you wish to use this software under Open 00125 /// Source Licensing, you must contribute all your source code to the open source 00126 /// community in accordance with the GPL Version 2 when your application is 00127 /// distributed. See http://www.gnu.org/copyleft/gpl.html 00128 /// 00129 /// \par Commercial Licensing 00130 /// This is the appropriate option if you are creating proprietary applications 00131 /// and you are not prepared to distribute and share the source code of your 00132 /// application. Contact info@open.com.au for details. 00133 /// 00134 /// \par Revision History 00135 /// - Version 1.0: Initial release 00136 /// - Version 1.1: Fixed compile error in ardrone_test example. 00137 /// - Version 1.2: Compiles on Arduino 1.0. Requires latest version of 00138 /// http://www.open.com.au/mikem/arduino/WiShield-v1.3.0-0-mikem-RCKit.zip 00139 /// which now compiles on Arduino 1.0 00140 00141 00142 // Copyright (C) 2010 Mike McCauley 00143 // $Id: Ardrone.h,v 1.1 2011/03/16 23:46:12 mikem Exp mikem $ 00144 00145 #ifndef Ardrone_h 00146 #define Ardrone_h 00147 00148 #include <WiShield.h> 00149 #include <inttypes.h> 00150 00151 ///////////////////////////////////////////////////////////////////// 00152 /// \class Ardrone Ardrone.h <Ardrone.h> 00153 /// \brief Remote Control module for AR.Drone 00154 /// 00155 /// This class provides a simple interface to the AR.Drone over a WiFi connection. 00156 /// 00157 /// \par Overview 00158 /// 00159 /// This module presents a simple interface through wchich you can control and fly a AR.Drone. 00160 /// It requires a WiFi interface hardware and the WiShield library. 00161 /// It initialises the WiFi library, hardware and drone, then sends a stream of flying commands 00162 /// to the drone's AT UDP port. Member functions allow you to control the pitch, roll, yaw and altitude of the 00163 /// drone, and to make it land and take off, based on some input device (or perhaps a canned sequence of commands). 00164 /// 00165 /// \par Initialisation 00166 /// 00167 /// This module intialises the drone in the following way: 00168 /// - initialises the WiShield WiFi hardware to connect to the ad-hoc network whose name is given by ssid 00169 /// - Makes a TCP connection to ARDRONE_CONFIGDATA_PORT. This forces ARP to be done, and 00170 /// waits for the drone to be booted and available. The following AT cpommands are then sent to the 00171 /// ARDRONE_AT_PORT UDP port on the drone. 00172 /// - Sets the control:outdoor, control:control_yaw, control:control_vz_max, control:euler_angle_max, 00173 /// control:altitude_max configuration parameters. 00174 /// - sets control_level to 1 00175 /// - Sets a FTRIM command which indicates the drone is level 00176 /// - flashes the LEDs on teh drone. 00177 /// 00178 /// After initialisation, the update() function sends PCMD, REF and COMWDG commands every 00179 /// ARDRONE_AT_CMD_INTERVAL milliseconds. 00180 /// 00181 class Ardrone 00182 { 00183 #define ARDRONE_NAVDATA_PORT 5554 00184 #define ARDRONE_VIDEO_PORT 5555 00185 #define ARDRONE_AT_PORT 5556 00186 #define ARDRONE_CONFIGDATA_PORT 5559 00187 00188 #define ARDRONE_STATE_CONNECTING 0 00189 #define ARDRONE_STATE_INITIALISING 1 00190 #define ARDRONE_STATE_INITIALISED 2 00191 00192 // Flags for AtPCmd 00193 #define ARDRONE_PCMD_FLAG_PROGRESSIVE 0x1 00194 #define ARDRONE_PCMD_FLAG_COMBINED_YAW 0x2 00195 00196 // Flags for AtRefCmd 00197 #define ARDRONE_REF_FLAG_EMERGENCY 0x100 00198 #define ARDRONE_REF_FLAG_START 0x200 00199 #define ARDRONE_REF_FLAG_BASIC 0x11540000 00200 00201 // Milliseconds between AT commands: 00202 #define ARDRONE_AT_CMD_INTERVAL 30 00203 00204 // Max length of an accumulated AT command 00205 // Caution there is no protection against buffer overruns 00206 #define ARDRONE_MAX_AT_COMMAND_LENGTH 300 00207 00208 public: 00209 00210 /// \brief Defines types of LED animation for use with addAtLedAnimCmd() 00211 /// 00212 /// Each animation produces a different type of flashing pattern 00213 typedef enum { 00214 ARDRONE_LED_ANIMATION_BLINK_GREEN_RED = 0, 00215 ARDRONE_LED_ANIMATION_BLINK_GREEN, 00216 ARDRONE_LED_ANIMATION_BLINK_RED, 00217 ARDRONE_LED_ANIMATION_BLINK_ORANGE, 00218 ARDRONE_LED_ANIMATION_SNAKE_GREEN_RED, 00219 ARDRONE_LED_ANIMATION_FIRE, 00220 ARDRONE_LED_ANIMATION_STANDARD, 00221 ARDRONE_LED_ANIMATION_RED, 00222 ARDRONE_LED_ANIMATION_GREEN, 00223 ARDRONE_LED_ANIMATION_RED_SNAKE, 00224 ARDRONE_LED_ANIMATION_BLANK, 00225 ARDRONE_LED_ANIMATION_RIGHT_MISSILE, 00226 ARDRONE_LED_ANIMATION_LEFT_MISSILE, 00227 ARDRONE_LED_ANIMATION_DOUBLE_MISSILE, 00228 ARDRONE_LED_ANIMATION_FRONT_LEFT_GREEN_OTHERS_RED, 00229 ARDRONE_LED_ANIMATION_FRONT_RIGHT_GREEN_OTHERS_RED, 00230 ARDRONE_LED_ANIMATION_REAR_RIGHT_GREEN_OTHERS_RED, 00231 ARDRONE_LED_ANIMATION_REAR_LEFT_GREEN_OTHERS_RED, 00232 ARDRONE_LED_ANIMATION_LEFT_GREEN_RIGHT_RED, 00233 ARDRONE_LED_ANIMATION_LEFT_RED_RIGHT_GREEN, 00234 ARDRONE_LED_ANIMATION_BLINK_STANDARD, 00235 } LEDAnimation; 00236 00237 /// \brief Defines types of animation for use with addAtAnimCmd() 00238 /// 00239 /// Each animation produces a different type of preprogrammed pattern of movement, superposed 00240 /// on the flying commands 00241 typedef enum { 00242 ARDRONE_ANIMATION_PHI_M30_DEG = 0, 00243 ARDRONE_ANIMATION_PHI_30_DEG, 00244 ARDRONE_ANIMATION_THETA_M30_DEG, 00245 ARDRONE_ANIMATION_THETA_30_DEG, 00246 ARDRONE_ANIMATION_THETA_20DEG_YAW_200DEG, 00247 ARDRONE_ANIMATION_THETA_20DEG_YAW_M200DEG, 00248 ARDRONE_ANIMATION_TURNAROUND, 00249 ARDRONE_ANIMATION_TURNAROUND_GODOWN, 00250 ARDRONE_ANIMATION_YAW_SHAKE, 00251 ARDRONE_ANIMATION_YAW_DANCE, 00252 ARDRONE_ANIMATION_PHI_DANCE, 00253 ARDRONE_ANIMATION_THETA_DANCE, 00254 ARDRONE_ANIMATION_VZ_DANCE, 00255 ARDRONE_ANIMATION_WAVE, 00256 ARDRONE_ANIMATION_PHI_THETA_MIXED, 00257 ARDRONE_ANIMATION_DOUBLE_PHI_THETA_MIXED, 00258 } Animation; 00259 00260 /// Constructor. 00261 /// After contruction and initialisation, call the init() and run() functions. 00262 /// You must also define the SSID of the AR.Drone's ad-hoc wireless network, like this: 00263 /// \code 00264 /// Ardrone ardrone; 00265 /// const prog_char ssid[] PROGMEM = "ardrone_165416"; 00266 /// \endcode 00267 /// where ardrone_165416 is replaced with the actual network name for your particular AR.Drone. 00268 Ardrone(); 00269 00270 /// Initialises the wireless WiFi receiver 00271 /// Call once at startup time after addresses, flight parameters etc have been configured. 00272 void init(); 00273 00274 /// Call this to process pending Wireless events. Call this as often as possible in your 00275 /// main loop. Runs the wireless driver stack, which calls periodicTask(), among other things 00276 void run(); 00277 00278 /// Sets the intialisation value for control:control_yaw 00279 /// which limits the maximum rate of change of yaw 00280 /// Defaults to 1.75 radians/sec 00281 /// \param[in] control_yaw maximum rate of change of yaw, radians/second 00282 void setControlYaw(float control_yaw); 00283 00284 /// Sets the intialisation value for control:control_vz_max 00285 /// which limits the maximum rate of change of altitude 00286 /// Defaults to 700.0 mm/sec 00287 /// \param[in] control_vz_max maximum rate of change of altitude, mm/second 00288 void setControlVZMax(float control_vz_max); 00289 00290 /// Sets the intialisation value for control:euler_angle_max 00291 /// which limits the maximum roll and pitch tilt 00292 /// Defaults to 0.1 radians 00293 /// \param[in] euler_angle_max maximum tilt for roll and pitch in radians 00294 void setEulerAngleMax(float euler_angle_max); 00295 00296 /// Sets the intialisation value for control:altitude_max 00297 /// which limits the maximum height 00298 /// Defaults to 3000.0 mm 00299 /// \param[in] altitude_max maximum altitude in mm 00300 void setAlitudeMax(float altitude_max); 00301 00302 /// Sets the intialisation value for control:outdoor 00303 /// which specifies whether the default drone limits for indoor or outdoor flying should be used 00304 /// Defaults to false. 00305 /// \param[in] outdoor true if flying outdoors 00306 void setOutdoor(float outdoor); 00307 00308 /// Sets the flying parameter 00309 /// Causes the drone to take off or land. Defaults at initialisation to false. 00310 /// \param[in] flying If true, drone will take off to 1m hover. If false, drone will land. 00311 void setFlying(boolean flying); 00312 00313 /// Returns the most recently set value of the flying parameter. 00314 /// \return the current value of the flying parameter 00315 boolean flying(); 00316 00317 /// Sets the roll parameter. Range from -1.0 (roll left to euler_angle_max radians) 00318 /// to +1.0 (roll right to euler_angle_max radians). 0.0 means level. Defaults at initialisation to 0.0. 00319 /// The new roll parameter will be sent during the next update() if the drone is flying. 00320 /// \param[in] roll The new roll value 00321 void setRoll(float roll); 00322 00323 /// Returns the most recently set value of the roll parameter. 00324 /// \return The current roll value; 00325 float roll(); 00326 00327 /// Sets the pitch parameter. Range from -1.0 (pitch forward to euler_angle_max radians) 00328 /// to +1.0 (pitch back to euler_angle_max radians). 0.0 means level. Defaults at initialisation to 0.0. 00329 /// The new pitch parameter will be sent during the next update() if the drone is flying. 00330 /// \param[in] pitch The new pitch value 00331 void setPitch(float pitch); 00332 00333 /// Returns the most recently set value of the pitch parameter. 00334 /// \return The current pitch value; 00335 float pitch(); 00336 00337 /// Sets the gaz (rate of change of altitude). Range from -1.0 (descend at control_vz_max mm/sec) 00338 /// to +1.0 (ascend at control_vz_max mm/sec). 0.0 means level. Defaults at initialisation to 0.0. 00339 /// The new gaz parameter will be sent during the next update() if the drone is flying. 00340 /// \param[in] gaz The new gaz value 00341 void setGaz(float gaz); 00342 00343 /// Returns the most recently set value of the gaz parameter. 00344 /// \return The current gaz value; 00345 float gaz(); 00346 00347 /// Sets the yaw (rate of change of yaw). Range from -1.0 (rotate left at control_yaw radians/sec) 00348 /// to +1.0 (rotate right at control_yaw radians/sec). 0.0 means no rotation. Defaults at initialisation to 0.0. 00349 /// The new yaw parameter will be sent during the next update() if the drone is flying. 00350 /// \param[in] yaw The new yaw value 00351 void setYaw(float yaw); 00352 00353 /// Returns the most recently set value of the yaw parameter. 00354 /// \return The current yaw value; 00355 float yaw(); 00356 00357 /// For internal use only. 00358 /// Indicates a successful connection to the drone has been made, and initialisation can commence 00359 void connected(); 00360 00361 /// For internal use only. 00362 /// Runs various periodic tasks for the drone 00363 void periodicTask(); 00364 00365 /// Adds a drone PCMD comamnd to the command buffer, which will be sent during the next update(); 00366 /// \param[in] flags Bitmask of ARDRONE_PCMD_FLAG_* flags 00367 /// \param[in] roll The new roll command value. 00368 /// \param[in] pitch The new pitch command value. 00369 /// \param[in] gaz The new gaz command value. 00370 /// \param[in] yaw The new yaw command value. 00371 void addAtPCmd(unsigned int flags, float roll, float pitch, float gaz, float yaw); 00372 00373 /// Adds a drone CONFIG comamnd to the command buffer, which will be sent during the next update(); 00374 /// \param[in] name String name of the config parameter to change 00375 /// \param[in] value String value to change it to 00376 void addAtConfigCmd(const char* name, const char* value); 00377 00378 /// Adds a drone LED comamnd to the command buffer, which will be sent during the next update(); 00379 /// \param[in] animation One of the LEDAnimation values, which specifies the type of flashing pattern to use 00380 /// \param[in] frequency Flashing frequency in Hz. 00381 /// \param[in] duration Period of time to run the animation for in seconds 00382 void addAtLedCmd(Ardrone::LEDAnimation animation = ARDRONE_LED_ANIMATION_BLINK_GREEN_RED, float frequency = 5.0, uint16_t duration = 5); 00383 00384 /// Adds a drone ANIM comamnd to the command buffer, which will be sent during the next update(); 00385 /// \param[in] animation One of the Animation values, which specifies the type of flying animation pattern to use 00386 /// \param[in] duration Period of time to run the animation for in seconds 00387 void addAtAnimCmd(Ardrone::Animation animation = ARDRONE_ANIMATION_WAVE, uint16_t duration = 5); 00388 00389 /// Adds a drone FTRIM comamnd to the command buffer, which will be sent during the next update(); 00390 void addAtFtrimCmd(); 00391 00392 /// Adds a drone REF comamnd to the command buffer, which will be sent during the next update(); 00393 /// \param[in] flags Bitmask of ARDRONE_REF_FLAG_* 00394 void addAtRefCmd(uint32_t flags); 00395 00396 /// Adds a drone COMWDG comamnd to the command buffer, which will be sent during the next update(); 00397 void addAtComWdgCmd(); 00398 00399 /// Adds a drone PMODE comamnd to the command buffer, which will be sent during the next update(); 00400 /// \param[in] mode Not documented 00401 void addAtPmodeCmd(uint8_t mode); 00402 00403 /// Adds a drone MISC comamnd to the command buffer, which will be sent during the next update(); 00404 /// \param[in] a Not documented 00405 /// \param[in] b Not documented 00406 /// \param[in] c Not documented 00407 /// \param[in] d Not documented 00408 void addAtMiscCmd(uint16_t a, uint16_t b, uint16_t c, uint16_t d); 00409 00410 protected: 00411 00412 /// For internal use only. 00413 /// Called periodically during device initialisation. Sends a series of commands to initialise 00414 /// the drone. 00415 void device_init(); 00416 00417 /// For internal use only. 00418 /// Called periodically after device initialisation. Sends any commands accumulated by earlier calls to 00419 /// addAt*Cmd() functions. 00420 /// If the drone is flying sends a PCMD with the curent flying parameters 00421 /// Also sends a REF command with appropriate flags for flying or grounded 00422 /// Also sends a COMWDG command to refresh teh comms watchdog. 00423 void update(); 00424 00425 /// Sends a command to the drone AT port 00426 /// \param[in] msg The message to be sent 00427 /// \param[in] len The length of the message in bytes 00428 void sendAtCmd(uint8_t* msg, uint16_t len); 00429 00430 /// Sends a string to the drone AT port 00431 /// \param[in] s The ASCII string to send 00432 void sendAtCmd(char* s); 00433 00434 /// Sends the entire currently accumulated command buffer to the drone AT port 00435 void sendCurrentAtCmd(); 00436 00437 private: 00438 uint8_t _state; 00439 uint8_t _init_step; 00440 unsigned long _sequence; 00441 00442 // Initialisation values 00443 // These are used to set the CONFIG control: variables of the same name 00444 float _control_yaw; 00445 float _control_vz_max; 00446 float _euler_angle_max; 00447 float _altitude_max; 00448 boolean _outdoor; 00449 00450 // Flying command values 00451 boolean _flying; 00452 float _roll; 00453 float _pitch; 00454 float _gaz; 00455 float _yaw; 00456 00457 }; 00458 00459 #endif