Ardrone
Ardrone.h
1 // Ardrone.h
2 //
3 // Remote Control module for AR.Drone
4 ///
5 /// \mainpage Remote Control module for AR.Drone
6 ///
7 /// This is the Ardrone library.
8 /// It provides a class for easy interfacing to Parrot AR.Drone quad-copter http://www.parrot.com via WiFi.
9 ///
10 /// The version of the package that this documentation refers to can be downloaded
11 /// from http://www.airspayce.com/mikem/arduino/Ardrone/Ardrone-1.3.zip
12 /// You can find the latest version at http://www.airspayce.com/mikem/arduino/Ardrone
13 ///
14 /// \par Prerequisites
15 ///
16 /// - WiShield or Yellowjacket (http://asynclabs.com) WiFi interface hardware
17 /// - WiShield library
18 ///
19 /// You MUST alter the WiShield library header files to enable the UDP app support in Wishield that Ardrone needs.
20 /// See below.
21 ///
22 /// You MUST pre-configure the AR.Drone to accept WiShield or Yellowjacket connections.
23 /// See below.
24 ///
25 /// \par WiShield Library Configuration
26 /// Requires the Asynclabs WiShield library. See http://asynclabs.com/wiki/index.php?title=WiShield_library
27 /// Install the WiShield library in the libraries directory of your arduino IDE installation,
28 /// then follow the configuration steps below:
29 ///
30 /// Support of RSSI (receiver signal strength indicator) requires mods to WiShield library g2100.c as per
31 /// http://asynclabs.com/forums/viewtopic.php?f=10&t=385&start=0. You dont have to add this but its a
32 /// good feature.
33 ///
34 /// Correct operation of the WiShield requires you to set the jumper on the WiShield to INT0 or DIG8 to select
35 /// the arduino pin to use for WiShield interrupts, and also to make sure it agrees with the settings of
36 /// USE_DIG0_INTR or USE_DIG8_INTR in spi.h in the WiShield library (which defaults to
37 /// using Arduino digital pin 2, and which means setting the WiShield jumper to INT0 setting). Yes, the naming
38 /// conventions are inconsistent :-(. In summary:
39 /// \code
40 /// WiShield jumper spi.h Arduino
41 /// INT0 USE_DIG0_INTR Digital pin 2
42 /// D8 USE_DIG8_INTR Digital pin 8
43 /// \endcode
44 ///
45 /// For YellowJacket (which has no jumper), leave it as USE_DIG0_INTR.
46 ///
47 /// In order for WiShield library to support UDP (as needed by this module),
48 /// you MUST set UIP_CONF_UDP to 1 in uip-conf.h. This is an unfortunate but necessary requirement,
49 /// otherwise UDP support will not be compiled into the WiShield library.
50 /// Further, you must edit apps-conf.h and make sure the only APP_* defined is APP_UDPAPP.
51 /// Failure to do this will cause compile errors. A modified version of the WiShield library already
52 /// edited for use with Ardrone and Arduino 1.0 is available at
53 /// http://www.airspayce.com/mikem/arduino/WiShield-v1.3.0-0-mikem-RCKit.zip
54 ///
55 /// WiShield will work with Arduino Mega, but with difficulty. The problem is that with the Mega, the SPI
56 /// pins that are required for interface with WiShield come out on different pins to the smaller form
57 /// factor arduinos like Diecimila and Duemilanove. So, to make the Mega work with the WiShield, you
58 /// have to reroute the SPI pin to different Arduino pins, as per
59 /// http://asynclabs.com/forums/viewtopic.php?f=13&t=19&hilit=mega&start=10
60 ///
61 /// \par AR.Drone pre-configuration
62 ///
63 /// As delivered, the AR.Drone does not support the 1Mbit/sec data rate which is the only data rate WiShield supports.
64 /// Without this Ardrone module will associate correctly with the AR.Drone. Experienced Linux users can follow these steps.
65 /// If you are inexperienced unsure of some steps, more detail is at:
66 /// http://www.rcgroups.com/forums/showthread.php?t=1335257&pp=50#post16498030
67 /// Caution: if you do not follow these steps precisely, you may make your AR.Drone uncontactable by WiFi.
68 ///
69 /// - Establish an ad-hoc WiFi connection from your computer to your drone
70 /// - Telnet to the drone at 192.168.1.1. Should get a BusyBox prompt
71 /// - Edit Wifi initialisation script, with vi /bin/wifi_setup.sh
72 /// - Alter the line which reads:
73 /// \code
74 /// wmiconfig -i ath0 --setfixrates 3 8 11
75 /// \endcode
76 /// to read
77 /// \code
78 /// wmiconfig -i ath0 --setfixrates 1 3 8 11
79 /// \endcode
80 /// - Stop editing and save the file with:
81 /// \code
82 /// :wq
83 /// \endcode
84 /// Save the changes to flash with
85 /// \code
86 /// sync
87 /// \endcode
88 /// and wait a minute or so
89 /// - Make sure the script is still working with:
90 /// \code
91 /// # /bin/wifi_setup.sh
92 /// bmiloader: ath0: Operation not permitted
93 /// bmiloader: ath0: Operation not permitted
94 /// bmiloader: ath0: Operation not permitted
95 /// bmiloader: ath0: Operation not permitted
96 /// sh: 0x0: unknown operand
97 /// ......
98 /// \endcode
99 /// - Unplug the drone battery and restart it.
100 ///
101 /// \par Example programs
102 ///
103 /// Example Arduino programs are included to show the main modes of use.
104 ///
105 /// The following example programs are provided:
106 /// - ardrone_test: Simple demonstration that shows how to create and initialise an Ardrone instance
107 /// - usbjoystick_test: Shows how to use both Ardrone and USBJoystick libraries to control an AR.Drone
108 /// using a USB Joystick or game pad. Requires USB Host Shield hardware, USB_Host_Shield library USB Joystick,
109 /// along with the USBJoystick library from http://www.airspayce.com/mikem/arduino/USBJoystick
110 ///
111 /// \par Installation
112 ///
113 /// Install in the usual way: unzip the distribution zip file to the libraries
114 /// sub-folder of your sketchbook.
115 ///
116 /// \author Mike McCauley (mikem@airspayce.com)
117 ///
118 /// This software is Copyright (C) 2011 Mike McCauley. Use is subject to license
119 /// conditions. The main licensing options available are GPL V2 or Commercial:
120 ///
121 /// \par Open Source Licensing GPL V2
122 /// This is the appropriate option if you want to share the source code of your
123 /// application with everyone you distribute it to, and you also want to give them
124 /// the right to share who uses it. If you wish to use this software under Open
125 /// Source Licensing, you must contribute all your source code to the open source
126 /// community in accordance with the GPL Version 2 when your application is
127 /// distributed. See http://www.gnu.org/copyleft/gpl.html
128 ///
129 /// \par Commercial Licensing
130 /// This is the appropriate option if you are creating proprietary applications
131 /// and you are not prepared to distribute and share the source code of your
132 /// application. Contact info@airspayce.com for details.
133 ///
134 /// \par Revision History
135 /// - Version 1.0: Initial release
136 /// - Version 1.1: Fixed compile error in ardrone_test example.
137 /// - Version 1.2: Compiles on Arduino 1.0. Requires latest version of
138 /// http://www.airspayce.com/mikem/arduino/WiShield-v1.3.0-0-mikem-RCKit.zip
139 /// which now compiles on Arduino 1.0
140 /// - Version 1.3: Updated author and distribution location details to airspayce.com
141 ///
142 
143 
144 // Copyright (C) 2010 Mike McCauley
145 // $Id: Ardrone.h,v 1.1 2011/03/16 23:46:12 mikem Exp mikem $
146 
147 #ifndef Ardrone_h
148 #define Ardrone_h
149 
150 #include <WiShield.h>
151 #include <inttypes.h>
152 
153 /////////////////////////////////////////////////////////////////////
154 /// \class Ardrone Ardrone.h <Ardrone.h>
155 /// \brief Remote Control module for AR.Drone
156 ///
157 /// This class provides a simple interface to the AR.Drone over a WiFi connection.
158 ///
159 /// \par Overview
160 ///
161 /// This module presents a simple interface through wchich you can control and fly a AR.Drone.
162 /// It requires a WiFi interface hardware and the WiShield library.
163 /// It initialises the WiFi library, hardware and drone, then sends a stream of flying commands
164 /// to the drone's AT UDP port. Member functions allow you to control the pitch, roll, yaw and altitude of the
165 /// drone, and to make it land and take off, based on some input device (or perhaps a canned sequence of commands).
166 ///
167 /// \par Initialisation
168 ///
169 /// This module intialises the drone in the following way:
170 /// - initialises the WiShield WiFi hardware to connect to the ad-hoc network whose name is given by ssid
171 /// - Makes a TCP connection to ARDRONE_CONFIGDATA_PORT. This forces ARP to be done, and
172 /// waits for the drone to be booted and available. The following AT cpommands are then sent to the
173 /// ARDRONE_AT_PORT UDP port on the drone.
174 /// - Sets the control:outdoor, control:control_yaw, control:control_vz_max, control:euler_angle_max,
175 /// control:altitude_max configuration parameters.
176 /// - sets control_level to 1
177 /// - Sets a FTRIM command which indicates the drone is level
178 /// - flashes the LEDs on teh drone.
179 ///
180 /// After initialisation, the update() function sends PCMD, REF and COMWDG commands every
181 /// ARDRONE_AT_CMD_INTERVAL milliseconds.
182 ///
183 class Ardrone
184 {
185 #define ARDRONE_NAVDATA_PORT 5554
186 #define ARDRONE_VIDEO_PORT 5555
187 #define ARDRONE_AT_PORT 5556
188 #define ARDRONE_CONFIGDATA_PORT 5559
189 
190 #define ARDRONE_STATE_CONNECTING 0
191 #define ARDRONE_STATE_INITIALISING 1
192 #define ARDRONE_STATE_INITIALISED 2
193 
194 // Flags for AtPCmd
195 #define ARDRONE_PCMD_FLAG_PROGRESSIVE 0x1
196 #define ARDRONE_PCMD_FLAG_COMBINED_YAW 0x2
197 
198 // Flags for AtRefCmd
199 #define ARDRONE_REF_FLAG_EMERGENCY 0x100
200 #define ARDRONE_REF_FLAG_START 0x200
201 #define ARDRONE_REF_FLAG_BASIC 0x11540000
202 
203 // Milliseconds between AT commands:
204 #define ARDRONE_AT_CMD_INTERVAL 30
205 
206 // Max length of an accumulated AT command
207 // Caution there is no protection against buffer overruns
208 #define ARDRONE_MAX_AT_COMMAND_LENGTH 300
209 
210 public:
211 
212  /// \brief Defines types of LED animation for use with addAtLedAnimCmd()
213  ///
214  /// Each animation produces a different type of flashing pattern
215  typedef enum {
216  ARDRONE_LED_ANIMATION_BLINK_GREEN_RED = 0,
217  ARDRONE_LED_ANIMATION_BLINK_GREEN,
218  ARDRONE_LED_ANIMATION_BLINK_RED,
219  ARDRONE_LED_ANIMATION_BLINK_ORANGE,
220  ARDRONE_LED_ANIMATION_SNAKE_GREEN_RED,
221  ARDRONE_LED_ANIMATION_FIRE,
222  ARDRONE_LED_ANIMATION_STANDARD,
223  ARDRONE_LED_ANIMATION_RED,
224  ARDRONE_LED_ANIMATION_GREEN,
225  ARDRONE_LED_ANIMATION_RED_SNAKE,
226  ARDRONE_LED_ANIMATION_BLANK,
227  ARDRONE_LED_ANIMATION_RIGHT_MISSILE,
228  ARDRONE_LED_ANIMATION_LEFT_MISSILE,
229  ARDRONE_LED_ANIMATION_DOUBLE_MISSILE,
230  ARDRONE_LED_ANIMATION_FRONT_LEFT_GREEN_OTHERS_RED,
231  ARDRONE_LED_ANIMATION_FRONT_RIGHT_GREEN_OTHERS_RED,
232  ARDRONE_LED_ANIMATION_REAR_RIGHT_GREEN_OTHERS_RED,
233  ARDRONE_LED_ANIMATION_REAR_LEFT_GREEN_OTHERS_RED,
234  ARDRONE_LED_ANIMATION_LEFT_GREEN_RIGHT_RED,
235  ARDRONE_LED_ANIMATION_LEFT_RED_RIGHT_GREEN,
236  ARDRONE_LED_ANIMATION_BLINK_STANDARD,
237  } LEDAnimation;
238 
239  /// \brief Defines types of animation for use with addAtAnimCmd()
240  ///
241  /// Each animation produces a different type of preprogrammed pattern of movement, superposed
242  /// on the flying commands
243  typedef enum {
244  ARDRONE_ANIMATION_PHI_M30_DEG = 0,
245  ARDRONE_ANIMATION_PHI_30_DEG,
246  ARDRONE_ANIMATION_THETA_M30_DEG,
247  ARDRONE_ANIMATION_THETA_30_DEG,
248  ARDRONE_ANIMATION_THETA_20DEG_YAW_200DEG,
249  ARDRONE_ANIMATION_THETA_20DEG_YAW_M200DEG,
250  ARDRONE_ANIMATION_TURNAROUND,
251  ARDRONE_ANIMATION_TURNAROUND_GODOWN,
252  ARDRONE_ANIMATION_YAW_SHAKE,
253  ARDRONE_ANIMATION_YAW_DANCE,
254  ARDRONE_ANIMATION_PHI_DANCE,
255  ARDRONE_ANIMATION_THETA_DANCE,
256  ARDRONE_ANIMATION_VZ_DANCE,
257  ARDRONE_ANIMATION_WAVE,
258  ARDRONE_ANIMATION_PHI_THETA_MIXED,
259  ARDRONE_ANIMATION_DOUBLE_PHI_THETA_MIXED,
260  } Animation;
261 
262  /// Constructor.
263  /// After contruction and initialisation, call the init() and run() functions.
264  /// You must also define the SSID of the AR.Drone's ad-hoc wireless network, like this:
265  /// \code
266  /// Ardrone ardrone;
267  /// const prog_char ssid[] PROGMEM = "ardrone_165416";
268  /// \endcode
269  /// where ardrone_165416 is replaced with the actual network name for your particular AR.Drone.
270  Ardrone();
271 
272  /// Initialises the wireless WiFi receiver
273  /// Call once at startup time after addresses, flight parameters etc have been configured.
274  void init();
275 
276  /// Call this to process pending Wireless events. Call this as often as possible in your
277  /// main loop. Runs the wireless driver stack, which calls periodicTask(), among other things
278  void run();
279 
280  /// Sets the intialisation value for control:control_yaw
281  /// which limits the maximum rate of change of yaw
282  /// Defaults to 1.75 radians/sec
283  /// \param[in] control_yaw maximum rate of change of yaw, radians/second
284  void setControlYaw(float control_yaw);
285 
286  /// Sets the intialisation value for control:control_vz_max
287  /// which limits the maximum rate of change of altitude
288  /// Defaults to 700.0 mm/sec
289  /// \param[in] control_vz_max maximum rate of change of altitude, mm/second
290  void setControlVZMax(float control_vz_max);
291 
292  /// Sets the intialisation value for control:euler_angle_max
293  /// which limits the maximum roll and pitch tilt
294  /// Defaults to 0.1 radians
295  /// \param[in] euler_angle_max maximum tilt for roll and pitch in radians
296  void setEulerAngleMax(float euler_angle_max);
297 
298  /// Sets the intialisation value for control:altitude_max
299  /// which limits the maximum height
300  /// Defaults to 3000.0 mm
301  /// \param[in] altitude_max maximum altitude in mm
302  void setAlitudeMax(float altitude_max);
303 
304  /// Sets the intialisation value for control:outdoor
305  /// which specifies whether the default drone limits for indoor or outdoor flying should be used
306  /// Defaults to false.
307  /// \param[in] outdoor true if flying outdoors
308  void setOutdoor(float outdoor);
309 
310  /// Sets the flying parameter
311  /// Causes the drone to take off or land. Defaults at initialisation to false.
312  /// \param[in] flying If true, drone will take off to 1m hover. If false, drone will land.
313  void setFlying(boolean flying);
314 
315  /// Returns the most recently set value of the flying parameter.
316  /// \return the current value of the flying parameter
317  boolean flying();
318 
319  /// Sets the roll parameter. Range from -1.0 (roll left to euler_angle_max radians)
320  /// to +1.0 (roll right to euler_angle_max radians). 0.0 means level. Defaults at initialisation to 0.0.
321  /// The new roll parameter will be sent during the next update() if the drone is flying.
322  /// \param[in] roll The new roll value
323  void setRoll(float roll);
324 
325  /// Returns the most recently set value of the roll parameter.
326  /// \return The current roll value;
327  float roll();
328 
329  /// Sets the pitch parameter. Range from -1.0 (pitch forward to euler_angle_max radians)
330  /// to +1.0 (pitch back to euler_angle_max radians). 0.0 means level. Defaults at initialisation to 0.0.
331  /// The new pitch parameter will be sent during the next update() if the drone is flying.
332  /// \param[in] pitch The new pitch value
333  void setPitch(float pitch);
334 
335  /// Returns the most recently set value of the pitch parameter.
336  /// \return The current pitch value;
337  float pitch();
338 
339  /// Sets the gaz (rate of change of altitude). Range from -1.0 (descend at control_vz_max mm/sec)
340  /// to +1.0 (ascend at control_vz_max mm/sec). 0.0 means level. Defaults at initialisation to 0.0.
341  /// The new gaz parameter will be sent during the next update() if the drone is flying.
342  /// \param[in] gaz The new gaz value
343  void setGaz(float gaz);
344 
345  /// Returns the most recently set value of the gaz parameter.
346  /// \return The current gaz value;
347  float gaz();
348 
349  /// Sets the yaw (rate of change of yaw). Range from -1.0 (rotate left at control_yaw radians/sec)
350  /// to +1.0 (rotate right at control_yaw radians/sec). 0.0 means no rotation. Defaults at initialisation to 0.0.
351  /// The new yaw parameter will be sent during the next update() if the drone is flying.
352  /// \param[in] yaw The new yaw value
353  void setYaw(float yaw);
354 
355  /// Returns the most recently set value of the yaw parameter.
356  /// \return The current yaw value;
357  float yaw();
358 
359  /// For internal use only.
360  /// Indicates a successful connection to the drone has been made, and initialisation can commence
361  void connected();
362 
363  /// For internal use only.
364  /// Runs various periodic tasks for the drone
365  void periodicTask();
366 
367  /// Adds a drone PCMD comamnd to the command buffer, which will be sent during the next update();
368  /// \param[in] flags Bitmask of ARDRONE_PCMD_FLAG_* flags
369  /// \param[in] roll The new roll command value.
370  /// \param[in] pitch The new pitch command value.
371  /// \param[in] gaz The new gaz command value.
372  /// \param[in] yaw The new yaw command value.
373  void addAtPCmd(unsigned int flags, float roll, float pitch, float gaz, float yaw);
374 
375  /// Adds a drone CONFIG comamnd to the command buffer, which will be sent during the next update();
376  /// \param[in] name String name of the config parameter to change
377  /// \param[in] value String value to change it to
378  void addAtConfigCmd(const char* name, const char* value);
379 
380  /// Adds a drone LED comamnd to the command buffer, which will be sent during the next update();
381  /// \param[in] animation One of the LEDAnimation values, which specifies the type of flashing pattern to use
382  /// \param[in] frequency Flashing frequency in Hz.
383  /// \param[in] duration Period of time to run the animation for in seconds
384  void addAtLedCmd(Ardrone::LEDAnimation animation = ARDRONE_LED_ANIMATION_BLINK_GREEN_RED, float frequency = 5.0, uint16_t duration = 5);
385 
386  /// Adds a drone ANIM comamnd to the command buffer, which will be sent during the next update();
387  /// \param[in] animation One of the Animation values, which specifies the type of flying animation pattern to use
388  /// \param[in] duration Period of time to run the animation for in seconds
389  void addAtAnimCmd(Ardrone::Animation animation = ARDRONE_ANIMATION_WAVE, uint16_t duration = 5);
390 
391  /// Adds a drone FTRIM comamnd to the command buffer, which will be sent during the next update();
392  void addAtFtrimCmd();
393 
394  /// Adds a drone REF comamnd to the command buffer, which will be sent during the next update();
395  /// \param[in] flags Bitmask of ARDRONE_REF_FLAG_*
396  void addAtRefCmd(uint32_t flags);
397 
398  /// Adds a drone COMWDG comamnd to the command buffer, which will be sent during the next update();
399  void addAtComWdgCmd();
400 
401  /// Adds a drone PMODE comamnd to the command buffer, which will be sent during the next update();
402  /// \param[in] mode Not documented
403  void addAtPmodeCmd(uint8_t mode);
404 
405  /// Adds a drone MISC comamnd to the command buffer, which will be sent during the next update();
406  /// \param[in] a Not documented
407  /// \param[in] b Not documented
408  /// \param[in] c Not documented
409  /// \param[in] d Not documented
410  void addAtMiscCmd(uint16_t a, uint16_t b, uint16_t c, uint16_t d);
411 
412 protected:
413 
414  /// For internal use only.
415  /// Called periodically during device initialisation. Sends a series of commands to initialise
416  /// the drone.
417  void device_init();
418 
419  /// For internal use only.
420  /// Called periodically after device initialisation. Sends any commands accumulated by earlier calls to
421  /// addAt*Cmd() functions.
422  /// If the drone is flying sends a PCMD with the curent flying parameters
423  /// Also sends a REF command with appropriate flags for flying or grounded
424  /// Also sends a COMWDG command to refresh teh comms watchdog.
425  void update();
426 
427  /// Sends a command to the drone AT port
428  /// \param[in] msg The message to be sent
429  /// \param[in] len The length of the message in bytes
430  void sendAtCmd(uint8_t* msg, uint16_t len);
431 
432  /// Sends a string to the drone AT port
433  /// \param[in] s The ASCII string to send
434  void sendAtCmd(char* s);
435 
436  /// Sends the entire currently accumulated command buffer to the drone AT port
437  void sendCurrentAtCmd();
438 
439 private:
440  uint8_t _state;
441  uint8_t _init_step;
442  unsigned long _sequence;
443 
444  // Initialisation values
445  // These are used to set the CONFIG control: variables of the same name
446  float _control_yaw;
447  float _control_vz_max;
448  float _euler_angle_max;
449  float _altitude_max;
450  boolean _outdoor;
451 
452  // Flying command values
453  boolean _flying;
454  float _roll;
455  float _pitch;
456  float _gaz;
457  float _yaw;
458 
459 };
460 
461 #endif