Now you can download a copy of these docs so you can use them offline! Download now
RobotDrive.cpp
00001 /*----------------------------------------------------------------------------*/ 00002 /* Copyright (c) FIRST 2008. All Rights Reserved. */ 00003 /* Open Source Software - may be modified and shared by FRC teams. The code */ 00004 /* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */ 00005 /*----------------------------------------------------------------------------*/ 00006 00007 #include "RobotDrive.h" 00008 00009 #include "CANJaguar.h" 00010 #include "GenericHID.h" 00011 #include "Joystick.h" 00012 #include "Jaguar.h" 00013 #include "Utility.h" 00014 #include "WPIErrors.h" 00015 #include <math.h> 00016 00017 #define max(x, y) (((x) > (y)) ? (x) : (y)) 00018 00019 const INT32 RobotDrive::kMaxNumberOfMotors; 00020 00021 /* 00022 * Driving functions 00023 * These functions provide an interface to multiple motors that is used for C programming 00024 * The Drive(speed, direction) function is the main part of the set that makes it easy 00025 * to set speeds and direction independently in one call. 00026 */ 00027 00033 void RobotDrive::InitRobotDrive() { 00034 m_frontLeftMotor = NULL; 00035 m_frontRightMotor = NULL; 00036 m_rearRightMotor = NULL; 00037 m_rearLeftMotor = NULL; 00038 m_sensitivity = 0.5; 00039 m_maxOutput = 1.0; 00040 m_safetyHelper = new MotorSafetyHelper(this); 00041 m_safetyHelper->SetSafetyEnabled(true); 00042 } 00043 00051 RobotDrive::RobotDrive(UINT32 leftMotorChannel, UINT32 rightMotorChannel) 00052 { 00053 InitRobotDrive(); 00054 m_rearLeftMotor = new Jaguar(leftMotorChannel); 00055 m_rearRightMotor = new Jaguar(rightMotorChannel); 00056 for (INT32 i=0; i < kMaxNumberOfMotors; i++) 00057 { 00058 m_invertedMotors[i] = 1; 00059 } 00060 Drive(0, 0); 00061 m_deleteSpeedControllers = true; 00062 } 00063 00074 RobotDrive::RobotDrive(UINT32 frontLeftMotor, UINT32 rearLeftMotor, 00075 UINT32 frontRightMotor, UINT32 rearRightMotor) 00076 { 00077 InitRobotDrive(); 00078 m_rearLeftMotor = new Jaguar(rearLeftMotor); 00079 m_rearRightMotor = new Jaguar(rearRightMotor); 00080 m_frontLeftMotor = new Jaguar(frontLeftMotor); 00081 m_frontRightMotor = new Jaguar(frontRightMotor); 00082 for (INT32 i=0; i < kMaxNumberOfMotors; i++) 00083 { 00084 m_invertedMotors[i] = 1; 00085 } 00086 Drive(0, 0); 00087 m_deleteSpeedControllers = true; 00088 } 00089 00098 RobotDrive::RobotDrive(SpeedController *leftMotor, SpeedController *rightMotor) 00099 { 00100 InitRobotDrive(); 00101 if (leftMotor == NULL || rightMotor == NULL) 00102 { 00103 wpi_setWPIError(NullParameter); 00104 m_rearLeftMotor = m_rearRightMotor = NULL; 00105 return; 00106 } 00107 m_rearLeftMotor = leftMotor; 00108 m_rearRightMotor = rightMotor; 00109 for (INT32 i=0; i < kMaxNumberOfMotors; i++) 00110 { 00111 m_invertedMotors[i] = 1; 00112 } 00113 m_deleteSpeedControllers = false; 00114 } 00115 00116 RobotDrive::RobotDrive(SpeedController &leftMotor, SpeedController &rightMotor) 00117 { 00118 InitRobotDrive(); 00119 m_rearLeftMotor = &leftMotor; 00120 m_rearRightMotor = &rightMotor; 00121 for (INT32 i=0; i < kMaxNumberOfMotors; i++) 00122 { 00123 m_invertedMotors[i] = 1; 00124 } 00125 m_deleteSpeedControllers = false; 00126 } 00127 00136 RobotDrive::RobotDrive(SpeedController *frontLeftMotor, SpeedController *rearLeftMotor, 00137 SpeedController *frontRightMotor, SpeedController *rearRightMotor) 00138 { 00139 InitRobotDrive(); 00140 if (frontLeftMotor == NULL || rearLeftMotor == NULL || frontRightMotor == NULL || rearRightMotor == NULL) 00141 { 00142 wpi_setWPIError(NullParameter); 00143 return; 00144 } 00145 m_frontLeftMotor = frontLeftMotor; 00146 m_rearLeftMotor = rearLeftMotor; 00147 m_frontRightMotor = frontRightMotor; 00148 m_rearRightMotor = rearRightMotor; 00149 for (INT32 i=0; i < kMaxNumberOfMotors; i++) 00150 { 00151 m_invertedMotors[i] = 1; 00152 } 00153 m_deleteSpeedControllers = false; 00154 } 00155 00156 RobotDrive::RobotDrive(SpeedController &frontLeftMotor, SpeedController &rearLeftMotor, 00157 SpeedController &frontRightMotor, SpeedController &rearRightMotor) 00158 { 00159 InitRobotDrive(); 00160 m_frontLeftMotor = &frontLeftMotor; 00161 m_rearLeftMotor = &rearLeftMotor; 00162 m_frontRightMotor = &frontRightMotor; 00163 m_rearRightMotor = &rearRightMotor; 00164 for (INT32 i=0; i < kMaxNumberOfMotors; i++) 00165 { 00166 m_invertedMotors[i] = 1; 00167 } 00168 m_deleteSpeedControllers = false; 00169 } 00170 00175 RobotDrive::~RobotDrive() 00176 { 00177 if (m_deleteSpeedControllers) 00178 { 00179 delete m_frontLeftMotor; 00180 delete m_rearLeftMotor; 00181 delete m_frontRightMotor; 00182 delete m_rearRightMotor; 00183 } 00184 delete m_safetyHelper; 00185 } 00186 00199 void RobotDrive::Drive(float outputMagnitude, float curve) 00200 { 00201 float leftOutput, rightOutput; 00202 00203 if (curve < 0) 00204 { 00205 float value = log(-curve); 00206 float ratio = (value - m_sensitivity)/(value + m_sensitivity); 00207 if (ratio == 0) ratio =.0000000001; 00208 leftOutput = outputMagnitude / ratio; 00209 rightOutput = outputMagnitude; 00210 } 00211 else if (curve > 0) 00212 { 00213 float value = log(curve); 00214 float ratio = (value - m_sensitivity)/(value + m_sensitivity); 00215 if (ratio == 0) ratio =.0000000001; 00216 leftOutput = outputMagnitude; 00217 rightOutput = outputMagnitude / ratio; 00218 } 00219 else 00220 { 00221 leftOutput = outputMagnitude; 00222 rightOutput = outputMagnitude; 00223 } 00224 SetLeftRightMotorOutputs(leftOutput, rightOutput); 00225 } 00226 00234 void RobotDrive::TankDrive(GenericHID *leftStick, GenericHID *rightStick) 00235 { 00236 if (leftStick == NULL || rightStick == NULL) 00237 { 00238 wpi_setWPIError(NullParameter); 00239 return; 00240 } 00241 TankDrive(leftStick->GetY(), rightStick->GetY()); 00242 } 00243 00244 void RobotDrive::TankDrive(GenericHID &leftStick, GenericHID &rightStick) 00245 { 00246 TankDrive(leftStick.GetY(), rightStick.GetY()); 00247 } 00248 00258 void RobotDrive::TankDrive(GenericHID *leftStick, UINT32 leftAxis, 00259 GenericHID *rightStick, UINT32 rightAxis) 00260 { 00261 if (leftStick == NULL || rightStick == NULL) 00262 { 00263 wpi_setWPIError(NullParameter); 00264 return; 00265 } 00266 TankDrive(leftStick->GetRawAxis(leftAxis), rightStick->GetRawAxis(rightAxis)); 00267 } 00268 00269 void RobotDrive::TankDrive(GenericHID &leftStick, UINT32 leftAxis, 00270 GenericHID &rightStick, UINT32 rightAxis) 00271 { 00272 TankDrive(leftStick.GetRawAxis(leftAxis), rightStick.GetRawAxis(rightAxis)); 00273 } 00274 00275 00282 void RobotDrive::TankDrive(float leftValue, float rightValue) 00283 { 00284 // square the inputs (while preserving the sign) to increase fine control while permitting full power 00285 leftValue = Limit(leftValue); 00286 rightValue = Limit(rightValue); 00287 if (leftValue >= 0.0) 00288 { 00289 leftValue = (leftValue * leftValue); 00290 } 00291 else 00292 { 00293 leftValue = -(leftValue * leftValue); 00294 } 00295 if (rightValue >= 0.0) 00296 { 00297 rightValue = (rightValue * rightValue); 00298 } 00299 else 00300 { 00301 rightValue = -(rightValue * rightValue); 00302 } 00303 00304 SetLeftRightMotorOutputs(leftValue, rightValue); 00305 } 00306 00316 void RobotDrive::ArcadeDrive(GenericHID *stick, bool squaredInputs) 00317 { 00318 // simply call the full-featured ArcadeDrive with the appropriate values 00319 ArcadeDrive(stick->GetY(), stick->GetX(), stick->GetTrigger()); 00320 } 00321 00331 void RobotDrive::ArcadeDrive(GenericHID &stick, bool squaredInputs) 00332 { 00333 // simply call the full-featured ArcadeDrive with the appropriate values 00334 ArcadeDrive(stick.GetY(), stick.GetX(), stick.GetTrigger()); 00335 } 00336 00347 void RobotDrive::ArcadeDrive(GenericHID* moveStick, UINT32 moveAxis, 00348 GenericHID* rotateStick, UINT32 rotateAxis, 00349 bool squaredInputs) 00350 { 00351 float moveValue = moveStick->GetRawAxis(moveAxis); 00352 float rotateValue = rotateStick->GetRawAxis(rotateAxis); 00353 00354 ArcadeDrive(moveValue, rotateValue, squaredInputs); 00355 } 00356 00368 void RobotDrive::ArcadeDrive(GenericHID &moveStick, UINT32 moveAxis, 00369 GenericHID &rotateStick, UINT32 rotateAxis, 00370 bool squaredInputs) 00371 { 00372 float moveValue = moveStick.GetRawAxis(moveAxis); 00373 float rotateValue = rotateStick.GetRawAxis(rotateAxis); 00374 00375 ArcadeDrive(moveValue, rotateValue, squaredInputs); 00376 } 00377 00385 void RobotDrive::ArcadeDrive(float moveValue, float rotateValue, bool squaredInputs) 00386 { 00387 // local variables to hold the computed PWM values for the motors 00388 float leftMotorOutput; 00389 float rightMotorOutput; 00390 00391 moveValue = Limit(moveValue); 00392 rotateValue = Limit(rotateValue); 00393 00394 if (squaredInputs) 00395 { 00396 // square the inputs (while preserving the sign) to increase fine control while permitting full power 00397 if (moveValue >= 0.0) 00398 { 00399 moveValue = (moveValue * moveValue); 00400 } 00401 else 00402 { 00403 moveValue = -(moveValue * moveValue); 00404 } 00405 if (rotateValue >= 0.0) 00406 { 00407 rotateValue = (rotateValue * rotateValue); 00408 } 00409 else 00410 { 00411 rotateValue = -(rotateValue * rotateValue); 00412 } 00413 } 00414 00415 if (moveValue > 0.0) 00416 { 00417 if (rotateValue > 0.0) 00418 { 00419 leftMotorOutput = moveValue - rotateValue; 00420 rightMotorOutput = max(moveValue, rotateValue); 00421 } 00422 else 00423 { 00424 leftMotorOutput = max(moveValue, -rotateValue); 00425 rightMotorOutput = moveValue + rotateValue; 00426 } 00427 } 00428 else 00429 { 00430 if (rotateValue > 0.0) 00431 { 00432 leftMotorOutput = - max(-moveValue, rotateValue); 00433 rightMotorOutput = moveValue + rotateValue; 00434 } 00435 else 00436 { 00437 leftMotorOutput = moveValue - rotateValue; 00438 rightMotorOutput = - max(-moveValue, -rotateValue); 00439 } 00440 } 00441 SetLeftRightMotorOutputs(leftMotorOutput, rightMotorOutput); 00442 } 00443 00460 void RobotDrive::MecanumDrive_Cartesian(float x, float y, float rotation, float gyroAngle) 00461 { 00462 double xIn = x; 00463 double yIn = y; 00464 // Negate y for the joystick. 00465 yIn = -yIn; 00466 // Compenstate for gyro angle. 00467 RotateVector(xIn, yIn, gyroAngle); 00468 00469 double wheelSpeeds[kMaxNumberOfMotors]; 00470 wheelSpeeds[kFrontLeftMotor] = xIn + yIn + rotation; 00471 wheelSpeeds[kFrontRightMotor] = -xIn + yIn - rotation; 00472 wheelSpeeds[kRearLeftMotor] = -xIn + yIn + rotation; 00473 wheelSpeeds[kRearRightMotor] = xIn + yIn - rotation; 00474 00475 Normalize(wheelSpeeds); 00476 00477 UINT8 syncGroup = 0x80; 00478 00479 m_frontLeftMotor->Set(wheelSpeeds[kFrontLeftMotor] * m_invertedMotors[kFrontLeftMotor] * m_maxOutput, syncGroup); 00480 m_frontRightMotor->Set(wheelSpeeds[kFrontRightMotor] * m_invertedMotors[kFrontRightMotor] * m_maxOutput, syncGroup); 00481 m_rearLeftMotor->Set(wheelSpeeds[kRearLeftMotor] * m_invertedMotors[kRearLeftMotor] * m_maxOutput, syncGroup); 00482 m_rearRightMotor->Set(wheelSpeeds[kRearRightMotor] * m_invertedMotors[kRearRightMotor] * m_maxOutput, syncGroup); 00483 00484 CANJaguar::UpdateSyncGroup(syncGroup); 00485 00486 m_safetyHelper->Feed(); 00487 } 00488 00502 void RobotDrive::MecanumDrive_Polar(float magnitude, float direction, float rotation) 00503 { 00504 // Normalized for full power along the Cartesian axes. 00505 magnitude = Limit(magnitude) * sqrt(2.0); 00506 // The rollers are at 45 degree angles. 00507 double dirInRad = (direction + 45.0) * 3.14159 / 180.0; 00508 double cosD = cos(dirInRad); 00509 double sinD = sin(dirInRad); 00510 00511 double wheelSpeeds[kMaxNumberOfMotors]; 00512 wheelSpeeds[kFrontLeftMotor] = sinD * magnitude + rotation; 00513 wheelSpeeds[kFrontRightMotor] = cosD * magnitude - rotation; 00514 wheelSpeeds[kRearLeftMotor] = cosD * magnitude + rotation; 00515 wheelSpeeds[kRearRightMotor] = sinD * magnitude - rotation; 00516 00517 Normalize(wheelSpeeds); 00518 00519 UINT8 syncGroup = 0x80; 00520 00521 m_frontLeftMotor->Set(wheelSpeeds[kFrontLeftMotor] * m_invertedMotors[kFrontLeftMotor] * m_maxOutput, syncGroup); 00522 m_frontRightMotor->Set(wheelSpeeds[kFrontRightMotor] * m_invertedMotors[kFrontRightMotor] * m_maxOutput, syncGroup); 00523 m_rearLeftMotor->Set(wheelSpeeds[kRearLeftMotor] * m_invertedMotors[kRearLeftMotor] * m_maxOutput, syncGroup); 00524 m_rearRightMotor->Set(wheelSpeeds[kRearRightMotor] * m_invertedMotors[kRearRightMotor] * m_maxOutput, syncGroup); 00525 00526 CANJaguar::UpdateSyncGroup(syncGroup); 00527 00528 m_safetyHelper->Feed(); 00529 } 00530 00542 void RobotDrive::HolonomicDrive(float magnitude, float direction, float rotation) 00543 { 00544 MecanumDrive_Polar(magnitude, direction, rotation); 00545 } 00546 00554 void RobotDrive::SetLeftRightMotorOutputs(float leftOutput, float rightOutput) 00555 { 00556 wpi_assert(m_rearLeftMotor != NULL && m_rearRightMotor != NULL); 00557 00558 UINT8 syncGroup = 0x80; 00559 00560 if (m_frontLeftMotor != NULL) 00561 m_frontLeftMotor->Set(Limit(leftOutput) * m_invertedMotors[kFrontLeftMotor] * m_maxOutput, syncGroup); 00562 m_rearLeftMotor->Set(Limit(leftOutput) * m_invertedMotors[kRearLeftMotor] * m_maxOutput, syncGroup); 00563 00564 if (m_frontRightMotor != NULL) 00565 m_frontRightMotor->Set(-Limit(rightOutput) * m_invertedMotors[kFrontRightMotor] * m_maxOutput, syncGroup); 00566 m_rearRightMotor->Set(-Limit(rightOutput) * m_invertedMotors[kRearRightMotor] * m_maxOutput, syncGroup); 00567 00568 CANJaguar::UpdateSyncGroup(syncGroup); 00569 00570 m_safetyHelper->Feed(); 00571 } 00572 00576 float RobotDrive::Limit(float num) 00577 { 00578 if (num > 1.0) 00579 { 00580 return 1.0; 00581 } 00582 if (num < -1.0) 00583 { 00584 return -1.0; 00585 } 00586 return num; 00587 } 00588 00592 void RobotDrive::Normalize(double *wheelSpeeds) 00593 { 00594 double maxMagnitude = fabs(wheelSpeeds[0]); 00595 INT32 i; 00596 for (i=1; i<kMaxNumberOfMotors; i++) 00597 { 00598 double temp = fabs(wheelSpeeds[i]); 00599 if (maxMagnitude < temp) maxMagnitude = temp; 00600 } 00601 if (maxMagnitude > 1.0) 00602 { 00603 for (i=0; i<kMaxNumberOfMotors; i++) 00604 { 00605 wheelSpeeds[i] = wheelSpeeds[i] / maxMagnitude; 00606 } 00607 } 00608 } 00609 00613 void RobotDrive::RotateVector(double &x, double &y, double angle) 00614 { 00615 double cosA = cos(angle * (3.14159 / 180.0)); 00616 double sinA = sin(angle * (3.14159 / 180.0)); 00617 double xOut = x * cosA - y * sinA; 00618 double yOut = x * sinA + y * cosA; 00619 x = xOut; 00620 y = yOut; 00621 } 00622 00623 /* 00624 * Invert a motor direction. 00625 * This is used when a motor should run in the opposite direction as the drive 00626 * code would normally run it. Motors that are direct drive would be inverted, the 00627 * Drive code assumes that the motors are geared with one reversal. 00628 * @param motor The motor index to invert. 00629 * @param isInverted True if the motor should be inverted when operated. 00630 */ 00631 void RobotDrive::SetInvertedMotor(MotorType motor, bool isInverted) 00632 { 00633 if (motor < 0 || motor > 3) 00634 { 00635 wpi_setWPIError(InvalidMotorIndex); 00636 return; 00637 } 00638 m_invertedMotors[motor] = isInverted ? -1 : 1; 00639 } 00640 00647 void RobotDrive::SetSensitivity(float sensitivity) 00648 { 00649 m_sensitivity = sensitivity; 00650 } 00651 00656 void RobotDrive::SetMaxOutput(double maxOutput) 00657 { 00658 m_maxOutput = maxOutput; 00659 } 00660 00661 00662 00663 void RobotDrive::SetExpiration(float timeout) 00664 { 00665 m_safetyHelper->SetExpiration(timeout); 00666 } 00667 00668 float RobotDrive::GetExpiration() 00669 { 00670 return m_safetyHelper->GetExpiration(); 00671 } 00672 00673 bool RobotDrive::IsAlive() 00674 { 00675 return m_safetyHelper->IsAlive(); 00676 } 00677 00678 bool RobotDrive::IsSafetyEnabled() 00679 { 00680 return m_safetyHelper->IsSafetyEnabled(); 00681 } 00682 00683 void RobotDrive::SetSafetyEnabled(bool enabled) 00684 { 00685 m_safetyHelper->SetSafetyEnabled(enabled); 00686 } 00687 00688 void RobotDrive::GetDescription(char *desc) 00689 { 00690 sprintf(desc, "RobotDrive"); 00691 } 00692 00693 void RobotDrive::StopMotor() 00694 { 00695 if (m_frontLeftMotor != NULL) m_frontLeftMotor->Disable(); 00696 if (m_frontRightMotor != NULL) m_frontRightMotor->Disable(); 00697 if (m_rearLeftMotor != NULL) m_rearLeftMotor->Disable(); 00698 if (m_rearRightMotor != NULL) m_rearRightMotor->Disable(); 00699 }
Generated on Thu Jan 12 2012 22:35:23 for WPILibC++ by
1.7.1