ArDrone SDK 1.8 added
[mardrone] / mardrone / ARDrone_SDK_Version_1_8_20110726 / Examples / Linux / Navigation / Sources / UI / wiimote.c
diff --git a/mardrone/ARDrone_SDK_Version_1_8_20110726/Examples/Linux/Navigation/Sources/UI/wiimote.c b/mardrone/ARDrone_SDK_Version_1_8_20110726/Examples/Linux/Navigation/Sources/UI/wiimote.c
new file mode 100644 (file)
index 0000000..ffc6288
--- /dev/null
@@ -0,0 +1,344 @@
+/**
+ *  \brief    Wiimote handling implementation
+ *  \author   Aurelien Morelle <aurelien.morelle@parrot.com>
+ *  \version  1.0
+ *  \date     04/06/2007
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <generated_custom.h>
+
+#if defined(WIIMOTE_SUPPORT)
+       //#warning Wiimote support enabled
+       #include <bluetooth/bluetooth.h>
+       #include <cwiid.h>
+#else
+       //#warning Wiimote support disabled
+#endif
+
+#include "wiimote.h"
+
+input_device_t wiimote_device = {
+  "Wiimote",
+  open_wiimote,
+  update_wiimote,
+  close_wiimote
+};
+
+
+#if !defined(WIIMOTE_SUPPORT)
+//#warning Wiimote compilation disabled
+C_RESULT open_wiimote(void)
+{
+  return C_FAIL;
+}
+
+C_RESULT update_wiimote(void)
+{
+  return C_FAIL;
+}
+
+C_RESULT close_wiimote(void)
+{
+  return C_OK;
+}
+
+#else // ! WIIMOTE_SUPPORT
+#warning Wiimote compilation enabled
+
+#include <VP_Os/vp_os_print.h>
+
+static bdaddr_t bdaddr = {0};
+static cwiid_wiimote_t *wiimote = NULL;
+
+static struct acc_cal wm_cal;
+
+C_RESULT open_wiimote(void)
+{
+  C_RESULT res = C_OK;
+
+  printf("\nSearching for Wiimote - press both '1' and '2' on your Wiimote !!\n");
+
+  if(cwiid_find_wiimote(&bdaddr, WIIMOTE_FIND_TIMEOUT) == 0)
+  {
+    if( ! (wiimote = cwiid_open(&bdaddr, 0)) )
+      PRINT("Unable to connect to wiimote\n");
+    else
+      res = C_OK;
+  }
+
+  if(SUCCEED(res))
+    if(cwiid_set_rpt_mode(wiimote, CWIID_RPT_BTN|CWIID_RPT_ACC))
+      res = C_FAIL;
+
+  if(SUCCEED(res))
+    if (cwiid_get_acc_cal(wiimote, CWIID_EXT_NONE, &wm_cal))
+      res = C_FAIL;
+
+  cwiid_set_led(wiimote,1);
+
+  printf(" ... Wiimote found.\n");
+
+  return res;
+}
+
+void print_state(struct cwiid_state *state)
+{
+  printf("Battery: %d%%\n", (int)(100.0 * state->battery / CWIID_BATTERY_MAX));
+  printf("Buttons: %X\n", state->buttons);
+  printf("Acc: x=%d y=%d z=%d\n", state->acc[CWIID_X], state->acc[CWIID_Y], state->acc[CWIID_Z]);
+}
+
+//extern void api_set_iphone_acceleros(bool_t enable, float32_t fax, float32_t fay, float32_t faz);
+
+#define NEW_AMOUNT 0.1
+#define OLD_AMOUNT (1.0-NEW_AMOUNT)
+
+typedef struct{
+       float x,y,z;
+}vec3;
+
+typedef struct{
+       float r,p,t;
+}vec3sph;
+
+
+static void rumble(int flag)
+               {
+               static int localflag=0;
+               if (flag!=localflag){
+                       localflag=flag;
+                       cwiid_set_rumble(wiimote,flag);
+               }
+}
+
+static void leds(int flags)
+{
+               static int localflags=0;
+               if (flags!=localflags){
+                       localflags=flags;
+                       cwiid_set_led(wiimote,flags);
+               }
+}
+
+C_RESULT update_wiimote(void)
+{
+  C_RESULT res = C_OK;
+  static struct cwiid_state state,previous_state;
+
+  static int control_mode = 1;
+  static int valid_domain = 0;
+
+  int8_t x, y;
+  static int start=0;
+  static int select=0;
+
+  static vec3 a={0,0,0},s={0,0,0};
+  static vec3sph r={0,0,0},pr={0,0,0},rref={0,0,0};
+
+  static float pitch=0.0f,roll=0.0f,gaz=0.0f,yaw=0.0f;
+
+  float tmp;
+  static int fly=0;
+
+
+
+  if (cwiid_get_state(wiimote, &state))
+    {
+      fprintf(stderr, "Error getting state\n");
+      res = C_FAIL;
+    }
+
+
+#define SWITCHING(X) ((state.buttons&X) && !(previous_state.buttons&X))
+#define RELEASING(X) ((!state.buttons&X) && (previous_state.buttons&X))
+#define PRESSED(X) ((state.buttons&X))
+  static int flag_rumble=0;
+#define RUMBLE_ON { if (!flag_rumble) {flag_rumble=1;  } }
+  /* Sets how to use the wiimote */
+#define MAXMODE 4
+  if (SWITCHING(CWIID_BTN_MINUS)) {
+         control_mode--;
+         if (control_mode<1) control_mode=MAXMODE;
+         leds(1<<(control_mode-1));
+  }
+  if (SWITCHING(CWIID_BTN_PLUS))  {
+         control_mode++;
+         if (control_mode>MAXMODE) control_mode=1;
+         leds(1<<(control_mode-1));
+  }
+
+ /* Gets gravitation G projection on x,y,z axis */
+         a.x = - (float32_t) ((((double)state.acc[CWIID_X] - wm_cal.zero[CWIID_X]) /
+                                 (wm_cal.one[CWIID_X] - wm_cal.zero[CWIID_X])));
+         a.y = - (float32_t) ((((double)state.acc[CWIID_Y] - wm_cal.zero[CWIID_Y]) /
+                                 (wm_cal.one[CWIID_Y] - wm_cal.zero[CWIID_Y])));
+         a.z = + (float32_t) ((((double)state.acc[CWIID_Z] - wm_cal.zero[CWIID_Z]) /
+                         (wm_cal.one[CWIID_Z] - wm_cal.zero[CWIID_Z])));
+
+         s.x = (a.x<0.0f)?(1.0f):(-1.0f);
+         s.y = (a.y<0.0f)?(1.0f):(-1.0f);
+         s.z = (a.z<0.0f)?(1.0f):(-1.0f);
+
+         float ax2 = a.x*a.x;
+         float ay2 = a.y*a.y;
+         float az2 = a.z*a.z;
+
+         r.r = sqrtf((ax2+ay2)+az2);
+
+         switch(control_mode)
+         {
+         case 1:
+         case 2:
+
+                 if (r.r==0.0f) { r.p=r.t=0.0f; } else {
+                         // Angle gauche/droite
+                         r.p = asin(a.y);  if (isnan(r.p)) r.p=0.0f;
+
+                         // Sur plan vertical radial
+                                 r.t = acos(a.z/(sqrtf(az2+ax2)));  if (isnan(r.t)) r.t=0.0f;
+                                 r.t*=s.x;
+                 }
+                 break;
+
+         case 3:
+         case 4:
+
+                         if (r.r==0.0f) { r.p=r.t=0.0f; } else {
+                                 // Angle entre le projete de G sur le plan vertical longitudinal (yz) et l'axe z
+                                         r.p = acos(a.z/(sqrtf(az2+ay2)));  if (isnan(r.p)) r.p=0.0f;
+                                         /* If wiimote faces the ground */
+                                           //if (a.z<0.0f) r.p= M_PI-r.p;
+                                         r.p*=s.y;
+                                 // Idem sur le plan vertical radial
+                                         r.t = acos(a.z/(sqrtf(az2+ax2)));  if (isnan(r.t)) r.t=0.0f;
+                                         r.t*=s.x;
+                         }
+                         break;
+           }
+
+         r.r = (r.r+pr.r)/2.0f;
+         r.t = (r.t+pr.t)/2.0f;
+         r.p = (r.p+pr.p)/2.0f;
+
+
+
+  switch(control_mode)
+  {
+
+                 case 1:
+                 case 2:
+                         /* Wiimote is handled horizontally.
+                          * '2' button under left thumb
+                          * directionnal cross under right thumb
+                          */
+
+
+                         /* 0 -> buttons facing sky */
+
+                         if ((SWITCHING(CWIID_BTN_1)||SWITCHING(CWIID_BTN_2)||SWITCHING(CWIID_BTN_B))){  rref=r;  }
+
+                         if (PRESSED(CWIID_BTN_1)||PRESSED(CWIID_BTN_2)||PRESSED(CWIID_BTN_B))
+                         {
+                                 /* If wiimote facing ground */
+                                 if (a.z<0 && a.x>0)
+                                 {
+                                         rumble(1);
+                                 }
+                                 else
+                                 {
+                                         rumble(0);
+                                         leds(1<<(control_mode-1));
+                                         pitch = (r.t-rref.t)*1.0f; if (pitch<-1.0f) pitch=-1.0f; if (pitch>1.0f) pitch=1.0f;
+                                         roll  = -(r.p-rref.p)*0.75f; if (roll<-1.0f)  roll=-1.0f; if (roll>1.0f) roll=1.0f;
+                                         fly=1;
+                                 }
+                         }
+                         else
+                         {
+                                 pitch=roll=0;
+                                 rumble(0);
+                                 leds(1<<(control_mode-1));
+                                 fly=0;
+                         }
+
+
+                         gaz  = (PRESSED(CWIID_BTN_LEFT))? 1.0f: (PRESSED(CWIID_BTN_RIGHT)) ? -1.0f : 0.0f;
+                         yaw  = (PRESSED(CWIID_BTN_DOWN))? -1.0f: (PRESSED(CWIID_BTN_UP))   ? 1.0f : (control_mode==2) ? (-pitch*roll) : 0.0f;
+
+                         break;
+
+
+                 case 3:
+                 case 4:
+
+                         if (PRESSED(CWIID_BTN_B))
+                         {
+                                 if (a.z<-0.5f)
+                                 {
+                                         rumble(1);
+                                 }
+                                 else
+                                 {
+                                         rumble(0);
+                                         leds(1<<(control_mode-1));
+                                         pitch = -(r.p-rref.p)*1.5f; if (pitch<-1.0f) pitch=-1.0f; if (pitch>1.0f) pitch=1.0f;
+                                         roll  = (r.t-rref.t)*1.5f; if (roll<-1.0f)  roll=-1.0f; if (roll>1.0f) roll=1.0f;
+                                         fly=1;
+                                 }
+                         }
+                         else
+                                 {
+                                        rumble(0);
+                                    leds(1<<(control_mode-1));
+                                        fly=0;
+                                        pitch=roll=0;
+
+                                 }
+
+                         if (SWITCHING(CWIID_BTN_B))  { rref = r; }
+
+                         gaz  = (PRESSED(CWIID_BTN_DOWN))? -1.0f: (PRESSED(CWIID_BTN_UP)) ? +1.0f : 0.0f;
+                         yaw  = (PRESSED(CWIID_BTN_LEFT))? -1.0f: (PRESSED(CWIID_BTN_RIGHT))   ? 1.0f : (control_mode==4) ? (-pitch*roll) : 0.0f;
+
+  }
+  /* Buttons common to all modes */
+         if (SWITCHING(CWIID_BTN_A)) { start^=1;  ardrone_tool_set_ui_pad_start(start); }
+         if (SWITCHING(CWIID_BTN_HOME)) {
+                                                                 select^=1;
+                                                                 ardrone_tool_set_ui_pad_select(select);
+                                                                 ardrone_tool_set_ui_pad_start(0);
+                                                         }
+
+
+         //
+       //printf("Wiimote mode 2 [ax %f][ay %f][az %f]\n\033[1A", a.x,a.y,a.z);
+       printf("Wiimode %i  [rr %3.2f][rp %3.2f][rt %3.2f]\n", control_mode,r.r,r.p,r.t);
+       printf("[Fly %i][Ptc %3.2f][Rl %3.2f][Yw %3.2f][Gz %3.2f][Strt. %i][Sel. %i]\n\033[2A", fly,pitch,roll,yaw,gaz,start,select);
+         ardrone_at_set_progress_cmd( fly,/*roll*/roll,/*pitch*/pitch,/*gaz*/gaz,/*yaw*/yaw);
+
+  /*api_set_iphone_acceleros(
+                          (state.buttons&CWIID_BTN_2 ? 1 : 0)|(state.buttons&CWIID_BTN_A ? 2 : 0),
+                          a_x, a_y, a_z);*/
+
+  previous_state = state;
+  pr=r;
+
+  return C_OK;
+}
+
+C_RESULT close_wiimote(void)
+{
+  cwiid_close(wiimote);
+
+  return C_OK;
+}
+
+#endif // ! WIIMOTE_SUPPORT
+