int32_t shutdown_all(cwiid_wiimote_t *wiimote)
{
	stop_motors();
	set_ir_led(false);
	write_status_led(STATUS_LED_OFF, 0);
	return cwiid_close(wiimote);
}
Example #2
0
void epuckPlayer()
{
  //e_start_agendas_processing();
  //e_init_motors();
  //e_init_prox();
  //e_init_uart1();

  /* Must send anything here or it don't work. Is it a bug? */
  e_send_uart1_char("epuckSide_v3.0", 14);

  unsigned a,b;

  /* Flash the LED's in a singular manner for show that this program is in
   * epuck memory */
  for(a=0; a<8; a++)
    for(b=0; b<20000; b++)
      e_set_led(a ,1); /* LED ON */

  for(a=0; a<8; a++)
    for(b=0; b<20000; b++)
      e_set_led(a ,0); /* LED OFF */

  char command;
  while(1)
  {
    command = recv_char();

    switch(command)
    {
    case 0x13:
      recv_vel();
      break;
    case 0x14:
      send_steps();
      break;
    case 0x16:
      read_ir_sensors();
      break;
    case 0x15:
      stop_motors();
      break;
    case 0x17:
      read_camera();
      break;
    case 0x18:
      set_LEDs();
      break;
    case 0x01:
      sendVersion();
      break;
    case 0x02:
      config_camera();
      break;
    }
  }
}
Example #3
0
//==============================
//==============================
int main(int argc, char *argv[])
{
    int ret;
    //printf("[wifibot - go]\n");
    /*
       if(argc==4)
       {
       strcpy(host_addr,argv[1]);
       target_distance=100*atof(argv[2]); //convert to cm
       target_angle=atof(argv[3]);
       }
       else
       {
       printf("syntax: go [address] [distance] [angle]\n");
       exit(1);
       }
       */
    if(process_args(argc, argv)<0)
    {
        printf("Syntax: move -h <address> -d <distance> -a <angle> -s <speed>\n");
        exit(1);
    }
    if((socket_command=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP))<0)
    {
        fprintf(stderr,"Command socket error\n");
        exit(1);
    }
    memset((char *) &myaddr_command, 0, sizeof(myaddr_command));
    myaddr_command.sin_family=AF_INET;
    myaddr_command.sin_port=htons(PORT_COMMAND);
    myaddr_command.sin_addr.s_addr=inet_addr(host_addr); //inet_addr(HOST_ADDR);
    stop_motors();
    if((ret = pthread_create(&threads[0], NULL, th_robot_status, (void *) 0)) != 0)
    {
        fprintf(stderr,"Status thread (%s)\n", strerror(ret));
        exit (1);
    }
    /*
       if((ret = pthread_create(&threads[1], NULL, th_gps, (void *) 0)) != 0)
       {
       printf("ERRR gps thread (%s)\n", strerror(ret));
       exit (1);
       }
       */
    while(!wait_for_status)
    {
        usleep(50000);
    }
    // do the thing and exit
    //printf("DIST_START: %.2f\n",target_distance);
    me.dist_from_start=0;
    rotate();
    go_forward();
    printf("[wifibot] %.2f\n",me.dist_from_start/100);
    return 0;
}
Example #4
0
void linecheck(int32_t * u_fwd, int32_t * u_back, uint8_t * iterations, uint8_t moves)
{
	if((*iterations) >= moves)
	{
		(*u_fwd) = 0;
		(*u_back) = 0;
		(*iterations) = 0;
		stop_motors(0);										// Change state and stop motors
	}
}
Example #5
0
void stop_omni_realtime(void)
{
	printf("Stopping...\n");


	/* Signal a stop the realtime thread */
    exiting = 1;
    pthread_join(thread, 0);

	/* Now stop all motors. */
	stop_motors();

	printf("Unloading.\n");
}
Example #6
0
//===========
void rotate()
{
    uchar speed_flag;
    target_angle = ((long)target_angle) % 360;
#ifdef debug_printf
    printf("ROT: deg %.2f", target_angle);
#endif
    target_angle = to_rad(target_angle);
    //target_angle = target_angle%(2*M_PI);
    if(target_angle>=0)
    {
        if(target_angle<=M_PI)
        {
            speed_flag=FLAG_RIGHT;
        }
        else
        {
            speed_flag=FLAG_LEFT;
            target_angle=2*M_PI-target_angle;
        }
    }
    else
    {
        target_angle=-target_angle;
        if(target_angle<=M_PI)
        {
            speed_flag=FLAG_LEFT;
        }
        else
        {
            speed_flag=FLAG_RIGHT;
            target_angle=2*M_PI-target_angle;
        }
    }
#ifdef debug_printf
    printf(" rad %.2f flag %d\n", target_angle, speed_flag);
#endif
    if(target_angle>(to_rad(ANGLE_TRESHOLD)))
    {
        //set_motors_speed_dir(ROTATION_SPEED,ROTATION_SPEED, speed_flag);
        while((target_angle-abs(me.angle))>to_rad(ANGLE_OVERFLOW))	//including inertion overturn ~23.3 degrees (speed~70)
        {
            set_motors_speed_dir(ROTATION_SPEED, ROTATION_SPEED, speed_flag);
            usleep(MOTOR_SLEEP);
        }
        stop_motors();
    }
}
Example #7
0
void linecheck(int32_t * u_fwd, int32_t * u_back, uint8_t * iterations, uint8_t moves)
{
	int32_t temp;
	if((*iterations) >= moves)
	{
		/*ADDED BY ERNIE*/
		if (drivestate == DRIVESTATE_FWD) {
			//rv_motors(25, 1);
		} else {
			(*u_fwd) = 0;
			(*u_back) = 0;
			stop_motors(0);	// Change state and stop motors
		}
		/*END ADDED BY ERNIE*/
		(*iterations) = 0;
	}
}
Example #8
0
//This is the thread that will run with high priority
void* realtimeMain(void* udata)
{
  struct timespec tick;
  int period = 1e+6; // 1 ms in nanoseconds

  while(!exiting)
  {
    cyclic_task(); // Send and receave from the motor controllers

    if(pthread_mutex_trylock(&mutex) == 0)
    {
      tar = tar_buffer;
      cur_buffer = cur;
      pthread_mutex_unlock(&mutex);
    }

    // Compute end of next period
    timespecInc(&tick, period);

    struct timespec before;
    clock_gettime(CLOCK_REALTIME, &before);
    if ((before.tv_sec + before.tv_nsec/1e9) > (tick.tv_sec + tick.tv_nsec/1e9))
    {
      // We overran, snap to next "period"
      tick.tv_sec = before.tv_sec;
      tick.tv_nsec = (before.tv_nsec / period) * period;
      timespecInc(&tick, period);

      misses++;
    }
    // Sleep until end of period
    clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &tick, NULL);

  }

  stop_motors();



  return 0;
}
int main(void)
{	
	init();
	BOOL motors_stopped = FALSE;
	
	send_welcome();
	        
    while (1)
    {	
		if (motors_stopped)
		{
			led_on ( STOP_LED );
			led_off ( GO_LED );
		} else
		{
			led_on( GO_LED );
			led_off( STOP_LED );
		}
		
		read_buttons();
		if (stop_button_pressed)
		{
			motors_stopped = TRUE;
			stop_motors();
		}
		if (prog_button_pressed)
		{
			motors_stopped = FALSE; 
			resume_motors();
		}

		encoder_timeslice();		
		limit_switch_timeslice();
		motor_timeslice_10ms();		
		serial_timeslice();		// handle incoming messages (if avail)

		watchdog_reset();
		//delay(one_second/10);
    }
    return (0);
}
void perform_effect(const int op)
{
	switch(op)
	{
		case MOTOR_1_TURN_R_OPTION:
			motor_1_turn_right();
		break;
		case MOTOR_1_TURN_L_OPTION:
			motor_1_turn_left();
		break;
		case MOTOR_2_TURN_R_OPTION:
			motor_2_turn_right();
		break;
		case MOTOR_2_TURN_L_OPTION:
			motor_2_turn_left();
		break;
		case MOTOR_3_TURN_R_OPTION:
			motor_3_turn_right();
		break;
		case MOTOR_3_TURN_L_OPTION:
			motor_3_turn_left();
		break;
		case MOTORS_1_2_3_TURN_R_OPTION:
			motors_1_2_3_turn_right();
		break;
		case MOTORS_1_2_3_TURN_L_OPTION:
			motors_1_2_3_turn_left();
		break;
		case STOP_MOTORS_OPTION:
			stop_motors();
		break;
		case EXIT_OPTION:
			printl("BYE...");
		break;
		default:
			printl("BAD INPUT, Try Again");
		break;
	}
}
Example #11
0
void isr_timer(void)
{
    if( qr.link_down )
    {
        unsigned char i;

        qr.current_mode = SAFE_MODE;
        stop_motors();
        qr.exit = 1;
        qr.flag_mode = 1;

        for(i=0; i < 5; i++, catnap(500))
            X32_LEDS = ALL_ON, catnap(500), X32_LEDS = ALL_OFF;

        #ifdef PERIPHERAL_DISPLAY
            X32_DISPLAY = 0xf1fa;
        #endif

        DISABLE_INTERRUPT(INTERRUPT_TIMER1);
    }

    qr.link_down = 1;
}
Example #12
0
/*******************************************************************
 * MAIN()
 *******************************************************************/
int
main(void)
{
	long lEEPROMRetStatus;
	uint16_t i=0;
	uint8_t halted_latch = 0;

	// Set the clocking to run at 80 MHz from the PLL.
	// (Well we were at 80MHz with SYSCTL_SYSDIV_2_5 but according to the errata you can't
	// write to FLASH at frequencies greater than 50MHz so I slowed it down. I supposed we
	// could slow the clock down when writing to FLASH but then we need to find out how long
	// it takes for the clock to stabilize. This is on at the bottom of my list of things to do
	// for now)
	SysCtlClockSet(SYSCTL_SYSDIV_4_5 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ | SYSCTL_OSC_MAIN);

	// Initialize the device pinout.
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOG);
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOH);
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOJ);

	// Enable processor interrupts.
	IntMasterEnable();

	// Setup the UART's
	my_uart_0_init(115200, (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE));
	// command_handler_init overwrites the baud rate. We still need to configure the pins though
	my_uart_1_init(38400, (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE));

	// Enable the command handler
	command_handler_init(); // We set the baud in here

	// Start the timers
	my_timer0_init();
	my_timer1_init();

	i2c_init();
	motor_init();
	qei_init();
	gyro_init();
	accel_init();
	led_init();
	//rc_radio_init();
	//setupBluetooth();

	// Initialize the EEPROM emulation region.
	lEEPROMRetStatus = SoftEEPROMInit(EEPROM_START_ADDR, EEPROM_END_ADDR, EEPROM_PAGE_SIZE);
	if(lEEPROMRetStatus != 0) UART0Send("EEprom ERROR!\n", 14);

#if 0
	// If ever we wanted to write some parameters to FLASH without the HMI
	// we could do it here.
	SoftEEPROMWriteDouble(kP_ID, 10.00);
	SoftEEPROMWriteDouble(kI_ID, 10.00);
	SoftEEPROMWriteDouble(kD_ID, 10.00);
	SoftEEPROMWriteDouble(ANG_ID, 0.0);
	SoftEEPROMWriteDouble(COMPC_ID, 0.99);
#endif

	kP = SoftEEPROMReadDouble(kP_ID);
	kI = SoftEEPROMReadDouble(kI_ID);
	kD = SoftEEPROMReadDouble(kD_ID);
	commanded_ang = zero_ang = SoftEEPROMReadDouble(ANG_ID);
	COMP_C = SoftEEPROMReadDouble(COMPC_ID);

	pid_init(kP, kI, kD, &pid_ang);
	motor_controller_init(20, 100, 10, &mot_left);
	motor_controller_init(20, 100, 10, &mot_right);


	//pid_init(0.0, 0.0, 0.0, &pid_pos_left);
	//pid_init(0.0, 0.0, 0.0, &pid_pos_right);

	//UART0Send("Hello World!\n", 13);

	// Tell the HMI what the initial parameters are.
	print_params(1);


	while(1)
	{
		delta_t = myTimerValueGet();
		myTimerZero();
		sum_delta_t += delta_t;

		// Read our sensors
		accel_get_xyz_cal(&accel_x, &accel_y, &accel_z, true);
		gyro_get_y_cal(&gyro_y, false);

		// Calculate the pitch angle with the accelerometer only
		R = sqrt(pow(accel_x, 2) + pow(accel_z, 2));
		accel_pitch_ang = (acos(accel_z / R)*(RAD_TO_DEG)) - 90.0 - zero_ang;
		//accel_pitch_ang = (double)((atan2(accel_x, -accel_z))*RAD_TO_DEG - 90.0);

		gyro_pitch_ang += (double)gyro_y*g_gyroScale*CONV_TO_SEC(delta_t);

		// Kalman filter
		//filtered_ang = kalman((double)accel_pitch_ang, ((double)gyro_y)*g_gyroScale, CONV_TO_SEC(delta_t));
		filtered_ang = (COMP_C*(filtered_ang+((double)gyro_y*g_gyroScale*CONV_TO_SEC(delta_t)))) + ((1.0-COMP_C)*(double)accel_pitch_ang);

		// Skip the rest of the process until the angle stabilizes
		if(i < 250) { i++; continue; }

		// Tell the HMI what's going on every 100ms
		if(sum_delta_t >= 1000)
		{
			print_update(1);
			print_debug(0);
			//print_control_surfaces(0);
			led_toggle();
			//print_angle();
			sum_delta_t = 0;
		}


		// See if the HMI has anything to say
		command_handler();
		//continue;

		// If we are leaning more than +/- FALL_ANG deg off center it's hopeless.
		// Turn off the motors in hopes of some damage control
		if( abs(filtered_ang) > FALL_ANG )
		{
			if(halted_latch) continue;
			stop_motors();
			halted_latch = 1;
			continue;
		}
		halted_latch = 0;

		motor_val = pid_controller(calc_commanded_angle(0), filtered_ang, delta_t, &pid_ang);
		motor_left = motor_right = motor_val;
		drive_motors(motor_left*left_mot_gain, motor_right*right_mot_gain);
	}
}
Example #13
0
int main(void)
{
	//Sväng inte
	turn = 0;
	
	//Initiera spi, pwm och display
	spi_init();
	pwm_init();
	init_display();
	update();
	
	claw_out();
	_delay_ms(500);
	claw_in();	
	
	//Aktivera global interrupts
	sei();
	
	//Initiera regulator
	clear_pid();	
	init_pid(80, -80);
	//update_k_values(40, 12, 22);
	update_k_values(40, 170, 20);
	
	// Pekare till aktuell position i bufferten
	tmp_sensor_buffer_p = 0x00;
	
	// Flagga som avgör huruvida vi är i början av meddelande	
	sensor_start = 1;
	
	// Anger aktuell längd av meddelandet				
	tmp_sensor_buffer_len = 0x00;
	
	//Initiera standardsträng på display		
	init_default_printf_string();
	clear_screen();
	update();
	
	
	while(1)
	{
		uint8_t has_comm_data, has_sensor_data, comm_data, sensor_data;
	
		do_spi(&has_comm_data, &has_sensor_data, &comm_data, &sensor_data);
		
		//Undersök och hantera meddelanden från slavarna
		if(has_comm_data) decode_comm(comm_data);
		if(has_sensor_data) decode_sensor(sensor_data);
		
		//Vid manuell sväng eller 180 grader måste make_turn anropas 		
		if(!autonomous || turning_180)
		{
			if(turn_dir) 
			{
				make_turn_flag = 1;
				make_turn(turn_dir);
				
				if(!make_turn_flag) 
				{
					turn_dir = 0;
					stop_motors();
				}				
			}
		}			
		
		//Kör regulatorn
		if (regulator_enable)
		{
			regulator(sensor_buffer[IR_RIGHT_FRONT] - sensor_buffer[IR_RIGHT_BACK], 
					  sensor_buffer[IR_LEFT_FRONT] - sensor_buffer[IR_LEFT_BACK], 
					  sensor_buffer[IR_RIGHT_FRONT] - sensor_buffer[IR_LEFT_FRONT], 
					  sensor_buffer[IR_RIGHT_BACK] - sensor_buffer[IR_LEFT_BACK]);
			regulator_enable = 0;
		}	
	}
}
int main(int argc, char* argv[])
{
    ros::init(argc, argv, "phidgets_motor_control_hc");
    ros::NodeHandle n;
    ros::NodeHandle nh("~");
    int serial_number = -1;
    nh.getParam("serial", serial_number);
    std::string name = "motorcontrol";
    nh.getParam("name", name);
    nh.getParam("x_forward", x_forward);
    nh.getParam("rotation", rotation_offset);
    std::string odometry_topic = "odom";
    nh.getParam("odometry", odometry_topic);
    double g = 0;
    const double min_g = 0.00001;
    nh.getParam("max_angular_error", g);
    if (g>min_g) max_angular_error = g;
    g=0;
    nh.getParam("max_velocity_error", g);
    if (g>min_g) max_velocity_error = g;
    g=0;
    nh.getParam("linear_deadband", g);
    if (g>min_g) linear_deadband = g;
    g=0;
    nh.getParam("angular_deadband", g);
    if (g>min_g) angular_deadband = g;
    g=0;
    nh.getParam("linear_proportional", g);
    if (g>min_g) linear_velocity_proportional = g;
    g=0;
    nh.getParam("linear_integral", g);
    if (g>min_g) linear_velocity_integral = g;
    g=0;
    nh.getParam("linear_derivative", g);
    if (g>min_g) linear_velocity_derivative = g;
    g=0;
    nh.getParam("angular_proportional", g);
    if (g>min_g) angular_velocity_proportional = g;
    g=0;
    nh.getParam("angular_integral", g);
    if (g>min_g) angular_velocity_integral = g;
    g=0;
    nh.getParam("angular_derivative", g);
    if (g>min_g) angular_velocity_derivative = g;
    g=0;
    nh.getParam("max_angular_velocity", g);
    if (g>min_g) max_angular_velocity = g;
    nh.getParam("invert_rotation", invert_rotation);
    nh.getParam("invert_forward", invert_forward);
    if (serial_number==-1) {
        nh.getParam("serial_number", serial_number);
    }

    g=0;
    nh.getParam("max_angular_accel", g);
    if (g>0) max_angular_accel = g;
    g=0;
    nh.getParam("max_linear_accel", g);
    if (g>0) max_linear_accel = g;

    std::string topic_path = "phidgets/";
    nh.getParam("topic_path", topic_path);
    int timeout_sec = 2;
    nh.getParam("timeout", timeout_sec);
    int v=0;
    nh.getParam("speed", v);
    if (v>0) speed = v;
    int frequency = 30;
    nh.getParam("frequency", frequency);

    ITerm[0]=0;
    ITerm[1]=0;

    if (attach(phid, serial_number)) {
        display_properties(phid);

        const int buffer_length = 100;
        std::string topic_name = topic_path + name;
        std::string service_name = name;
        if (serial_number > -1) {
            char ser[10];
            sprintf(ser,"%d", serial_number);
            topic_name += "/";
            topic_name += ser;
            service_name += "/";
            service_name += ser;
        }
        motors_pub =
            n.advertise<ros_phidgets_jade::motor_params>(topic_name,
                    buffer_length);

        // receive velocity commands
        ros::Subscriber command_velocity_sub =
            n.subscribe("cmd_vel", 1, velocityCommandCallback);

        // subscribe to odometry
        ros::Subscriber odometry_sub =
            n.subscribe(odometry_topic, 1, odometryCallback);

        initialised = true;
        ros::Rate loop_rate(frequency);

        while (ros::ok()) {
            ros::spinOnce();
            loop_rate.sleep();

            // SAFETY FEATURE
            // if a velocity command has not been received
            // for a period of time then stop the motors
            double time_since_last_command_sec =
                (ros::Time::now() -
                 last_velocity_command).toSec();
            if ((motors_active) &&
                    (time_since_last_command_sec > timeout_sec)) {
                stop_motors();
                ROS_WARN("No velocity command received - " \
                         "motors stopped");
            }
        }

        disconnect(phid);
    }
    return 0;
}
void update_field(){
    copy_objects();
    int current_x = (int)(game.coords[0].x * VPS_RATIO);
    int current_y = (int)(game.coords[0].y * VPS_RATIO);
    uint8_t has_encoder_moved = FALSE;
    /*if(get_time() > field_state.last_encoder_update + ENCODER_UPDATE_TIME){
        if(encoder_read(FREEWHEEL_ENCODER_PORT) != field_state.encoder_value){
            field_state.robot_stopped = TRUE;
            field_state.encoder_value = encoder_read(FREEWHEEL_ENCODER_PORT);
            field_state.
        }
        else{
            field_state.robot_stopped = TRUE;
        }

    }*/
    
    //printf("Current X: %d, Current Y: %d\n", current_x, current_y);
    float current_theta = (((float)game.coords[0].theta) * 180.0) / 2048;
    field_state.curr_loc_plus_delta.x = current_x; //+ get_delta(field_state.curr_loc).x;
    field_state.curr_loc_plus_delta.y = current_y; //+ get_delta(field_state.curr_loc).y;
    uint8_t sextant = get_current_sextant(field_state.curr_loc_plus_delta);
    uint8_t old_sextant = get_current_sextant(field_state.curr_loc);
    
    //printf("Current Distance: %f, Waypoint Distance: %f, Target Distance: %f, Distance Increment: %f\n", pythagorean(field_state.curr_loc_plus_delta.x, field_state.curr_loc_plus_delta.y), pythagorean(field_state.target_loc_waypoint.x, field_state.target_loc_waypoint.y), pythagorean(field_state.target_loc.x, field_state.target_loc.y), field_state.distance_increment);
    float dist_to_waypoint = pythagorean_loc(field_state.curr_loc_plus_delta, field_state.target_loc_waypoint);
    if(sextant != old_sextant ){//|| (get_angle_error_circle() > 90 && dist_to_waypoint < CIRCLE_DECELERATE_DISTANCE_SECOND){
        uint8_t target_sextant = get_current_sextant(field_state.target_loc);
        /*int direction;
        if((get_angle_error_circle() > 90 && dist_to_waypoint < CIRCLE_DECELERATE_DISTANCE_SECOND) && (sextant == old_sextant)){
            //we're about to spiral...let's not spiral
            direction = get_waypoint_direction(field_state.curr_loc_plus_delta, field_state.target_loc, gyro_get_degrees());
            if(get_sextant_difference(field_state.curr_loc_plus_delta, field_state.target_loc, direction) > 1){
                //we aren't at the target sextant yet, so set target waypoint to next waypoint
                float distance_increment;
                    switch(direction){
                    case COUNTER_CLOCKWISE:
                            if(target_sextant < sextant)
                                target_sextant += 6;
                            new_distance = bound_waypoint_distance(field_state.distance_increment, field_state.target_loc_waypoint);
                            field_state.target_loc_waypoint = get_scaled_loc_int_param(bisecting_points[(2*sextant+4)%12], bisecting_points[(2*sextant+5)%12], new_distance);
                            break;
                        case CLOCKWISE:
                            if(target_sextant > sextant)
                                target_sextant -= 6;
                            new_distance = bound_waypoint_distance(field_state.distance_increment, field_state.target_loc_waypoint);
                            field_state.target_loc_waypoint = get_scaled_loc_int_param(bisecting_points[mod_ui(2*sextant - 2, 12)], bisecting_points[mod_ui(2*sextant - 1, 12)], new_distance);
                            break;
                    }
                }

            }

        }*/
        //We have broken the plane, get next waypoint, or target if in same sextant
        int direction = get_waypoint_direction(field_state.curr_loc_plus_delta, field_state.target_loc, gyro_get_degrees());
        if(sextant != target_sextant){
            float distance_increment;
            if(sextant == mod_ui(old_sextant + direction, 6)){
                float new_distance;
                switch(direction){
                    case COUNTER_CLOCKWISE:
                        if(target_sextant < sextant)
                            target_sextant += 6;
                        new_distance = bound_waypoint_distance(field_state.distance_increment, field_state.target_loc_waypoint);
                        field_state.target_loc_waypoint = get_scaled_loc_int_param(bisecting_points[(2*sextant+2)%12], bisecting_points[(2*sextant+3)%12], new_distance);
                        break;
                    case CLOCKWISE:
                        if(target_sextant > sextant)
                            target_sextant -= 6;
                        new_distance = bound_waypoint_distance(field_state.distance_increment, field_state.target_loc_waypoint);
                        field_state.target_loc_waypoint = get_scaled_loc_int_param(bisecting_points[(2*sextant)%12], bisecting_points[(2*sextant + 1)%12], new_distance);
                        break;
                }
            }
            field_state.target_loc_plane = get_scaled_loc(field_state.target_loc_waypoint, OUTER_HEX_APATHEM_DIST);

        }
        else{
            field_state.target_loc_waypoint = field_state.target_loc;
        }
        field_state.curr_loc = field_state.curr_loc_plus_delta;
        encoder_reset(LEFT_ENCODER_PORT);
        encoder_reset(RIGHT_ENCODER_PORT);
        
    }
    if((field_state.substage == TERRITORY_APPROACH_SUBSTAGE) && current_vel > 0){
        if(get_time() - field_state.stored_time > TERRITORY_TIMEOUT_TIME || game.coords[0].score != field_state.score){
            if(!(field_state.we_want_to_dump)){
                field_state.substage = DRIVE_SUBSTAGE;
                //SET MOTORS TO LEVER ARC THINGY
                target_vel = 96;
                current_vel = 96;
                set_spinners(0);
                //accelerate_time = CIRCLE_ACCELERATE_TIME;
                //decelerate_distance = CIRCLE_DECELERATE_DISTANCE;
                //KP_CIRCLE = 1.5;
                //set_motors(55, 120);
                field_state.stored_time = get_time();
                field_state.drive_direction = FORWARD;
                field_state.pid_enabled = TRUE;
                field_state.circle_PID.enabled = true;
                servo_set_pos(1, SERVO_UP);
                set_new_destination(field_state.curr_loc_plus_delta, get_lever_pivot_point_loc(sextant));
            }
            else{
                retreat_from_territory();
            }
        }
        if(get_time() - field_state.start_time > THINK_ABOUT_DUMPING_TIME){
            field_state.we_want_to_dump = TRUE;
        }
    }
    if((field_state.substage == LEVER_APPROACH_SUBSTAGE) && current_vel > 0){
        if(get_time() - field_state.stored_time > LEVER_APPROACH_TIME){
            field_state.substage = LEVER_SUBSTAGE;
            //SET MOTORS TO LEVER ARC THINGY
            //target_vel = 64;
            //current_vel = 64;
            //set_spinners(0);
            //accelerate_time = CIRCLE_ACCELERATE_TIME;
            //decelerate_distance = CIRCLE_DECELERATE_DISTANCE;
            //KP_CIRCLE = 1.5;
            //set_motors(55, 120);
            stop_motors();
            field_state.stored_time = get_time();
            field_state.target_loc_waypoint = field_state.curr_loc_plus_delta;
            field_state.target_loc = field_state.curr_loc_plus_delta;
            field_state.pid_enabled = TRUE;
            field_state.stored_time = get_time();
            int score_temp = field_state.score;
            servo_set_pos(1, SERVO_DOWN);
            pause(CLICKY_CLICKY_TIME + 100);
            while(1){
                copy_objects();
                if(get_time() - field_state.start_time > THINK_ABOUT_DUMPING_TIME){
                    field_state.we_want_to_dump = TRUE;
                }
                if(game.coords[0].score != score_temp){
                    score_temp += 40;
                    field_state.balls_held += 1;
                }
                if(game.coords[0].score == field_state.score + 200 || field_state.stored_time + LEVER_TIMEOUT_TIME < get_time() ){
                    if(!field_state.we_want_to_dump){
                        pause(50);
                        field_state.substage = DRIVE_SUBSTAGE;
                        target_vel = TARGET_CIRCLE_VEL;
                        current_vel = 0;
                        accelerate_time = CIRCLE_ACCELERATE_TIME;
                        decelerate_distance = CIRCLE_DECELERATE_DISTANCE_FIRST;
                        KP_CIRCLE = KP_DRIVE;
                        field_state.stored_time = get_time();
                        field_state.start_drive_time = get_time();
                        field_state.drive_direction = BACKWARD;
                        field_state.circle_PID.enabled = true;
                        field_state.pid_enabled = true;
                        uint8_t temp_sextant = sextant;
                        if(temp_sextant == 0)
                            temp_sextant += 6;
                        set_new_destination(field_state.curr_loc_plus_delta, get_territory_pivot_point_loc(get_target_territory(field_state.curr_loc_plus_delta)));
                        break;
                    }
                    else{
                        pause(50);
                        get_your_ass_to_a_toilet();
                        break;
                    }
                }
                servo_set_pos(1, SERVO_MIDDLE);
                pause(CLICKY_CLICKY_TIME);
                servo_set_pos(1, SERVO_DOWN);
                pause(CLICKY_CLICKY_TIME);
            }
        }
    }
    /*if(field_state.substage == TRANSITION_SUBSTAGE){
        if(get_time() - field_state.stored_time > TRANSITION_TIME){
            field_state.substage = LEVER_SUBSTAGE;
            stop_motors();
            field_state.stored_time = get_time();
            field_state.target_loc_waypoint = field_state.curr_loc_plus_delta;
            field_state.target_loc = field_state.curr_loc_plus_delta;
            field_state.pid_enabled = TRUE;
            field_state.circle_PID.enabled = true;
            while(1){
                copy_objects();
                if(game.coords[0].score == field_state.score + 200 || field_state.stored_time + LEVER_TIMEOUT_TIME < get_time() ){
                    field_state.substage = DRIVE_SUBSTAGE;
                    target_vel = 128;
                    current_vel = 0;
                    accelerate_time = CIRCLE_ACCELERATE_TIME;
                    decelerate_distance = CIRCLE_DECELERATE_DISTANCE_FIRST;
                    KP_CIRCLE = KP_DRIVE;
                    field_state.stored_time = get_time();
                    field_state.start_drive_time = get_time();
                    field_state.drive_direction = BACKWARD;
                    field_state.circle_PID.enabled = true;
                    uint8_t temp_sextant = sextant;
                    if(temp_sextant == 0)
                        temp_sextant += 6;
                    set_new_destination(field_state.curr_loc_plus_delta, get_territory_pivot_point_loc((temp_sextant - 1)%6));
                    break;
                }
                servo_set_pos(1, SERVO_DOWN);
                pause(CLICKY_CLICKY_TIME);
                servo_set_pos(1, SERVO_MIDDLE);
                pause(CLICKY_CLICKY_TIME);
            }
        }
    }*/
    /*else if((field_state.substage == LEVER_APPROACH_SUBSTAGE) && current_vel > 0){
        if(get_time() - field_state.stored_time > TERRITORY_TIMEOUT_TIME || game.coords[0].score != field_state.score){
            field_state.substage = LEVER_APPROACH_SUBSTAGE;
            target_vel = 64;
            current_vel = 0;
            set_spinners(0);
            //accelerate_time = CIRCLE_ACCELERATE_TIME;
            //decelerate_distance = CIRCLE_DECELERATE_DISTANCE;
            //KP_CIRCLE = 1.5;
            //field_state.start_drive_time = get_time();
            field_state.drive_direction = FORWARD;
            set_new_destination(field_state.curr_loc_plus_delta, get_lever_robot_loc((sextant)%6));
            
        }
    }*/
    
    if(get_time() - field_state.start_time > THINK_ABOUT_DUMPING_TIME){
        if(field_state.substage == DRIVE_SUBSTAGE){
            if(!field_state.we_want_to_dump)
                get_your_ass_to_a_toilet();
        }
        field_state.we_want_to_dump = TRUE;
    }
    
    int acceptable_error = get_acceptable_error(field_state.substage);
    float dist_to_target = pythagorean(field_state.target_loc.x - field_state.curr_loc_plus_delta.x, field_state.target_loc.y - field_state.curr_loc_plus_delta.y);
    
    if(field_state.target_loc.x == field_state.target_loc_waypoint.x && field_state.target_loc.y == field_state.target_loc_waypoint.y){
        if(dist_to_target < acceptable_error){
            gyro_set_degrees(current_theta);
            encoder_reset(LEFT_ENCODER_PORT);
            encoder_reset(RIGHT_ENCODER_PORT);
            /*if(field_state.substage == TERRITORY_APPROACH_SUBSTAGE){
                field_state.substage = TERRITORY_SUBSTAGE;
                stop_motors();
                set_spinners(0);
                current_vel = 0;
                target_vel = 0;
            }
            if(field_state.substage == LEVER_APPROACH_SUBSTAGE){
                field_state.substage = LEVER_SUBSTAGE;
                stop_motors();
                current_vel = 0;
                target_vel = 0;
            }*/
            if(field_state.substage == DRIVE_SUBSTAGE || field_state.substage == TERRITORY_RETREAT_SUBSTAGE || field_state.substage == LEVER_RETREAT_SUBSTAGE){
                if(field_state.stage == FIRST_STAGE)
                    field_state.stage = SECOND_STAGE;
                if(field_state.target_loc.x == get_territory_pivot_point_loc(sextant).x && field_state.target_loc.y == get_territory_pivot_point_loc(sextant).y){
                    if(field_state.substage != TERRITORY_RETREAT_SUBSTAGE){
                        set_new_destination(field_state.curr_loc_plus_delta, get_territory_robot_loc(sextant));
                        set_spinners( 229 * field_state.color);
                        target_vel = 64;
                        current_vel = 0;
                        field_state.start_drive_time = get_time();
                        accelerate_time = WALL_ACCELERATE_TIME;
                        decelerate_distance = (int)(WALL_DECELERATE_DISTANCE);
                        field_state.substage = TERRITORY_APPROACH_SUBSTAGE;
                        KP_CIRCLE = KP_APPROACH;
                        field_state.drive_direction = BACKWARD;
                    }
                    else{
                        field_state.substage = PIVOT_SUBSTAGE;
                        uint8_t dump_sextant = pick_dump_sextant();
                        Location dump_loc = get_dump_location_robot(dump_sextant);
                        set_new_destination(field_state.curr_loc_plus_delta, dump_loc);
                        current_vel = 0;
                    }
                }
                else if(field_state.target_loc.x == get_lever_pivot_point_loc(sextant).x && field_state.target_loc.y == get_lever_pivot_point_loc(sextant).y){
                    if(field_state.substage != LEVER_RETREAT_SUBSTAGE){
                        target_vel = 64;
                        current_vel = 0;
                        set_new_destination(field_state.curr_loc_plus_delta, get_lever_robot_loc(sextant));
                        decelerate_distance = (int)(WALL_DECELERATE_DISTANCE);
                        field_state.start_drive_time = get_time();
                        accelerate_time = WALL_ACCELERATE_TIME;
                        KP_CIRCLE = KP_APPROACH;
                        field_state.drive_direction = FORWARD;
                        field_state.substage = LEVER_APPROACH_SUBSTAGE;
                    }
                    else{
                        field_state.substage = PIVOT_SUBSTAGE;
                        //WE WILL PROBABLY NEVER USE LEVER_RETREAT_SUBSTAGE...
                    }
                }
                else if(field_state.target_loc.x == get_dump_location_robot(sextant).x && field_state.target_loc.y == get_dump_location_robot(sextant).y){
                    field_state.substage = DUMPING_SUBSTAGE;
                    set_new_destination(field_state.curr_loc_plus_delta, get_dump_location(sextant));
                    current_vel = 0;
                    target_vel = 64;
                    field_state.start_dump_time = get_time();
                    decelerate_distance = 0;
                    KP_CIRCLE = KP_APPROACH;
                    field_state.drive_direction = BACKWARD;
                }
            }
        }
    }
    
    run_pivot_subroutine();
    
    if(field_state.substage == DUMPING_SUBSTAGE){
        if(get_time() - field_state.start_dump_time > 4000)
           servo_set_pos(0, 150);
        if(get_time() - field_state.start_dump_time > 4000 + time_during_dump){
            servo_set_pos(0, 300);
        }
    }
    if(current_x != field_state.curr_loc.x || current_y != field_state.curr_loc.y || current_theta != field_state.curr_angle){
        field_state.update_time = get_time();
        field_state.curr_loc.x = current_x;
        field_state.curr_loc.y = current_y;
        field_state.curr_angle = current_theta;
        //printf("Lag: %lu, CX: %d, CY: %d, OX: %d, OY: %d, TX: %d, TY: %d, TWX: %d, TWY: %d, CA: %.2f, G: %.3f, LE: %d, RE: %d\n", get_time() - field_state.stored_time, current_x, current_y, field_state.curr_loc.x, field_state.curr_loc.y, field_state.target_loc.x, field_state.target_loc.y, field_state.target_loc_waypoint.x, field_state.target_loc_waypoint.y, field_state.curr_angle, gyro_get_degrees(), encoder_read(LEFT_ENCODER_PORT), encoder_read(RIGHT_ENCODER_PORT));
        //field_state.stored_time = get_time();
        encoder_reset(LEFT_ENCODER_PORT);
        encoder_reset(RIGHT_ENCODER_PORT);
        if(field_state.substage == DRIVE_SUBSTAGE)
            gyro_set_degrees(current_theta);
        
    }
    
    field_state.curr_time = get_time();
    
    //***TIMEOUTS***
    /*if(field_state.curr_time - field_state.update_time >= DRIVE_TIMEOUT_TIME && !is_decelerating() && field_state.substage == DRIVE_SUBSTAGE && dist_to_target < acceptable_error){
        //We hit a wall...or another robot, but we haven't coded robot-ramming timeouts yet...
        float distance = pythagorean(field_state.curr_loc_plus_delta.x, field_state.curr_loc_plus_delta.y);
        if(fabs(distance - get_min_distance_loc_param(field_state.curr_loc)) < fabs(distance - get_max_distance_loc_param(field_state.curr_loc))){
            //We hit the inner hex
            
        }
    }*/
    
    field_state.score = game.coords[0].score;

}
ErrorID_t acceleration_mode(cwiid_wiimote_t *wiimote,
		volatile WiimoteStatusDataType *wiimote_status)
{
	typedef enum WiimoteAccelStateType
	{
		WIIMOTE_ACCEL_WAIT_FOR_START,
		WIIMOTE_ACCEL_READ_CAL_DATA,
		WIIMOTE_ACCEL_READ_DATA,
		WIIMOTE_ACCEL_WAIT_FOR_EXIT,
		WIIMOTE_ACCEL_EXIT,
	} WiimoteAccelStateType;

	const uint8_t RETRY_VALUE = 2;
	uint8_t retry_count = 0;
	ErrorID_t error_flag = ERR_NONE;

	WiimoteAccelStateType state = WIIMOTE_ACCEL_WAIT_FOR_START;

	debug_print("Entering acceleration mode...\n");
	write_status_led(STATUS_LED_OFF, 0);

	for (;;)
	{
		switch (state)
		{
		case WIIMOTE_ACCEL_WAIT_FOR_START:
			if (0 > wait_for_wiimotedata(wiimote_status, INFINITE_TIMEOUT))
			{
				debug_print("No start signal received\n");
				error_flag = WII_ERROR_DATA_TIMEOUT;
				state = WIIMOTE_ACCEL_EXIT;
			}
			else if (0 == (wiimote_status->button_data & CWIID_BTN_A))
			{
				state = WIIMOTE_ACCEL_READ_CAL_DATA;
			}
			break;

		case WIIMOTE_ACCEL_READ_CAL_DATA:
			error_flag = WII_ERROR_ACCEL_CAL;
			do
			{
				if (0
						== cwiid_get_acc_cal(
								wiimote,
								CWIID_EXT_NONE,
								(struct acc_cal *) &wiimote_status->accel_cal_data))
				{
					error_flag = ERR_NONE;
					break;
				}
			} while (retry_count++ < RETRY_VALUE);

			if (error_flag != ERR_NONE)
			{
				debug_print("Cannot read cal data\n");
				return error_flag;
			}

			if (0 > cwiid_set_rpt_mode(wiimote, CWIID_RPT_ACC | CWIID_RPT_BTN))
			{
				debug_print("Cannot set report mode to ACCEL\n");
				return false;
			}

			set_lcd(0, "Accel Mode...");
			set_lcd(1, "P = %4d R = %4d", 0, 0);
			state = WIIMOTE_ACCEL_READ_DATA;
			break;

		case WIIMOTE_ACCEL_READ_DATA:
			if (0 > wait_for_wiimotedata(wiimote_status, INFINITE_TIMEOUT))
			{
				debug_print("@%u: WII_ERROR_DATA_TIMEOUT\n", get_tick_count());
				error_flag = WII_ERROR_DATA_TIMEOUT;
				state = WIIMOTE_ACCEL_EXIT;
			}
			else
			{
				if (wiimote_status->button_data & CWIID_BTN_A)
				{
					state = WIIMOTE_ACCEL_WAIT_FOR_EXIT;
				}
				else
				{
					error_flag = computer_motor_levels_accel(wiimote_status);
					set_lcd(1, "P = %4d R = %4d",
							wiimote_status->accel_computed_data.pitch / 100,
							wiimote_status->accel_computed_data.roll / 100);

					if (ERR_EXEC == error_flag)
						cwiid_set_rumble(wiimote, true);
					else
					{
						cwiid_set_rumble(wiimote, false);
						if (error_flag < 0)
						{
							debug_print("@%u: CONTROL CAR COMM ERROR: %d\n",
									get_tick_count(), error_flag);
							state = WIIMOTE_ACCEL_EXIT;
						}
					}

				}
			}
			break;

		case WIIMOTE_ACCEL_WAIT_FOR_EXIT:
			stop_motors();

			if (0 < wait_for_wiimotedata(wiimote_status, INFINITE_TIMEOUT))
			{
				error_flag = WII_ERROR_DATA_TIMEOUT;
				state = WIIMOTE_ACCEL_EXIT;
			}
			else if (0 == (wiimote_status->button_data & CWIID_BTN_A))
			{
				state = WIIMOTE_ACCEL_EXIT;
			}
			break;
		case WIIMOTE_ACCEL_EXIT:
			debug_print("Exiting acceleration mode.\n\n");
			return error_flag;
		}
	}
	return ERR_NONE;
}
Example #17
0
void move()
{
  int i;

  /*variable to use in figuring out the "best" option*/
  int max_q_score = 0;

  /*what do we do next? store it here*/
  /*we init to -1 as an error*/
  int next_movement = -1;

  /*Where we started.*/
  /*We don't use ROTATION_2 all the way through in case it changes.*/
  int initial_angle = norm_rotation(ROTATION_2);

  /*Where we ended up.*/
  int new_angle;

  /*Show the current angle*/
  cputc_native_user(CHAR_A, CHAR_N, CHAR_G, CHAR_L);  // ANGL
  msleep(200);
  lcd_int(initial_angle);
  msleep(500);
  
  /*
   * Most of the time, we do the "correct" thing
   * by finding the best q_score of our possible options.
   * On the off chance that norm_random() is low (or EPSILON is high ;)
   * we then "explore" by choosing a random movement.
   */

  if(norm_random() > EPSILON_CURRENT)
    {
      /*We are doing what the table tells us to.*/
      cputc_native_user(CHAR_r, CHAR_e, CHAR_a, CHAR_l);  // real
      msleep(500);

      for(i=0; i<MOVEMENTS; i++)
  {
    if(q_score[initial_angle][i] > max_q_score)
      {
        max_q_score = q_score[initial_angle][i];
        next_movement = i;
      }
  }
    }
  else
    {
      double temp;
      /*We are just picking something at random.*/
      cputc_native_user(CHAR_r, CHAR_a, CHAR_n, CHAR_d);  // rand
      msleep(500);

      /*pick one. Any one.*/
      
      temp = norm_random();
      next_movement = temp*MOVEMENTS;   

      /*show what we do next*/
      lcd_int(next_movement);
      sleep(1);
    }
  
  /*what happens if next_movement never gets changed?*/
  /*we'd hate to do HARD_LEFT over and over again*/
  /*so we choose randomly*/

  if(-1==next_movement)
    {
      double temp;
      temp = norm_random();
      next_movement = temp*MOVEMENTS;
    }

  /*having chosen a movement, lets do it*/
  switch(next_movement)
    {
    case HARD_LEFT:
      cputc_native_user(CHAR_H, CHAR_L, 0, 0);  // HL
      hard_left();
      break;
    case SOFT_LEFT:
      cputc_native_user(CHAR_S, CHAR_L, 0, 0);  // SL
      soft_left();
      break;
    case FORWARD:
      cputc_native_user(CHAR_F, CHAR_W, CHAR_W, CHAR_D); // FWD
      go_forward();
      break;
    case SOFT_RIGHT:
      cputc_native_user(CHAR_S, CHAR_R, 0, 0);  // SR
      soft_right();
      break;
    case HARD_RIGHT:
      cputc_native_user(CHAR_H, CHAR_R, 0, 0);  // HR
      hard_right();
      break;
    case REVERSE:
      cputc_native_user(CHAR_R, CHAR_E, CHAR_V, 0);  // REV
      go_back();
      break;
    default:
      /*this is an error and should never be reached*/
      cputc_native_user(CHAR_E, CHAR_R, CHAR_R, 0);  // ERR
      stop_motors();
      sleep(1);
      break;
    }

  /*Once we've started, we'd better stop*/
  stop_motors();

  /*Allows us to read direction*/
  msleep(500);

  /*This is here just to make the next function cleaner*/
  new_angle = norm_rotation(ROTATION_2);

  /*Where are we now?*/
  cputc_native_user(CHAR_N, CHAR_E, CHAR_W, CHAR_W);  // NEW
  msleep(200);
  lcd_int(new_angle);
  msleep(500);
  
  /*
   * Since we know that "next_movement" took us from "initial_angle"
   * to new_angle (ROTATION_2), we store that increased probability.
   */
  
  steering_results[initial_angle][next_movement][new_angle] += ALPHA;
  
  /*here we re-norm so that the sum of the probabilities is still 1*/
  for(i=0; i<ANGLES; i++)
    {
      steering_results[initial_angle][next_movement][i] /= (1+ALPHA);
    }  
  
  /*The last thing we do is reduce Epsilon*/
  if(EPSILON_CURRENT > EPSILON_MIN)
    {
      EPSILON_CURRENT-=EPSILON_DECAY;
    }

}
Example #18
0
//===============
void go_forward()
{
    float angle_diff;
    uchar lspeed, rspeed, speed_flag, current_speed=0;
#ifdef debug_printf
    printf("MOV: %f\n",target_distance);
#endif
    if(target_distance>=0)
    {
        speed_flag=FLAG_FORWARD;
    }
    else
    {
        target_distance=-target_distance;
        speed_flag=FLAG_BACKWARD;
    }
    if(target_distance>INERTION)
    {
        while(moving_allowed&&(me.dist_from_start<(target_distance-INERTION)))
        {
            //acceleration
            if(current_speed<input_speed)
            {
                current_speed += ACCELERATION;
                if(current_speed>input_speed)
                    current_speed = input_speed;
                lspeed=rspeed=current_speed;
            }
            else
            {
                lspeed=rspeed=input_speed;
                // speed-trajectory correction
                angle_diff = target_angle-me.angle;
                if(angle_diff>to_rad(ANGLE_DIFF))
                {
                    if(speed_flag==FLAG_FORWARD)
                    {
                        lspeed += 5;  //lspeed += (2*ANGLE_CORRECTION*angle_diff)/M_PI;
                        rspeed -= 15; //rspeed -= (2*ANGLE_CORRECTION*angle_diff)/M_PI;
                    }
                    if(speed_flag==FLAG_BACKWARD)
                    {
                        rspeed += 5;
                        lspeed -= 15;
                    }
                }
                if(angle_diff<-to_rad(ANGLE_DIFF))
                {
                    if(speed_flag==FLAG_FORWARD)
                    {
                        rspeed += 5;  //rspeed += (2*ANGLE_CORRECTION*angle_diff)/M_PI;
                        lspeed -= 15; //lspeed -= (2*ANGLE_CORRECTION*angle_diff)/M_PI;
                    }
                    if(speed_flag==FLAG_BACKWARD)
                    {
                        lspeed += 5;
                        rspeed -= 15;
                    }

                }
            }
            set_motors_speed_dir(lspeed, rspeed, speed_flag);
            usleep(MOTOR_SLEEP);
        }
        // decceleration
        while(moving_allowed&&(current_speed>0))
        {
            current_speed -= ACCELERATION<<1;
            if(current_speed<0)
                current_speed = 0;
            lspeed = rspeed = current_speed;
        }
        stop_motors();
    }
}
/*!
 @brief Determines motor parameters from IR data.
 */
ErrorID_t infrared_mode(cwiid_wiimote_t *wiimote,
		volatile WiimoteStatusDataType *wiimote_status)
{

	typedef enum WiimoteInfraredStateType
	{
		WIIMOTE_INFRARED_WAIT_FOR_START,
		WIIMOTE_INFRARED_ENABLE,
		WIIMOTE_INFRARED_READ_DATA,
		WIIMOTE_INFRARED_WAIT_FOR_EXIT,
		WIIMOTE_INFRARED_EXIT,
	} WiimoteInfraredStateType;

	ErrorID_t error_flag = ERR_NONE;

	bool last_valid = false;
	bool valid_points = false;

	WiimoteInfraredStateType state = WIIMOTE_INFRARED_WAIT_FOR_START;

	write_status_led(STATUS_LED_OFF, 0);

	for (;;)
	{
		switch (state)
		{
		case WIIMOTE_INFRARED_WAIT_FOR_START:
			if (0 < wait_for_wiimotedata(wiimote_status, 500))
			{
				error_flag = WII_ERROR_DATA_TIMEOUT;
				state = WIIMOTE_INFRARED_EXIT;
			}
			else if (0 == (wiimote_status->button_data & CWIID_BTN_B))
			{
				state = WIIMOTE_INFRARED_ENABLE;
			}
			break;

		case WIIMOTE_INFRARED_ENABLE:
			set_ir_led(STATUS_LED_ON);

			debug_print("Setting IR Report\n");

			if (0 < cwiid_set_rpt_mode(wiimote, CWIID_RPT_IR | CWIID_RPT_BTN))
			{
				debug_print("Cannot set report mode to IR\n");
				return false;
			}

			set_lcd(0, "Infrared Mode");
			set_lcd(1, "Point wiimote at car");

			write_status_led(STATUS_LED_ON, 0);

			state = WIIMOTE_INFRARED_READ_DATA;
			break;

		case WIIMOTE_INFRARED_READ_DATA:
			if (0 < wait_for_wiimotedata(wiimote_status, 500))
			{
				error_flag = WII_ERROR_DATA_TIMEOUT;
				state = WIIMOTE_INFRARED_EXIT;
			}
			else if (wiimote_status->button_data & CWIID_BTN_B)
			{
				state = WIIMOTE_INFRARED_WAIT_FOR_EXIT;
			}
			else
			{
				error_flag = WiiComputeMotorLevelsInfrared(wiimote_status,
						&valid_points);
				if (valid_points != last_valid)
				{
					write_status_led(
							valid_points ? STATUS_LED_OFF : STATUS_LED_ON, 0);
					set_lcd(
							1,
							valid_points ?
									"LED's seen" : "Point wiimote at car");
				}

				last_valid = valid_points;
				if (ERR_EXEC == error_flag)
					cwiid_set_rumble(wiimote, true);
				else
				{
					cwiid_set_rumble(wiimote, false);
					if (error_flag < 0)
						state = WIIMOTE_INFRARED_EXIT;
				}
			}
			break;

		case WIIMOTE_INFRARED_WAIT_FOR_EXIT:
			if (0 < wait_for_wiimotedata(wiimote_status, 500))
			{
				state = WIIMOTE_INFRARED_EXIT;
			}
			else if (0 == (wiimote_status->button_data & CWIID_BTN_B))
			{
				state = WIIMOTE_INFRARED_EXIT;
			}
			break;
		case WIIMOTE_INFRARED_EXIT:
			stop_motors();
			write_status_led(STATUS_LED_OFF, 0);
			set_ir_led(false);
			return error_flag;
			break;

			break;
		}
	}
	return true;
}