Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed RSEDP_AM_MC1_lib SDFileSystem
Rover.cpp
00001 /** 00002 * @author Aaron Berk 00003 * 00004 * @section LICENSE 00005 * 00006 * Copyright (c) 2010 ARM Limited 00007 * 00008 * Permission is hereby granted, free of charge, to any person obtaining a copy 00009 * of this software and associated documentation files (the "Software"), to deal 00010 * in the Software without restriction, including without limitation the rights 00011 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00012 * copies of the Software, and to permit persons to whom the Software is 00013 * furnished to do so, subject to the following conditions: 00014 * 00015 * The above copyright notice and this permission notice shall be included in 00016 * all copies or substantial portions of the Software. 00017 * 00018 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00019 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00020 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00021 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00022 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00023 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 00024 * THE SOFTWARE. 00025 * 00026 * @section DESCRIPTION 00027 * 00028 * RS-EDP Rover application class. 00029 * 00030 * Demonstrates four action states: moving {forward, backward}, 00031 * rotating {clockwise, counter-clockwise}. 00032 * 00033 * Logs heading and left and right motor position and velocity data. 00034 * 00035 * Performs PID velocity control on the motors. 00036 * 00037 * --------------- 00038 * CONFIGURATION 00039 * --------------- 00040 * 00041 * The set up assumes the H-bridge being used has pins for: 00042 * 00043 * - PWM input 00044 * - Brake 00045 * - Direction 00046 * 00047 * The constructor arguments will need to be changed if a different type of 00048 * H-bridge is used. 00049 * 00050 * The PID controllers are configured using the #defines below. 00051 * 00052 * The set up also assumes two quadrature encoders are used, each using the 00053 * default X2 encoding. 00054 * 00055 * The constructor arguments will need to be changed if a different number 00056 * of encoders are used or if a different encoding is required. 00057 */ 00058 00059 /** 00060 * Includes 00061 */ 00062 #include "Rover.h" 00063 00064 Rover::Rover(PinName leftMotorPwm, 00065 PinName leftMotorBrake, 00066 PinName leftMotorDirection, 00067 PinName rightMotorPwm, 00068 PinName rightMotorBrake, 00069 PinName rightMotorDirection, 00070 PinName leftQeiChannelA, 00071 PinName leftQeiChannelB, 00072 PinName leftQeiIndex, 00073 int leftPulsesPerRev, 00074 PinName rightQeiChannelA, 00075 PinName rightQeiChannelB, 00076 PinName rightQeiIndex, 00077 int rightPulsesPerRev) : 00078 leftMotors(), 00079 rightMotors(), 00080 leftQei(leftQeiChannelA, 00081 leftQeiChannelB, 00082 leftQeiIndex, 00083 leftPulsesPerRev), 00084 rightQei(rightQeiChannelA, 00085 rightQeiChannelB, 00086 rightQeiIndex, 00087 rightPulsesPerRev), 00088 leftController(Kc, Ti, Td, PID_RATE), 00089 rightController(Kc, Ti, Td, PID_RATE), 00090 stateTicker(), 00091 logTicker(), 00092 imu(IMU_RATE_, 00093 GYRO_MEAS_ERROR, 00094 ACCELEROMETER_RATE, 00095 GYROSCOPE_RATE) { 00096 00097 //--------------------------------- 00098 // Left motors and PID controller. 00099 //--------------------------------- 00100 00101 //Motors. 00102 leftMotors.setPwmPin(leftMotorPwm); 00103 leftMotors.setBrakePin(leftMotorBrake); 00104 leftMotors.setDirectionPin(leftMotorDirection); 00105 leftMotors.initialize(); 00106 leftMotors.setDirection(BACKWARD); 00107 leftMotors.setBrake(BRAKE_OFF); 00108 00109 //PID. 00110 leftController.setInputLimits(PID_IN_MIN, PID_IN_MAX); 00111 leftController.setOutputLimits(PID_OUT_MIN, PID_OUT_MAX); 00112 leftController.setBias(PID_BIAS); 00113 leftController.setMode(AUTO_MODE); 00114 leftPulses_ = 0; 00115 leftPrevPulses_ = 0; 00116 leftPwmDuty_ = 1.0; 00117 leftVelocity_ = 0.0; 00118 00119 //---------------------------------- 00120 // Right motors and PID controller. 00121 //---------------------------------- 00122 00123 //Motors. 00124 rightMotors.setPwmPin(rightMotorPwm); 00125 rightMotors.setBrakePin(rightMotorBrake); 00126 rightMotors.setDirectionPin(rightMotorDirection); 00127 rightMotors.initialize(); 00128 rightMotors.setDirection(FORWARD); 00129 rightMotors.setBrake(BRAKE_OFF); 00130 00131 //PID. 00132 rightController.setInputLimits(PID_IN_MIN, PID_IN_MAX); 00133 rightController.setOutputLimits(PID_OUT_MIN, PID_OUT_MAX); 00134 rightController.setBias(PID_BIAS); 00135 rightController.setMode(AUTO_MODE); 00136 rightPulses_ = 0; 00137 rightPrevPulses_ = 0; 00138 rightPwmDuty_ = 1.0; 00139 rightVelocity_ = 0.0; 00140 00141 //-------------------- 00142 // Working Variables. 00143 //-------------------- 00144 positionSetPoint_ = 0.0; 00145 headingSetPoint_ = 0.0; 00146 heading_ = 0.0; 00147 prevHeading_ = 0.0; 00148 degreesTurned_ = 0.0; 00149 leftStopFlag_ = 0; 00150 rightStopFlag_ = 0; 00151 logIndex = 0; 00152 00153 //-------- 00154 // BEGIN! 00155 //-------- 00156 state_ = STATE_STATIONARY; 00157 stateTicker.attach(this, &Rover::doState, PID_RATE); 00158 startLogging(); 00159 00160 } 00161 00162 void Rover::move(float distance) { 00163 00164 //Convert from metres into millimetres. 00165 distance *= 1000; 00166 //Work out how many pulses are required to go that many millimetres. 00167 distance *= PULSES_PER_MM; 00168 //Make sure we scale the number of pulses according to our encoding method. 00169 distance /= ENCODING; 00170 00171 positionSetPoint_ = distance; 00172 00173 //Moving forward. 00174 if (distance > 0) { 00175 00176 enterState(STATE_MOVING_FORWARD); 00177 00178 } 00179 //Moving backward. 00180 else if (distance < 0) { 00181 00182 enterState(STATE_MOVING_BACKWARD); 00183 00184 } 00185 00186 //If distance == 0, then do nothing, i.e. stay stationary. 00187 00188 } 00189 00190 void Rover::turn(int degrees) { 00191 00192 //Correct the amount to turn based on deviation during last segment. 00193 headingSetPoint_ = abs(degrees) + (endHeading_ - startHeading_); 00194 00195 //In case the rover tries to [pointlessly] turn >360 degrees. 00196 if (headingSetPoint_ > 359.8){ 00197 00198 headingSetPoint_ -= 359.8; 00199 00200 } 00201 00202 //Rotating clockwise. 00203 if (degrees > 0) { 00204 00205 enterState(STATE_ROTATING_CLOCKWISE); 00206 00207 } 00208 //Rotating counter-clockwise. 00209 else if (degrees < 0) { 00210 00211 enterState(STATE_ROTATING_COUNTER_CLOCKWISE); 00212 00213 } 00214 00215 //If degrees == 0, then do nothing, i.e. stay stationary. 00216 00217 } 00218 00219 Rover::State Rover::getState(void) { 00220 00221 return state_; 00222 00223 } 00224 00225 void Rover::startLogging(void) { 00226 00227 logFile = fopen("/local/roverlog.csv", "w"); 00228 fprintf(logFile, "leftPulses, rightPulses, leftVelocity, rightVelocity, heading\n"); 00229 //logTicker.attach(this, &Rover::log, LOG_RATE); 00230 00231 } 00232 00233 void Rover::stopLogging(void) { 00234 00235 //logFile = fopen("/local/roverlog.csv", "w"); 00236 //fprintf(logFile, "leftPulses, rightPulses, leftVelocity, rightVelocity, heading, degreesTurned\n"); 00237 //fprintf(logFile, "leftVelocity, rightVelocity\n"); 00238 //for(int i = 0; i < 1024; i++){ 00239 // fprintf(logFile, "%f, %f\n", leftVelocityBuffer[i], rightVelocityBuffer[i]); 00240 //} 00241 fclose(logFile); 00242 00243 } 00244 00245 void Rover::log(void) { 00246 00247 //fprintf(logFile, "%i,%i,%f,%f,%f,%f\n", 00248 // leftPulses_, rightPulses_, leftVelocity_, rightVelocity_, imu.getYaw(), degreesTurned_); 00249 00250 } 00251 00252 void Rover::doState(void) { 00253 00254 switch (state_) { 00255 00256 //We're not moving so don't do anything! 00257 case (STATE_STATIONARY): 00258 00259 break; 00260 00261 case (STATE_MOVING_FORWARD): 00262 00263 //If we haven't hit the position set point yet, 00264 //perform velocity control on the motors. 00265 if (leftPulses_ < positionSetPoint_) { 00266 00267 leftPulses_ = leftQei.getPulses(); 00268 leftVelocity_ = (leftPulses_ - leftPrevPulses_) / PID_RATE; 00269 leftPrevPulses_ = leftPulses_; 00270 leftController.setProcessValue(leftVelocity_); 00271 leftPwmDuty_ = leftController.compute(); 00272 00273 } else { 00274 leftStopFlag_ = 1; 00275 } 00276 00277 leftMotors.setPwmDuty(leftPwmDuty_); 00278 00279 if (rightPulses_ < positionSetPoint_) { 00280 00281 rightPulses_ = rightQei.getPulses(); 00282 rightVelocity_ = (rightPulses_ - rightPrevPulses_) / PID_RATE; 00283 rightPrevPulses_ = rightPulses_; 00284 rightController.setProcessValue(rightVelocity_); 00285 rightPwmDuty_ = rightController.compute(); 00286 00287 } else { 00288 rightStopFlag_ = 1; 00289 } 00290 00291 rightMotors.setPwmDuty(rightPwmDuty_); 00292 00293 //We've hit the end position set point. 00294 if (leftStopFlag_ == 1 && rightStopFlag_ == 1) { 00295 leftPwmDuty_ = 1.0; 00296 rightPwmDuty_ = 1.0; 00297 leftMotors.setPwmDuty(leftPwmDuty_); 00298 rightMotors.setPwmDuty(rightPwmDuty_); 00299 endHeading_ = imu.getYaw(); 00300 enterState(STATE_STATIONARY); 00301 } 00302 00303 break; 00304 00305 case (STATE_MOVING_BACKWARD): 00306 00307 //If we haven't hit the position set point yet, 00308 //perform velocity control on the motors. 00309 if (leftPulses_ > positionSetPoint_) { 00310 leftPulses_ = leftQei.getPulses(); 00311 leftVelocity_ = (leftPulses_ - leftPrevPulses_) / PID_RATE; 00312 leftPrevPulses_ = leftPulses_; 00313 leftController.setProcessValue(fabs(leftVelocity_)); 00314 leftPwmDuty_ = leftController.compute(); 00315 } else { 00316 leftStopFlag_ = 1; 00317 } 00318 00319 leftMotors.setPwmDuty(leftPwmDuty_); 00320 00321 if (rightPulses_ > positionSetPoint_) { 00322 rightPulses_ = rightQei.getPulses(); 00323 rightVelocity_ = (rightPulses_ - rightPrevPulses_) / PID_RATE; 00324 rightPrevPulses_ = rightPulses_; 00325 rightController.setProcessValue(fabs(rightVelocity_)); 00326 rightPwmDuty_ = rightController.compute(); 00327 00328 } else { 00329 rightStopFlag_ = 1; 00330 } 00331 00332 rightMotors.setPwmDuty(rightPwmDuty_); 00333 00334 //We've hit the end position set point. 00335 if (leftStopFlag_ == 1.0 && rightStopFlag_ == 1.0) { 00336 leftPwmDuty_ = 1.0; 00337 rightPwmDuty_ = 1.0; 00338 leftMotors.setPwmDuty(leftPwmDuty_); 00339 rightMotors.setPwmDuty(rightPwmDuty_); 00340 enterState(STATE_STATIONARY); 00341 } 00342 00343 break; 00344 00345 case (STATE_ROTATING_CLOCKWISE): 00346 00347 //If we haven't hit the position set point yet, 00348 //perform velocity control on the motors. 00349 if (degreesTurned_ < headingSetPoint_) { 00350 00351 heading_ = fabs(imu.getYaw()); 00352 degreesTurned_ += fabs(heading_ - prevHeading_); 00353 prevHeading_ = heading_; 00354 00355 leftPulses_ = leftQei.getPulses(); 00356 leftVelocity_ = (leftPulses_ - leftPrevPulses_) / PID_RATE; 00357 leftPrevPulses_ = leftPulses_; 00358 leftController.setProcessValue(leftVelocity_); 00359 leftPwmDuty_ = leftController.compute(); 00360 00361 rightPulses_ = rightQei.getPulses(); 00362 rightVelocity_ = (rightPulses_ - rightPrevPulses_) / PID_RATE; 00363 rightPrevPulses_ = rightPulses_; 00364 rightController.setProcessValue(fabs(rightVelocity_)); 00365 rightPwmDuty_ = rightController.compute(); 00366 00367 leftMotors.setPwmDuty(leftPwmDuty_); 00368 rightMotors.setPwmDuty(rightPwmDuty_); 00369 00370 } else { 00371 00372 leftPwmDuty_ = 1.0; 00373 rightPwmDuty_ = 1.0; 00374 leftMotors.setPwmDuty(leftPwmDuty_); 00375 rightMotors.setPwmDuty(rightPwmDuty_); 00376 enterState(STATE_STATIONARY); 00377 00378 } 00379 00380 break; 00381 00382 case (STATE_ROTATING_COUNTER_CLOCKWISE): 00383 00384 //If we haven't hit the position set point yet, 00385 //perform velocity control on the motors. 00386 if (degreesTurned_ < headingSetPoint_) { 00387 00388 heading_ = fabs(imu.getYaw()); 00389 degreesTurned_ += fabs(heading_ - prevHeading_); 00390 prevHeading_ = heading_; 00391 00392 leftPulses_ = leftQei.getPulses(); 00393 leftVelocity_ = (leftPulses_ - leftPrevPulses_) / PID_RATE; 00394 leftPrevPulses_ = leftPulses_; 00395 leftController.setProcessValue(fabs(leftVelocity_)); 00396 leftPwmDuty_ = leftController.compute(); 00397 00398 rightPulses_ = rightQei.getPulses(); 00399 rightVelocity_ = (rightPulses_ - rightPrevPulses_) / PID_RATE; 00400 rightPrevPulses_ = rightPulses_; 00401 rightController.setProcessValue(rightVelocity_); 00402 rightPwmDuty_ = rightController.compute(); 00403 00404 leftMotors.setPwmDuty(leftPwmDuty_); 00405 rightMotors.setPwmDuty(rightPwmDuty_); 00406 00407 } else { 00408 00409 leftPwmDuty_ = 1.0; 00410 rightPwmDuty_ = 1.0; 00411 leftMotors.setPwmDuty(leftPwmDuty_); 00412 rightMotors.setPwmDuty(rightPwmDuty_); 00413 enterState(STATE_STATIONARY); 00414 00415 } 00416 00417 break; 00418 00419 //If we've fallen into a black hole, the least we can do is turn 00420 //the motors off. 00421 default: 00422 00423 leftMotors.setPwmDuty(1.0); 00424 rightMotors.setPwmDuty(1.0); 00425 00426 break; 00427 00428 } 00429 00430 if (logIndex < 1024) { 00431 headingBuffer[logIndex] = imu.getYaw(); 00432 leftVelocityBuffer[logIndex] = leftVelocity_; 00433 rightVelocityBuffer[logIndex] = rightVelocity_; 00434 leftPositionBuffer[logIndex] = leftPulses_; 00435 rightPositionBuffer[logIndex] = rightPulses_; 00436 logIndex++; 00437 } 00438 00439 } 00440 00441 void Rover::enterState(State state) { 00442 00443 switch (state) { 00444 00445 //Entering stationary state. 00446 //1. Turn motors off. 00447 //2. Reset QEIs. 00448 //3. Reset PID working variables. 00449 //4. Reset PIDs. 00450 //5. Reset set points and working variables. 00451 //7. Set state variable. 00452 case (STATE_STATIONARY): 00453 00454 leftMotors.setPwmDuty(1.0); 00455 rightMotors.setPwmDuty(1.0); 00456 00457 leftQei.reset(); 00458 rightQei.reset(); 00459 00460 leftPulses_ = 0; 00461 leftPrevPulses_ = 0; 00462 leftPwmDuty_ = 1.0; 00463 leftVelocity_ = 0.0; 00464 00465 rightPulses_ = 0; 00466 rightPrevPulses_ = 0; 00467 rightPwmDuty_ = 1.0; 00468 rightVelocity_ = 0.0; 00469 00470 leftController.setSetPoint(0.0); 00471 leftController.setProcessValue(0.0); 00472 rightController.setSetPoint(0.0); 00473 rightController.setProcessValue(0.0); 00474 00475 positionSetPoint_ = 0.0; 00476 headingSetPoint_ = 0.0; 00477 heading_ = 0.0; 00478 prevHeading_ = 0.0; 00479 degreesTurned_ = 0.0; 00480 leftStopFlag_ = 0; 00481 rightStopFlag_ = 0; 00482 00483 for (int i = 0; i < logIndex; i++) { 00484 fprintf(logFile, "%i, %i, %f, %f, %f\n", leftPositionBuffer[i], 00485 rightPositionBuffer[i], 00486 leftVelocityBuffer[i], 00487 rightVelocityBuffer[i], 00488 headingBuffer[i]); 00489 } 00490 00491 logIndex = 0; 00492 00493 imu.reset(); 00494 00495 state_ = STATE_STATIONARY; 00496 00497 break; 00498 00499 //Entering moving forward state. 00500 //1. Set correct direction for motors. 00501 //2. Set velocity set point. 00502 //3. Set state variable. 00503 case (STATE_MOVING_FORWARD): 00504 00505 leftMotors.setDirection(BACKWARD); 00506 rightMotors.setDirection(FORWARD); 00507 00508 //Velocity control. 00509 leftController.setSetPoint(1000); 00510 rightController.setSetPoint(1000); 00511 00512 logIndex = 0; 00513 00514 startHeading_ = imu.getYaw(); 00515 00516 state_ = STATE_MOVING_FORWARD; 00517 00518 break; 00519 00520 //Entering moving backward state. 00521 //1. Set correct direction for motors. 00522 //2. Set velocity set point. 00523 //3. Set state variable. 00524 case (STATE_MOVING_BACKWARD): 00525 00526 leftMotors.setDirection(FORWARD); 00527 rightMotors.setDirection(BACKWARD); 00528 00529 //Velocity control. 00530 leftController.setSetPoint(1000); 00531 rightController.setSetPoint(1000); 00532 00533 logIndex = 0; 00534 00535 state_ = STATE_MOVING_BACKWARD; 00536 00537 break; 00538 00539 //Entering rotating clockwise state. 00540 //1. Set correct direction for motors. 00541 //2. Set velocity set point. 00542 //3. Set working variables. 00543 //4. Set state variable. 00544 case (STATE_ROTATING_CLOCKWISE): 00545 00546 leftMotors.setDirection(BACKWARD); 00547 rightMotors.setDirection(BACKWARD); 00548 00549 leftController.setSetPoint(500); 00550 rightController.setSetPoint(500); 00551 00552 degreesTurned_ = 0.0; 00553 heading_ = fabs(imu.getYaw()); 00554 prevHeading_ = heading_; 00555 00556 logIndex = 0; 00557 00558 state_ = STATE_ROTATING_CLOCKWISE; 00559 00560 break; 00561 00562 //Entering rotating clockwise state. 00563 //1. Set correct direction for motors. 00564 //2. Set velocity set point. 00565 //3. Set working variables. 00566 //4. Set state variable. 00567 case (STATE_ROTATING_COUNTER_CLOCKWISE): 00568 00569 leftMotors.setDirection(FORWARD); 00570 rightMotors.setDirection(FORWARD); 00571 00572 leftController.setSetPoint(500); 00573 rightController.setSetPoint(500); 00574 00575 degreesTurned_ = 0.0; 00576 heading_ = fabs(imu.getYaw()); 00577 prevHeading_ = heading_; 00578 00579 logIndex = 0; 00580 00581 state_ = STATE_ROTATING_COUNTER_CLOCKWISE; 00582 00583 break; 00584 00585 default: 00586 00587 state_ = STATE_STATIONARY; 00588 00589 break; 00590 00591 } 00592 00593 }
Generated on Fri Jul 22 2022 22:00:46 by
1.7.2