Exemple #1
0
int main(int argc, char *argv[])
{
    motor_init();

	bot_stop();

	// Move forward at 50% speed for 2 seconds
	bot_forward(pwm_speed(50));
	sleep(2);

	// Spin around a bit, woohoo!
	bot_spin(pwm_speed(40), SPIN_DIRECTION_LEFT);
	sleep(1);
	bot_spin(pwm_speed(40), SPIN_DIRECTION_RIGHT);
	sleep(1);

	bot_stop();

	return 0;
}
Exemple #2
0
void bot_StartStop(){
     if(ON){
		 lcd_clear();
		 print_string(50,30,"stop");
		 bot_stop();
		 _delay_ms(1000);
		 lcd_clear();
		 ON=0;
	 }
	  else if(!ON){
		 lcd_clear();
		 print_string(50,30,"start");
		 _delay_ms(1500);     //will move forward for minimum 500 ms till told to stop
		 bot_forward();
		 lcd_clear();
		 ON=1;
	 }
}
Exemple #3
0
void eye_control(){
    while(1){
		 if(buttonsPressed & BUTTON_S2){   //D3 to disable eye control
			 bot_stop();
			 buttonsPressed=0;
			 lcd_clear();
			 print_string(40,30,"Disabled!!");
			 _delay_ms(3000);
			 lcd_clear();
			 break;
		 }

        small_blink=0,big_blink=0,ON=0,menu_counter=0;
		 short toggle=1;
		 input = adc_read();

         highlight_and_print_string(0,8,"1.Waiting...");
         _delay_ms(100);
		 // lcd_clear();

		 if(input > AdcThreshold || input==AdcThreshold){
		        check_blink();
		 }

		 if(big_blink){
		     _delay_ms(1000);
			 while(1){
				 if(buttonsPressed & BUTTON_S2){   //D3 to disable eye control
					 bot_stop();
					 /*lcd_clear();
					 print_string(24,30,"Disabled!!");
					 _delay_ms(1000);
					 lcd_clear();*/
					 break;
				 }
				 small_blink=0,big_blink=0;
				 input = adc_read();
				 if(input > AdcThreshold){
					 check_blink();
				 }
				 if(small_blink && !ON){
					 menu_counter++;
					 toggle=1;
					 if(menu_counter==5) menu_counter=0;

				 }


				else if(big_blink){
						//lcd_clear();
						if(ON){
							   ON=0;
							   bot_stop();
							   _delay_ms(1000);
							   toggle=1;
						}
						else if(menu_counter==0){
						       _delay_ms(1000);
							   break;
						}
						else if(menu_counter==1){
							   highlight_and_print_string(0,16,"2.Left...");
							   _delay_ms(1000);
							   bot_left();
							   ON=1;
						}
						else if(menu_counter==2){
							   highlight_and_print_string(0,24,"3.Right...");
							   _delay_ms(1000);
							   bot_right();
							   ON=1;
						}
						else if(menu_counter==3){
						    	highlight_and_print_string(0,32,"4.Forward...");
							   _delay_ms(1000);
							   bot_forward();
							   ON=1;
						}
						else if(menu_counter==4){
						    	highlight_and_print_string(0,40,"5.Backward...");
							   _delay_ms(1000);
							   bot_backward();
							   ON=1;
						}


				}


				if(!ON && toggle){
					 toggle=0;
					 //lcd_clear();
		             print_string(0,0,"===Eye Control===");
		             print_string(0,8,"1.Wait      ");
		        	 print_string(0,16,"2.Left   ");
		        	 print_string(0,24,"3.Right   ");
		             print_string(0,32,"4.Forward   ");
		        	 print_string(0,40,"5.Backward   ");
		        	 print_string(0,56,"*S2=ESC*");

					 switch(menu_counter){
					 case 0:
			              highlight_and_print_string(0,8,"1.Wait      ");
						 _delay_ms(100);
						 break;
					 case 1:
						  highlight_and_print_string(0,16,"2.Left   ");
						 _delay_ms(100);
						 break;
					 case 2:
						 highlight_and_print_string(0,24,"3.Right   ");
						 _delay_ms(100);
						 break;
					 case 3:
						 highlight_and_print_string(0,32,"4.Forward   ");
						 _delay_ms(100);
						 break;
					 case 4:
						 highlight_and_print_string(0,40,"5.Backward   ");
						 _delay_ms(100);
						 break;
				   default:
						 break;
				  }
				}
			}
		}


	 }
}
Exemple #4
0
/**
 * Controller::goToPosition
 *
 * @param double x					desired waypoint x co-ord
 * @param double y					desired waypoing y co-ord
 * @param double fPosXStated		believed current x co-ord
 * @param double fPosYStated		believed current y co-ord
 *
 * @return void
 */
void Controller::goToPosition(double x, double y, double fPosXStated, double fPosYStated)
{
	double  		fTargetVectorMagnitude;             	// current distance between where we think we are and the waypoint
	double  		fTargetVectorMagnitudeLast = 0;			// last distance between where we think we were and the waypoint
	double  		fTargetVectorMagnitudeInitial = 0;		// initial distance between where we think we are and the waypoint
	double			fTargetVectorMagnitudeAtStartOfDrift;	// if we begin to get further from the target (rather than closer, perhaps due to a turning circle) what was our distance to the target when this started?
	unsigned int  	nConsecutiveIncreasingDistance = 0;		// number of times the distance has increased rather than decrease (used to stop out of controlness)
	bool			bApproachingTarget = false;				// once we start approaching the target don't forget it

	double       	fVelocityLeft = 0, fVelocityRight = 0;	// current velocity of left and right wheels

	Led    			ledHealth(1), ledProximity(3);

	ledHealth.off();
	ledProximity.off();

	// Reset the distance counters that are used in the PID loop, they are relative to our last (this) waypoint
	resetDistance();

	_logger->notice("goToPosition: --- START ---\nGoing to position (%.2f, %.2f) from current position (%.2f, %.2f) and heading [%.2f] ...", x, y, _currentPose.x, _currentPose.y, _currentPose.heading);

	_fPosXRef = x;
	_fPosYRef = y;

	// We need to keep our heading as close to this reference heading as possible to reach the waypoint
	_fHeadingRef = getHeading(_fPosXRef, _fPosYRef, _currentPose.x, _currentPose.y, _currentPose.heading);
//	_fHeadingRef = getHeading(_fPosXRef, _fPosYRef, fPosXStated, fPosYStated, _fHeadingCurrent);

	_logger->notice("goToPosition: new heading required is [%.2f]", _fHeadingRef);

	// Start (and reset) the odometry thread
	_odo->reset();

	int          	iteration = 0;
	bool          	bFirstIteration = true;

   	struct timeval 	tvNow, tvLast;
   	int           	nsec;
   	unsigned long 	delayms, totaldelayms = 0;	// time since last iteration and total time in this waypoint

   	gettimeofday(&tvLast, NULL);

	while (true)
    {
		/**
		 * Recalculate our reference heading every now and again as our current position changes.
		 */
		if (iteration % 10 == 0)
		{
			_logger->notice("goToPosition: recalculating heading based on current position...");
			_fHeadingRef = getHeading(_fPosXRef, _fPosYRef, _currentPose.x, _currentPose.y, _currentPose.heading);
			_logger->notice("new heading is %.2f", _fHeadingRef);
		}

		gettimeofday(&tvNow, NULL);

	    if (tvNow.tv_usec < tvLast.tv_usec)
	    {
	        nsec = (tvLast.tv_usec - tvNow.tv_usec) / 1000000 + 1;
	        tvLast.tv_usec -= 1000000 * nsec;
	        tvLast.tv_sec  += nsec;
	    }

	    if (tvNow.tv_usec - tvLast.tv_usec > 1000000)
	    {
	        nsec = (tvLast.tv_usec - tvNow.tv_usec) / 1000000;
	        tvLast.tv_usec += 1000000 * nsec;
	        tvLast.tv_sec  -= nsec;
	    }

	    // How long did we sleep since the last iteration? Required for derivatives.
	    delayms = ((tvNow.tv_sec - tvLast.tv_sec) * 1000) + ((tvNow.tv_usec - tvLast.tv_usec) / 1000);
	    totaldelayms += delayms;	// total time in this waypoint segment
	    _totalTime   += delayms;	// total time transiting altogether
	    tvLast        = tvNow;

	    _currentPose.timestamp = _totalTime;

	    // How long have we slept? This is required for our integral and derivative PID values.
    	double dt = delayms / 1000.0;

        ledHealth.strobe();

       	_logger->notice("goToPosition: %lu --- ITERATION %d --- \nreference: (%.2f, %.2f, distance: %.2f) at heading %.2f (total runtime: %lu) (dt: %.2f)", delayms, iteration, _fPosXRef, _fPosYRef, fTargetVectorMagnitudeInitial, _fHeadingRef, totaldelayms, dt);

        // How far has each wheel travelled? This is total distance since odo reset (start of waypoint).
        if (_bSimulation)
        {
        	// Don't use the odometer, see what our model predicts. This can be used to determine how accurate the odometer and drive train is.
            _fDistLeft  += dt * fVelocityLeft;
            _fDistRight += dt * fVelocityRight;
        }
        else
        {
	        _odo->getDistance(&_fDistLeft, &_fDistRight);
	    }

        _fDistTotal = (_fDistLeft + _fDistRight) / 2.0;

    	_logger->notice("goToPosition: distL[%.2f] distR[%.2f] dist[%.2f] distPrev[%.2f]", _fDistLeft, _fDistRight, _fDistTotal, _fDistTotalPrev);

        // How far have we travelled in this last iteration?
        double fDistDelta      = _fDistTotal - _fDistTotalPrev;
        double fDistLeftDelta  = _fDistLeft  - _fDistLeftPrev;
        double fDistRightDelta = _fDistRight - _fDistRightPrev;

    	// Position has changed based on the distance travelled at the previous heading
        _currentPose.x += fDistDelta * cos(_currentPose.heading);
    	_currentPose.y += fDistDelta * sin(_currentPose.heading);

    	// Update the heading as it has changed based on the distance travelled too
    	_currentPose.heading += ((fDistRightDelta - fDistLeftDelta) / CONTROLLER_WHEELBASE);

        // Ensure our heading remains sane
    	_currentPose.heading = atan2(sin(_currentPose.heading), cos(_currentPose.heading));

    	_fDistTotalPrev  = _fDistTotal;
    	_fDistLeftPrev   = _fDistLeft;
    	_fDistRightPrev  = _fDistRight;

        // What's the error between our required heading and our heading?
		double fHeadingErrorRaw = _fHeadingRef - _currentPose.heading;
		_fHeadingError = atan2(sin(fHeadingErrorRaw), cos(fHeadingErrorRaw));

		// How fast should we proceed forward? (Anything below 5 results in non-movement due to inertia)
		double fForwardVelocity = 9.0;              // 5.0 works as well but undershoots

       	// What is the magnitude of the vector between us and our target?
       	fTargetVectorMagnitude = sqrt(((_fPosXRef - _currentPose.x)*(_fPosXRef - _currentPose.x)) + ((_fPosYRef - _currentPose.y)*(_fPosYRef - _currentPose.y)));

       	if (bFirstIteration)
       	{
       	    fTargetVectorMagnitudeInitial = fTargetVectorMagnitude;
       	}

    	_logger->notice("goToPosition: heading[%.4f, e: %.6f] posX[%.2f] posY[%.2f] distToTarget[%.2f] distToTargetLast[%.2f]", _currentPose.heading, _fHeadingError, _currentPose.x, _currentPose.y, fTargetVectorMagnitude, fTargetVectorMagnitudeLast);

    	/**
    	 * @todo: Come up with a better way of determining whether we should consider ourself "close enough" to the waypoint.
    	 */
    	if ( ! bFirstIteration)
    	{
    	    if (fTargetVectorMagnitude >= fTargetVectorMagnitudeLast)
    	    {
    	    	if (nConsecutiveIncreasingDistance == 0)
    	    	{
    	    		fTargetVectorMagnitudeAtStartOfDrift = fTargetVectorMagnitude;
    	    	}

    	        nConsecutiveIncreasingDistance++;

    	        double fDistanceCoveredSinceStartOfDrift = fTargetVectorMagnitude - fTargetVectorMagnitudeAtStartOfDrift;

    	        if (fDistanceCoveredSinceStartOfDrift >= (0.25 * fTargetVectorMagnitudeInitial))
//    	        if (nConsecutiveIncreasingDistance > MAX_ITERATIONS_OF_INCREASING_TARGET_VECTOR_BEFORE_TERMINATION)
    	        {
		    	    _logger->notice("goToPosition: Distance to target has increased!\ngoToPosition: --- END ABNORMAL ---\n");
    	            break;
    	        }
    	    }
    	    else
    	    {
    	        nConsecutiveIncreasingDistance = 0;
    	    }
    	}

    	if (fTargetVectorMagnitude < 10 || bApproachingTarget)
    	{
    		bApproachingTarget = true;

    		ledProximity.on();
    	    _logger->notice("goToPosition: Approaching target, slowing down.");
    	    fForwardVelocity = 3.0;                 // 3.0 works as well, safer
    	}

//      _logger->notice("goToPosition: x(%.2f)\ty(%.2f)\ttheta(%.2f)", _fPosXCurrent, _fPosYCurrent, _fHeadingCurrent);

    	if (fTargetVectorMagnitude <= 5)
    	{
    	    _logger->notice("goToPosition: You have arrived at your destination!\ngoToPosition: --- END ---\n");
            _dotLogPosition->log((_totalTime / 1000.0), _currentPose.x, _currentPose.y, DotLog::DotLogPositionColour::RED, true);
    	    break;
    	}
    	else
    	{
            _dotLogPosition->log((_totalTime / 1000.0), _currentPose.x, _currentPose.y, bApproachingTarget ? DotLog::DotLogPositionColour::RED : DotLog::DotLogPositionColour::BLACK);
    	}

		fTargetVectorMagnitudeLast = fTargetVectorMagnitude;

//    	if (fabs(fPosXCurrent - fPosXRef) < (CONTROLLER_WHEELBASE/2.0) && fabs(fPosYCurrent - fPosYRef) < (CONTROLLER_WHEELBASE/2.0))
//    	{
//    		printf("You have arrived at your destination (non-vector)!\n");
//    		break;
//    	}

    	// Maintain the PID variables
    	double fHeadingErrorDerivative = (_fHeadingError - _fHeadingErrorPrev) / dt;
    	_fHeadingErrorIntegral        += (_fHeadingError * dt);
    	_fHeadingErrorPrev             = _fHeadingError;

    	double pidP = CONTROLLER_PID_PROPORTIONAL * _fHeadingError;
    	double pidI = CONTROLLER_PID_INTEGRAL     * _fHeadingErrorIntegral;
    	double pidD = CONTROLLER_PID_DERIVATIVE   * fHeadingErrorDerivative;

    	// PID, this gives us the control signal, u, this is required angular velocity
    	double u = pidP + pidI + pidD;

    	// Angular velocity gives us new wheel velocities. We assume a constant forward velocity for simplicity.
    	fVelocityRight = ((2.0*fForwardVelocity) + (u*CONTROLLER_WHEELBASE)) / (2.0*CONTROLLER_WHEELRADIUS);   // cm/s
		fVelocityLeft  = ((2.0*fForwardVelocity) - (u*CONTROLLER_WHEELBASE)) / (2.0*CONTROLLER_WHEELRADIUS);   // cm/s

		_logger->notice("goToPosition: P[%.6f] I[%.6f] D[%.6f] u[%.6f] -> required velocities (left,right) are (%.2f,%.2f)", pidP, pidI, pidD, u, fVelocityLeft, fVelocityRight);

		// These velocities are relative, work out the required velocity per wheel.
//		float vLeft  = (fVelocityLeft  / (fabs(fVelocityLeft) + fabs(fVelocityRight))) * 100.0;
//		float vRight = (fVelocityRight / (fabs(fVelocityLeft) + fabs(fVelocityRight))) * 100.0;
//
//		int   dLeft  = static_cast<int>(fabs(vLeft));
//		int   dRight = static_cast<int>(fabs(vRight));
//
//		printf("Required relative velocities (left,right) are (%.2f,%.2f) -> (%d,%d)\n", vLeft, vRight, dLeft, dRight);

		int nLeftPWM  = convertVelocityToPWMPercentage(true, fVelocityLeft);
		int nRightPWM = convertVelocityToPWMPercentage(false, fVelocityRight);

		// Apply the new velocities to the motors
		if ( ! _bSimulation)
		{
			if (fVelocityLeft < 0.0)
			{
				motor_reverse(MOTOR_LEFT, pwm_speed(nLeftPWM));
			}
			else
			{
				motor_forward(MOTOR_LEFT, pwm_speed(nLeftPWM));
			}

			if (fVelocityRight < 0.0)
			{
				motor_reverse(MOTOR_RIGHT, pwm_speed(nRightPWM));
			}
			else
			{
				motor_forward(MOTOR_RIGHT, pwm_speed(nRightPWM));
			}
		}

		usleep(50000);      // 50ms
//		usleep(300000);     // 300 ms
//		usleep(1000000);    // 1s

    	/**
    	 * time passes ... wheels respond to new control signal and begin moving at new velocities
    	 *
    	 *  These wheel velocities turn the wheels and influence the distance travelled and heading
    	 *  which is recalculated in the next iteration.
    	 */

    	bFirstIteration = false;
    	iteration++;
    }

    bot_stop();

    ledHealth.off();
}