/* This function is called in the update function, at a refresh rate of 20 ms */
C_RESULT ardrone_tool_update_custom() {
    // read from memdb and send to ardrone
    char buffer[1024];
    int hover = 0; // boolean indicating whether it's hovering or not
    float phi; // left/right angle
    float theta; // front/back angle
    float gaz; // verticle speed
    float yaw; // angular speed

    while (db_tryget(db, "drone_command", buffer, sizeof(buffer)) != -1)
    {
        sscanf(buffer, "%d,%f,%f,%f,%f", &hover, &phi, &theta, &gaz, &yaw);
        if (hover == 1) // hover
        {
            ardrone_at_set_progress_cmd(0, 0, 0, 0, 0);
        }
        else if (hover == -1) // land
        {
            ardrone_tool_set_ui_pad_start(0);
        }
        else // do stuff...
        {
            ardrone_at_set_progress_cmd(1, phi, theta, gaz, yaw);
        }
    }

    return C_OK;
}
Exemple #2
0
C_RESULT update_teleop(void)
{
	// This function *toggles* the emergency state, so we only want to toggle the emergency
	// state when we are in the emergency state (because we want to get out of it).
	ardrone_tool_set_ui_pad_select(needs_reset);
	needs_reset = false;

	// This function sets whether or not the robot should be flying.  If it is flying and you
	// send 0, the robot will slow down the motors and slowly descend to the floor.
	ardrone_tool_set_ui_pad_start(is_flying);

	float left_right = cmd_vel.linear.y;
	float front_back = cmd_vel.linear.x;
	float up_down = cmd_vel.linear.z;
	float turn = cmd_vel.angular.z;

	///printf("LR:%f FB:%f UD:%f TURN:%f\n", left_right, front_back, up_down, turn);
	if(left_right == 0 && front_back == 0 && up_down == 0 && turn == 0)
    {
        printf("Drone im Hover Mode\n");
        ardrone_at_set_progress_cmd(0, left_right, front_back, up_down, turn);
    }else{
        ardrone_at_set_progress_cmd(1, left_right, front_back, up_down, turn);
    }

	return C_OK;
}
DEFINE_THREAD_ROUTINE( comm_control, data )
{
    int seq_no = 0,prev_start = 0;
    control_data_t l_control;

    PRINT( "Initilizing Thread 1\n" );
    while( end_all_threads == 0 )
    {
    vp_os_delay(10);
    //PRINT("E:%d,S:%d\n\n",end_all_threads,control_data.start );
    vp_os_mutex_lock( &control_data_lock ); //Taking Control Mutex
    	l_control = control_data;
    vp_os_mutex_unlock( &control_data_lock );

    if( prev_start == 0 && l_control.start == 1 ) //To Start Drone
    {
        ardrone_tool_set_ui_pad_start( 1 );
        prev_start = 1;
    }
    else if( prev_start == 1 && l_control.start == 0 ) //To Stop the Drone
    {
        ardrone_tool_set_ui_pad_start( 0 );
        prev_start = 0;
    }
    //PRINT("YAW : %f\n\n",l_control.yaw);
    ardrone_at_set_progress_cmd( ++seq_no,l_control.roll,l_control.pitch,l_control.gaz,l_control.yaw); //command to make drone move.
    //ardrone_at_set_progress_cmd( ++seq_no,0,0,0,-1);
    }
    PRINT( "Communication Thread Ending\n" );
    return C_OK;
}
Exemple #4
0
void drone_fly(float pitch, float strafe, float upwards, float yaw) {
  pthread_mutex_lock(&drone_sharedDataMutex);
  if (!drone_targetEmergency && !drone_emergency) {
    if (drone_atCommands++ < MAX_AT_COMMANDS_PER_NAVDATA) {
      ardrone_at_set_progress_cmd(1, strafe, pitch, upwards, yaw);
    }
  }
  pthread_mutex_unlock(&drone_sharedDataMutex);
}
Exemple #5
0
void drone_hover() {
  pthread_mutex_lock(&drone_sharedDataMutex);
  if (!drone_targetEmergency && !drone_emergency) {
    if (drone_atCommands++ < MAX_AT_COMMANDS_PER_NAVDATA) {
      ardrone_at_set_progress_cmd(0, 0, 0, 0, 0);
    }
  }
  pthread_mutex_unlock(&drone_sharedDataMutex);
}
C_RESULT ardrone_control() {
    const char * linefiller="                                              ";
    static int nCountFrequency=0;
    static bool function_first_call = true;
    nCountFrequency++;
    if(nCountFrequency%50==0)
    {
        printf("过去了  %d    秒!!!!\n",nCountFrequency/50);
        if(nCountFrequency%5000==0)
            nCountFrequency=0;
    }
    if (function_first_call) {
        printf("Sending flat trim - make sure the drone is horizontal at client startup.\n");
        ardrone_at_set_flat_trim(); //向无人机发送确定无人机是水平躺着,每次无人机启动都要发送,不可在无人机飞行时调用此函数
        function_first_call=false;
        //	vp_os_memcpy(previous_keyboardState,keyboardState,sizeof(keyboardState));
        return C_OK;

    }

    ARWin32Demo_AcquireConsole();
    ARWin32Demo_SetConsoleCursor(0,12);

    if(emergency!=emergency_p) { //以下代码 待服务器端完成后,需再次修改
        if(emergency=0)
        {
            ardrone_tool_set_ui_pad_start(0);
            ardrone_tool_set_ui_pad_select(1);
            printf("Sending emergency.%s\n",linefiller);
        }
        else//若之前按下,现在没按,说明是emergency状态转常规飞行
        {
            ardrone_tool_set_ui_pad_select(0);
        }
    }

    if((takeoff!=takeoff_p)&&takeoff==1)
    {
        start^=1;
        ardrone_tool_set_ui_pad_start(start);
        printf("飞机起飞 %i.%s\n",start,linefiller);
    }
    if((trim!=trim_p)&&trim==1)
    {
        ardrone_at_set_flat_trim();
        printf("水平矫正.%s\n",linefiller);
    }

    ardrone_at_set_progress_cmd(hover,roll, pitch, gaz, yaw);
    printf("[Pitch %f] [Roll %f] [Yaw %f] [Gaz %f]%\n",pitch,roll,yaw,gaz);

    ARWin32Demo_ReleaseConsole();

    return C_OK;
}
Exemple #7
0
 int ardrone_at_set_radiogp_inputC(int32_t y, int32_t x, int32_t z, int32_t yaw){
   
   if(y == lasty && x == lastx && z == lastz && yaw == lastyaw && repeatCount < 10)
   {
     repeatCount++;
     return 0; //only continue if does not mach last command sent
   }
   repeatCount = 0;
   /*if(commandLog == NULL)
   {
     char filename[256];
     sprintf(filename, "ControlLog-%d.txt", (int)time(NULL));
     commandLog = fopen(filename, "w");
     fprintf(commandLog, "Time Pitch Roll Gaz Yaw\n");
   }
   else
   {
     timeval t;
     gettimeofday(&t, NULL);
     fprintf(commandLog, "%d.%06d %d %d %d %d \n", (int)t.tv_sec, (int)t.tv_usec, y, x, z, yaw);
   }*/
   
   /************* at_set_radiogp_input ****************
   * Description : Fill struct radiogp_cmd, 
   * used with at_cmds_loop function.
   * pitch : y-axis (rad) (-25000, +25000)  
   * roll : x-axis (rad) (-25000, +25000) 
   * gaz :  altitude (mm/s) (-25000, +25000)
   * yaw : z-axis (rad/s) (-25000, +25000)
   */
     //Make sure commands are in range
     if(x < -25000) x = -25000;
     if(x > 25000) x = 25000;
     if(y < -25000) y = -25000;
     if(y > 25000) y = 25000;
     if(z < -25000) z = -25000;
     if(z > 25000) z = 25000;
     if(yaw < -25000) yaw = -25000;
     if(yaw > 25000) yaw = 25000;
     ardrone_at_set_progress_cmd( 1,
                                  x/25000.0,
                                  y/25000.0,
                                  -z/25000.0,
                                  yaw/25000.0);
     //ardrone_at_set_radiogp_input(y, x, z, yaw); old command
    // PRINT("Pitch:%3d Roll:%3d Gaz:%3d Yaw:%3d\n", y, x, z, yaw);
     lastx = x;
     lasty = y;
     lastz = z;
     lastyaw = yaw;
     return 1;
 }
Exemple #8
0
C_RESULT update_fpad(void){

	/*FuzzyControl( &X , 0.0 , h1 );
	FuzzyControl( &Y , 0.0 , h2 );
	FuzzyControl( &Yaw , 0.0 , h3 );
	FuzzyControl( &Z , 0.0 , h4 );//*/
	//printf("%d\n",fcx);
	//dispControl(&Z);
	/*ardrone_at_set_progress_cmd( 1,
                                    //roll/(float)(stick1LR-center_x1)/32767.0f,
                                    //pitch/(float)(stick1UD-center_y1)/32767.0f,
                                    //gaz/-(float)(stick2UD-center_x2)/32767.0f,
                                    //yaw/(float)(stick2LR-center_y2)/32767.0f );*/
                                    //printf("++%0.2f++\n",Z.vout);
	if(heightTestMode==0){
	  if(theControl.phi!=0||theControl.theta!=0||theControl.gaz!=0||theControl.yaw!=0){
			ardrone_at_set_progress_cmd( 1,theControl.phi,theControl.theta,theControl.gaz,theControl.yaw);
			ardrone_at_set_led_animation(FIRE,10,1);
		}
		else{
			bringItOn();
		}
	}
	else{
		
		static int timer=0;
		static int theFlag=0;
		if(timer<heightTestModeTop){
			if(theFlag%2==0){
				Z.ref=heightTestModeH1;
				zg.ref=Z.ref;
			}
			else{
				Z.ref=heightTestModeH2;
				zg.ref=Z.ref;
			}
			timer++;
			//printf("%d!\n",timer);
		}
		else {
			printf("CHANGE to %0.2f !!!\n\n",Z.ref);
			theFlag++;
			timer=0;
		}
		bringItOn();
	}
	return C_OK;
}
Exemple #9
0
void bringItOn(){

  		//static GdkPixbuf *pixbuf = NULL;
  		
		  //gui_t *gui = get_gui();
			
			zg.z=Z.vin;
			zg.x=X.vin;
			zg.y=Y.vin;
			zg.w=Yaw.vin;
			fuzzyGraph( &zg, zvg );
    	
			fuzzyControl(&Z,&X,&Y,&Yaw);
			//printf(">>>%5.2f",fabs(Z.vin-Z.ref));
			//if(fabs(Z.vin-Z.ref)<200||Z.vin>Z.ref){
				ardrone_at_set_progress_cmd( 0,-X.vout,Y.vout,Z.vout,Yaw.vout);
			/*}
			else
				ardrone_at_set_progress_cmd( 0,0,0,Z.vout,0);//*/
			//printf("-");
}
Exemple #10
0
C_RESULT update_teleop(void)
{
	// This function *toggles* the emergency state, so we only want to toggle the emergency
	// state when we are in the emergency state (because we want to get out of it).
	//fprintf(stderr, "%d\n", int(needs_reset));
	if (needs_reset)
	{
	//	fprintf(stderr, "needs_reset true\n");
		ardrone_tool_set_ui_pad_select(needs_reset);
		needs_reset = false;
	//	fprintf(stderr, "needs_reset false\n");
	}

	// ******dep****** This function sets whether or not the robot should be flying.  If it is flying and you
	// ******dep****** send 0, the robot will slow down the motors and slowly descend to the floor.
	//rujian July 30
	if (needs_takeoff)
	{
		ardrone_tool_set_ui_pad_start(true);
		needs_takeoff = false;
	}

	if (needs_land)
	{
		ardrone_tool_set_ui_pad_start(false);
		needs_land = false;
	}

	float left_right = cmd_vel.linear.y;
	float front_back = cmd_vel.linear.x;
	float up_down = cmd_vel.linear.z;
	float turn = cmd_vel.angular.z;

	ardrone_at_set_progress_cmd(do_not_hover, left_right, front_back, up_down, turn);	//rujian July27
	return C_OK;
}
DEFINE_THREAD_ROUTINE( thread1, data )
{
    int seq_no = 0,prev_start = 0;
    PRINT( "Initilizing Thread 1\n" );
    while(1)
    {
    vp_os_delay(100);

    vp_os_mutex_lock( &control_data_lock ); //Taking Control Mutex

    if( prev_start == 0 && control_data.start == 1 )
    {
        ardrone_tool_set_ui_pad_start( 1 );
        prev_start = 1;
    }
    else if( prev_start == 1 && control_data.start == 0 )
    {
        ardrone_tool_set_ui_pad_start( 0 );
        prev_start = 0;
    }
    ardrone_at_set_progress_cmd( ++seq_no,control_data.roll, control_data.pitch, control_data.gaz, control_data.yaw); //command to make drone move.
    vp_os_mutex_unlock( &control_data_lock );
    }
}
	int _stdcall SetProgressCmd(BOOL bhovering, float roll, float pitch, float gaz, float yaw)
	{
		ardrone_at_set_progress_cmd((hovering)? 0:1, roll, pitch, gaz, yaw);
		printf("Sent Progress Cmd\n");
		return 0;
	}
Exemple #13
0
void sendControls(bool_t accelero, bool_t left, bool_t right, bool_t up, bool_t down)
{
	ardrone_at_set_progress_cmd(accelero, ctrldata.accelero_phi, ctrldata.accelero_theta, ctrldata.gaz, ctrldata.yaw);
}
Exemple #14
0
C_RESULT update_gamepad(void) {

	static int32_t start;
    static float phi = 0, theta = 0, gaz = 0, yaw = 0;
    phi = theta = gaz = yaw = 0.0;
    
	struct js_event js_e_buffer[64];
	ssize_t res = read(joy_dev, js_e_buffer, sizeof(struct js_event) * 64);

	if( !res || (res < 0 && errno == EAGAIN) )
		return C_OK;

	if( res < 0 )
		return C_FAIL;

	if (res < (int) sizeof(struct js_event))// If non-complete bloc: ignored
		return C_OK;

	// Buffer decomposition in blocs (if the last is incomplete, it's ignored)
	bool_t refresh_values = TRUE;
	bool_t enable = FALSE;
	int32_t idx = 0;
	printf("Num events: %d\n", sizeof(struct js_event));
	for (idx = 0; idx < res / sizeof(struct js_event); idx++) {

		unsigned char type = js_e_buffer[idx].type;
		unsigned char number = js_e_buffer[idx].number;
		short value = js_e_buffer[idx].value;

		if (type & JS_EVENT_INIT ) {

			break;
		}
		else if (!value) {

			break;
		}
		else if (type & JS_EVENT_BUTTON ) {
            printf("BUTTON: %d\n", number);
            refresh_values = TRUE;
			switch(number ) {

				case BUTTON_START :
					start ^= 1;
					ardrone_tool_set_ui_pad_start( start );
					g_autopilot = FALSE;
					break;
				case BUTTON_SELECT :
					ardrone_tool_set_ui_pad_select(js_e_buffer[idx].value);
					//g_exit = TRUE;
					return C_OK;
				case BUTTON_ZAP:
					agent_zap();
					break;
			    case BUTTON_GAZ_UP:
			        enable = TRUE;
			        gaz = +1;
			        break;
			    case BUTTON_GAZ_DOWN:
			        enable = TRUE;
    			    printf("GAZ DOWN: %f \n", -1);
			        gaz = -1;
			        break;
			    case BUTTON_YAW_R:
			        enable = TRUE;
			        yaw = +js_e_buffer[idx].value;
			        break;
		        case BUTTON_YAW_L:
		            enable = TRUE;
			        yaw = -js_e_buffer[idx].value;
			        break;
				/*case BUTTON_AUTO:
					if (g_autopilot) {
						refresh_values = TRUE;
					}
					else {
						g_autopilot = TRUE;
					}
					break;*/
			}

		}
		else if (type & JS_EVENT_AXIS ) {
            printf("AXIS: %d\n", number);
			if (number != AXIS_IGNORE3 && number != AXIS_IGNORE4) {
				refresh_values = TRUE;
				enable = TRUE;
				float angle = value / (float)SHRT_MAX;
				printf("ANGLE: %f", angle);
				switch (number) {
					case AXIS_PHI:
						phi = angle;
						break;
					case AXIS_THETA:
						theta = angle;
						break;
					//case AXIS_GAZ:
					//	gaz = angle;
					//	break;
					//case AXIS_YAW:
					//	yaw = angle;
					//	break;
				}
			}
		}

	} // loop over events


	if (refresh_values) {

		g_autopilot = FALSE;
		printf("\nSENDING: %f, %f, %f, %f\n", phi, theta, gaz, yaw);
		ardrone_at_set_progress_cmd(enable, phi, theta, gaz, yaw);
	}

	return C_OK;
}
Exemple #15
0
C_RESULT update_radioGP(void)
{
  static float32_t roll = 0, pitch = 0, gaz=0, yaw=0;
  static bool_t refresh_values = FALSE;
  ssize_t res;
  static struct js_event js_e_buffer[64];

  res = read(joy_dev, js_e_buffer, sizeof(struct js_event) * 64);

  if( !res || (res < 0 && errno == EAGAIN) )
    return C_OK;

  if( res < 0 )
    return C_FAIL;

  if (res < (int) sizeof(struct js_event))// If non-complete bloc: ignored
    return C_OK;

  // Buffer decomposition in blocs (if the last is incomplete, it's ignored)
  int32_t idx = 0;
  refresh_values = FALSE;
  for (idx = 0; idx < res / sizeof(struct js_event); idx++)
  {
    if(js_e_buffer[idx].type & JS_EVENT_INIT )// If Init, the first values are ignored
    {
      break;
    }
    else if(js_e_buffer[idx].type & JS_EVENT_BUTTON )// Event Button detected
    {
      switch( js_e_buffer[idx].number )
      {
        case GP_BOARD_LEFT :
					ardrone_tool_set_ui_pad_start(js_e_buffer[idx].value);
					break;
        case GP_SIDE_RIGHT :
					ardrone_tool_set_ui_pad_r2(js_e_buffer[idx].value);
					break;
        case GP_IMPULSE :
					ardrone_tool_set_ui_pad_select(js_e_buffer[idx].value);
					break;
        case GP_SIDE_LEFT_DOWN :
					ardrone_tool_set_ui_pad_ad(js_e_buffer[idx].value);
					break;
        case GP_SIDE_LEFT_UP :
					ardrone_tool_set_ui_pad_ad(js_e_buffer[idx].value);
					break;
        default: break;
      }
    }
    else if(js_e_buffer[idx].type & JS_EVENT_AXIS )// Event Axis detected
    {
      refresh_values = TRUE;
      switch( js_e_buffer[idx].number )
      {
        case GP_PITCH:
          pitch = js_e_buffer[idx].value;
          break;
        case GP_GAZ:
          gaz = js_e_buffer[idx].value;
          break;
        case GP_ROLL:
          roll = js_e_buffer[idx].value;
          break;
        case GP_PID:
          break;
        case GP_YAW:
          yaw = js_e_buffer[idx].value;
          break;
        default:
          break;
      }
    }
    else
    {// TODO: default: ERROR (non-supported)
    }
  }

  if(refresh_values)// Axis values to refresh
    {
       ardrone_at_set_progress_cmd( 1,
                                               roll/25000.0,
                                               pitch/25000.0,
                                               -gaz/25000.0,
                                               yaw/25000.0);
    }

  return C_OK;
}
Exemple #16
0
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;
}
void ardronewin32_progress(int enable, float roll, float pitch, float gaz, float yaw)
{
	ardrone_at_set_progress_cmd(enable, roll, pitch, gaz, yaw);
}
//NEW THREADS ADDED BY ME
DEFINE_THREAD_ROUTINE(drone_logic, data){
    //the game is active from start, but the logic will start only when a match is active
    
    struct timespec flying_sleep_time;
    flying_sleep_time.tv_sec = 0;
    flying_sleep_time.tv_nsec = 0000000;
    
    int emptiness_counter = 0;
    int shooting_counter = 0;
    
    int hovering = 0; //0 hover, 1 move
    float phi = 0.0; //left/right angle. Between [-1.0,+1.0], with negatives being leftward movement
    float theta = 0.0; //front/back angle. Between [-1.0, +1.0], with negatives being frontward movement
    float gaz = 0.0; //vertical speed. Between [-1.0, +1.0]
    float yaw = 0.0; //Angular speed. Between [-1.0, +1.0]
    
    while(game_active){
        if(match_active){
            
            if(takeoff){
                //TODO:Uncomment this when you are ready to make the drone move autonomously
                //ardrone_tool_set_ui_pad_start(1);
                //ardrone_at_set_progress_cmd(0,0.0,0.0,0.0,0.0);
                takeoff = 0;
            }
            
            //--- CHASING ---// 
            //NOTE: Hill have higher priority than enemy, this imply that if there is the enemy and an hill
            //the drone will choose the hill. 
            //NOTE: doing so, the drone won't care if the enemy is standing between it and the hill
            if(hill_in_sight){
                emptiness_counter = 0;
                shooting_counter = 0;
                
                //move toward the hill
                if((hill_distance > HILL_MIN_DISTANCE) && (hill_distance < HILL_MAX_DISTANCE)){
                    
                    printf("MOVING TOWARD THE HILL\n");
                    
                    hovering = 1;
                    phi = 0.0;
                    gaz = 0.0;
                    
                    //--- SET THE YAW ---//
                    //This is to correct the direction of the drone
                    if(abs(hill_offset_from_center) > ERROR_FROM_CENTER_FOR_HILL){
                        //TODO: find the right multiplier for yaw and discover which way the drone turn
                        yaw = (hill_offset_from_center) * YAW_COEFF; //YAW_COEFF = 0.007
                        //yaw has to be between -1.0 and +1.0
                        if(yaw > 1.0) {
                            yaw = 1.0;
                        } else if(yaw < -1.0){
                            yaw = -1.0;
                        }
                    }
                    
                    //--- SET THE APPROACHING SPEED ---//
                    //The closer the drone is to the hill, the slower it goes
                    
                    //Need to be negative to move forward
                    theta = -1*((hill_distance) / THETA_COEFF); //TODO: find the right theta_coeff
                    if(theta > 0.0) {
                        theta = -0.1;
                    } else if(theta < -1.0){ //TODO: I may want to rethink the maximum speed that the drone can reach!
                        theta = -1.0;
                    }
                    
                    flying_sleep_time.tv_sec = 1;
                    flying_sleep_time.tv_nsec = 0000000;
                    
                //hover over the hill
                } else if(hill_distance < HILL_MIN_DISTANCE) {
                    //ardrone_at_set_progress_cmd(0,0,0,0,0); //to hover
                    
                    printf("HOVERING ON TOP OF THE HILL\n");
                    
                    hovering = 0;
                    phi = 0.0;
                    theta = 0.0;
                    gaz = 0.0;
                    yaw = 0.0;
                    
                    //TODO: if you are close enough, you have to switch the cam and then inizialize 
                    //the recognition procedure. (wait tot secs)
                    //TODO: I have problem switching cam
                    vp_os_mutex_lock(&drone_score_mutex);
                        drone_add_score = 1;
                    vp_os_mutex_unlock(&drone_score_mutex);
                    //TODO: here, you switch the camera back
                    flying_sleep_time.tv_sec = 5;
                    flying_sleep_time.tv_nsec = 0000000;
                }
                
            } else if(enemy_in_sight){
                emptiness_counter = 0;
                
                //back up! Too close to the enemy (we don't want to phisically hit the human player!)
                if(enemy_distance < ENEMY_MIN_DISTANCE){
                    shooting_counter = 0;
                    
                    hovering = 1;
                    theta = 1.0; //Move backward at maximum speed
                    phi = 0.0;
                    gaz = 0.0;
                    yaw = 0.0;
                    
                    //TODO: test this!
                    flying_sleep_time.tv_sec = 2;
                    flying_sleep_time.tv_nsec = 0000000;
                    
                    printf("BACKING UP FROM THE ENEMY\n");
                    
                } else if((enemy_distance > ENEMY_MIN_DISTANCE) && (enemy_distance < ENEMY_SHOOTING_DISTANCE)){
                    
                    printf("INSIDE SHOOTING!!!!\n");
                    
                    shooting_counter++;
                    
                    if(shooting_counter > 5){
                        
                        //TODO: make the drone move
                        //TODO:set some sleep time
                        printf("ENOUGH WITH THE SHOOTING\n");
                        
                    } else {
                        
                        //TODO: shoot!!
                        //make animation.
                        
                        if(enemy_offset_from_center < ERROR_FROM_CENTER_FOR_ENEMY){
                            vp_os_mutex_lock(&enemy_score_mutex);
                            enemy_lose_score = 1;
                            vp_os_mutex_lock(&enemy_score_mutex);
                        }
                        
                        printf("SHOOTING!!!!!!!!\n");
                        
                        hovering = 0;
                        phi = 0.0;
                        theta = 0.0;
                        gaz = 0.0;
                        
                        //--- SET THE YAW ---//
                        //This is to correct the direction of the drone
                        if(abs(enemy_offset_from_center) > ERROR_FROM_CENTER_FOR_ENEMY){
                            //TODO: find the right multiplier for yaw and discover wich way the drone turn
                            yaw = (enemy_offset_from_center) * YAW_COEFF; //YAW_COEFF = 0.007
                            //yaw has to be between -1.0 and +1.0
                            if(yaw > 1.0) {
                                yaw = 1.0;
                            } else if(yaw < -1.0){
                                yaw = -1.0;
                            }
                        }
                        
                        flying_sleep_time.tv_sec = 1;
                        flying_sleep_time.tv_nsec = 0000000;
                    }
                
                } else if((enemy_distance > ENEMY_SHOOTING_DISTANCE) && (enemy_distance < ENEMY_MAX_DISTANCE)){
                    
                    shooting_counter = 0;
                    
                    //TODO: in this case I may want to just make the drone search for hills
                    //TODO: it may escape, turning itself so the led won't face the enemy anymore
                    //TODO: set some sleep time
                    
                    //--- SET THE YAW ---//
                    //This is to correct the direction of the drone
                    if(abs(enemy_offset_from_center) > ERROR_FROM_CENTER_FOR_ENEMY){
                        //TODO: find the right multiplier for yaw and discover wich way the drone turn
                        //TODO: in this case, I won't to make the drone move away from the enemy, so the algorithm below 
                        //has to be changed
                        yaw = (enemy_offset_from_center) * YAW_COEFF; //YAW_COEFF = 0.007
                        //yaw has to be between -1.0 and +1.0
                        if(yaw > 1.0) {
                            yaw = 1.0;
                        } else if(yaw < -1.0){
                            yaw = -1.0;
                        }
                    }
                }
                
                
            
            //NOTHING IN SIGHT
            } else {
                //If nothing is in sight I set a counter that increment every time I pass directly from here 
                //and make the drone rotate around itself. After tot passages with nothing in sight I take measure to land the drone.
                if(emptiness_counter == 0){
                    //TODO: set up everything for the algorithm to start
                    emptiness_counter = 1;
                    //yaw = something != to zero;
                    //everything else if zero (I don't know about hovering... problably should be 1 here)
                } else {
                    emptiness_counter++;
                    //TODO: set some sleep time
                    if(emptiness_counter > 10){
                        //TODO:land the drone and make the game stop
                        //so set everything that should to zero
                    }
                }
            }
            
            //---TELL THE DRONE TO MOVE---//
            //TODO: uncomment the line below when you're ready!
            //ardrone_at_set_progress_cmd(hovering,phi,theta,gaz,yaw);
            nanosleep(&flying_sleep_time, NULL);
            //NOTE: if the sleep remain under 2 secs it's ok. 
            //Only the hill recognition can have more, because the drone can't be hurt at that time.
            
            //NOTE: I don't know why, but if I add this printf the condition below works
            //printf("%d",drone_wounded);
            
            //---BEING HIT---//
            if(drone_wounded){
                //TODO: make the drone move as if it was being shot
                //maybe this should be moved in the flying thread
                vp_os_mutex_lock(&drone_wound_mutex);
                    drone_wounded = 0;
                vp_os_mutex_unlock(&drone_wound_mutex);
                
                //TODO: you can choose between this animation, defined in Soft/Common/config.h
                /*ARDRONE_ANIM_PHI_M30_DEG= 0,
                 A RDRONE_ANIM_PHI_30_DE*G,
                 ARDRONE_ANIM_THETA_M30_DEG,
                 ARDRONE_ANIM_THETA_30_DEG,
                 ARDRONE_ANIM_THETA_20DEG_YAW_200DEG,
                 ARDRONE_ANIM_THETA_20DEG_YAW_M200DEG,
                 ARDRONE_ANIM_TURNAROUND,
                 ARDRONE_ANIM_TURNAROUND_GODOWN,
                 ARDRONE_ANIM_YAW_SHAKE,
                 ARDRONE_ANIM_YAW_DANCE,
                 ARDRONE_ANIM_PHI_DANCE,
                 ARDRONE_ANIM_THETA_DANCE,
                 ARDRONE_ANIM_VZ_DANCE,
                 ARDRONE_ANIM_WAVE,
                 ARDRONE_ANIM_PHI_THETA_MIXED,
                 ARDRONE_ANIM_DOUBLE_PHI_THETA_MIXED,
                 ARDRONE_ANIM_FLIP_AHEAD,
                 ARDRONE_ANIM_FLIP_BEHIND,
                 ARDRONE_ANIM_FLIP_LEFT,
                 ARDRONE_ANIM_FLIP_RIGHT,
                 ARDRONE_NB_ANIM_MAYDAY*/
                //anim_mayday_t param;
                //ARDRONE_TOOL_CONFIGURATION_ADDEVENT (flight_anim, param, myCallback);
                ardrone_at_set_led_animation(BLINK_GREEN_RED, 0.25, 4);
                //TODO: freeze the drone for some time, also?
                //nanosleep(&shot_rumble_time, NULL);
            }
            
        //MATCH OVER
        } else {
            //land the drone
            ardrone_at_set_progress_cmd(0,0.0,0.0,0.0,0.0);
            ardrone_tool_set_ui_pad_start(0);
            //TODO: I may need some sleep time to make the drone land before closing everyting
        }
    }
    
    return C_OK;
}
C_RESULT display_stage_transform (display_stage_cfg_t *cfg, vp_api_io_data_t *in, vp_api_io_data_t *out)
{
	if(count > 1)
	{
		temp_x = cur_x;
		temp_y = cur_y;
	}

	int i = 0;
  	const char *cascade_name = "/usr/share/opencv/haarcascades/haarcascade_frontalface_alt.xml";
  	CvHaarClassifierCascade *cascade = 0;
  	CvMemStorage *storage = 0;
  	CvSeq *faces;

	cascade = (CvHaarClassifierCascade *) cvLoad (cascade_name, 0, 0, 0);

	if(!cascade)
	{
		printf("Could not load cascade.\n");
		return -1;
	}
  	
	uint32_t width = 0, height = 0;
    	getPicSizeFromBufferSize (in->size, &width, &height);

	//Obtain image from ARDrone and convert it to OpenCV format.
    	IplImage *img = ipl_image_from_data((uint8_t*)in->buffers[0], 1, 640, 360);

	storage = cvCreateMemStorage (0);
    	cvClearMemStorage (storage);

	//DetectFaces
	faces = cvHaarDetectObjects (img, cascade, storage, 1.11, 4, 0, cvSize(30, 30), cvSize (0, 0));
    	

	for (i = 0; i < (faces ? faces->total : 0); i++) 
	{
		CvRect *r = (CvRect *) cvGetSeqElem (faces, i);
      		doMosaic(img, r->x, r->y, r->width, r->height, 10);
		cur_x = r->x;
		cur_y = r->y;
		//printf("In the loop.\n");
		count++; //increases count when detect faces
 	}
	
	if(count > 2)
	{
		printf("prev_x = %d, prev_y = %d, cur_x = %d, cur_y = %d\n", temp_x, temp_y, cur_x, cur_y);
		if(cur_x - temp_x > 3)
		{
			//printf("Move Right.\n");
			ardrone_at_set_progress_cmd( 1, 1.0, 0.0, 0.0, 0.0 );
		}

		if(cur_x - temp_x < -3)
		{
			//printf("Move Left.\n");
			ardrone_at_set_progress_cmd( 1, -1.0, 0.0, 0.0, 0.0 );
		}

		if(cur_y - temp_y > 3)
		{
			//printf("Move Down.\n");
		        ardrone_at_set_progress_cmd( 1, 0.0, 0.0, -1.0, 0.0 );
		}

		if(cur_y - temp_y < -5)
		{
			//printf("Move Up.\n");
			//ardrone_at_reset_com_watchdog();
		        ardrone_tool_set_progressive_cmd( 1, 0.0, 0.0, 0.3, 0.0 );
			//vp_os_delay(1000);
		}
	}

	//emergency++;p

	if(count > 50)
	{
		printf("Exit\n");
		ardrone_tool_set_ui_pad_start(0);
		return -1;
	}

	cvNamedWindow("FaceDetect", CV_WINDOW_AUTOSIZE);
	cvShowImage("FaceDetect", img);
	cvWaitKey(1);
	cvReleaseImage(&img);

    return C_OK;
}