robot code for summer school
Dependencies: PM2_Libary Eigen
Fork of PM2_Example_Summer_School by
Robot_Library/robot.cpp@59:f2d7ef0db12b, 2022-05-30 (annotated)
- Committer:
- eversonrosed
- Date:
- Mon May 30 09:10:01 2022 +0200
- Revision:
- 59:f2d7ef0db12b
- Parent:
- 58:c9a55b0c3121
- Child:
- 60:85a40e69ced6
delete ToBinary
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
seas726 | 49:7da71f479dac | 1 | #include "robot.h" |
seas726 | 49:7da71f479dac | 2 | #include "EncoderCounter.h" |
seas726 | 49:7da71f479dac | 3 | #include "PeripheralNames.h" |
seas726 | 49:7da71f479dac | 4 | #include "PinNames.h" |
seas726 | 56:3fce0a9bb6df | 5 | #include <cstdint> |
seas726 | 49:7da71f479dac | 6 | #include <cstdio> |
seas726 | 49:7da71f479dac | 7 | |
seas726 | 56:3fce0a9bb6df | 8 | |
eversonrosed | 58:c9a55b0c3121 | 9 | Robot::Robot() : dist(PB_1), // initialize all of the physical ports |
seas726 | 49:7da71f479dac | 10 | bit0(PH_1), |
seas726 | 49:7da71f479dac | 11 | bit1(PC_2), |
seas726 | 49:7da71f479dac | 12 | bit2(PC_3), |
eversonrosed | 58:c9a55b0c3121 | 13 | ir_sensor_0(dist, bit0, bit1, bit2, 0), // one IR sensor |
seas726 | 56:3fce0a9bb6df | 14 | i2c2(PB_9, PB_8), // line sensor |
seas726 | 49:7da71f479dac | 15 | line_sensor(i2c2), |
eversonrosed | 58:c9a55b0c3121 | 16 | pwm_M1(PA_9), // motors + encoders |
seas726 | 49:7da71f479dac | 17 | pwm_M2(PA_8), |
seas726 | 49:7da71f479dac | 18 | encoder_M1(PA_6, PC_7), |
seas726 | 49:7da71f479dac | 19 | encoder_M2(PB_6,PB_7) |
seas726 | 49:7da71f479dac | 20 | { |
seas726 | 49:7da71f479dac | 21 | // initialize all variables |
seas726 | 49:7da71f479dac | 22 | wheel_to_robot << -WHEEL_RADIUS / 2.0f, WHEEL_RADIUS / 2.0f, |
eversonrosed | 58:c9a55b0c3121 | 23 | -WHEEL_RADIUS / DISTANCE_BETWEEN_WHEELS, -WHEEL_RADIUS / DISTANCE_BETWEEN_WHEELS; // transformation matrix |
seas726 | 49:7da71f479dac | 24 | robot_to_wheel = wheel_to_robot.inverse(); |
seas726 | 49:7da71f479dac | 25 | |
eversonrosed | 58:c9a55b0c3121 | 26 | robot_speed_desired.setZero(); // zero out all speeds |
seas726 | 49:7da71f479dac | 27 | wheel_speed_desired.setZero(); |
seas726 | 49:7da71f479dac | 28 | wheel_speed_smooth.setZero(); |
seas726 | 49:7da71f479dac | 29 | robot_speed_actual.setZero(); |
seas726 | 49:7da71f479dac | 30 | wheel_speed_actual.setZero(); |
seas726 | 49:7da71f479dac | 31 | |
seas726 | 49:7da71f479dac | 32 | // MOTORS + MOTION |
seas726 | 49:7da71f479dac | 33 | |
seas726 | 49:7da71f479dac | 34 | // TRAJECTORY PLANNERS |
seas726 | 49:7da71f479dac | 35 | trajectoryPlanners[0] = new Motion(); |
seas726 | 49:7da71f479dac | 36 | trajectoryPlanners[1] = new Motion(); |
seas726 | 49:7da71f479dac | 37 | |
seas726 | 49:7da71f479dac | 38 | trajectoryPlanners[0]->setProfileVelocity(MAX_MOTOR_VOLTAGE * KN / 60.0f); |
seas726 | 49:7da71f479dac | 39 | trajectoryPlanners[1]->setProfileVelocity(MAX_MOTOR_VOLTAGE * KN / 60.0f); |
seas726 | 49:7da71f479dac | 40 | trajectoryPlanners[0]->setProfileAcceleration(10.0f); |
seas726 | 49:7da71f479dac | 41 | trajectoryPlanners[1]->setProfileAcceleration(10.0f); |
seas726 | 49:7da71f479dac | 42 | trajectoryPlanners[0]->setProfileDeceleration(10.0f); |
seas726 | 49:7da71f479dac | 43 | trajectoryPlanners[1]->setProfileDeceleration(10.0f); |
seas726 | 49:7da71f479dac | 44 | |
seas726 | 49:7da71f479dac | 45 | // SPEED CONTROLLERS |
seas726 | 49:7da71f479dac | 46 | speedControllers[0] = new SpeedController(COUNTS_PER_TURN, KN, MAX_MOTOR_VOLTAGE, pwm_M1, encoder_M1); |
seas726 | 49:7da71f479dac | 47 | speedControllers[1] = new SpeedController(COUNTS_PER_TURN, KN, MAX_MOTOR_VOLTAGE, pwm_M2, encoder_M2); |
seas726 | 49:7da71f479dac | 48 | |
eversonrosed | 58:c9a55b0c3121 | 49 | speedControllers[0]->setSpeedCntrlGain(0.04f); // adjust speed controller gains |
seas726 | 49:7da71f479dac | 50 | speedControllers[1]->setSpeedCntrlGain(0.04f); |
seas726 | 49:7da71f479dac | 51 | speedControllers[0]->setMaxAccelerationRPS(999.0f); // adjust max. acceleration for smooth movement |
seas726 | 49:7da71f479dac | 52 | speedControllers[1]->setMaxAccelerationRPS(999.0f); |
seas726 | 49:7da71f479dac | 53 | |
seas726 | 49:7da71f479dac | 54 | } |
seas726 | 49:7da71f479dac | 55 | |
eversonrosed | 54:b442660523df | 56 | Robot::~Robot() |
eversonrosed | 54:b442660523df | 57 | { |
eversonrosed | 54:b442660523df | 58 | delete trajectoryPlanners[0]; |
eversonrosed | 54:b442660523df | 59 | delete trajectoryPlanners[1]; |
eversonrosed | 54:b442660523df | 60 | delete speedControllers[0]; |
eversonrosed | 54:b442660523df | 61 | delete speedControllers[1]; |
eversonrosed | 54:b442660523df | 62 | } |
eversonrosed | 54:b442660523df | 63 | |
seas726 | 49:7da71f479dac | 64 | void Robot::Update() { |
seas726 | 49:7da71f479dac | 65 | |
seas726 | 49:7da71f479dac | 66 | controller.Update(); |
seas726 | 49:7da71f479dac | 67 | |
seas726 | 49:7da71f479dac | 68 | printf("STATE: %d \r\n", state); |
seas726 | 49:7da71f479dac | 69 | switch (state) { |
seas726 | 49:7da71f479dac | 70 | case INITIAL: |
seas726 | 49:7da71f479dac | 71 | Initial(); |
seas726 | 49:7da71f479dac | 72 | break; |
seas726 | 49:7da71f479dac | 73 | case IDLE: |
seas726 | 49:7da71f479dac | 74 | Idle(); |
seas726 | 49:7da71f479dac | 75 | break; |
seas726 | 49:7da71f479dac | 76 | case FOLLOWING_LINE: |
seas726 | 49:7da71f479dac | 77 | FollowingLine(); |
seas726 | 49:7da71f479dac | 78 | break; |
seas726 | 49:7da71f479dac | 79 | case RIGHT_TURN_90: |
seas726 | 56:3fce0a9bb6df | 80 | RightTurn_90(); |
seas726 | 49:7da71f479dac | 81 | break; |
seas726 | 49:7da71f479dac | 82 | case LEFT_TURN_90: |
seas726 | 56:3fce0a9bb6df | 83 | LeftTurn_90(); |
seas726 | 49:7da71f479dac | 84 | break; |
seas726 | 49:7da71f479dac | 85 | default: state = IDLE; // on default, stop the car |
seas726 | 49:7da71f479dac | 86 | } |
seas726 | 49:7da71f479dac | 87 | } |
seas726 | 49:7da71f479dac | 88 | |
seas726 | 49:7da71f479dac | 89 | void Robot::Initial() |
seas726 | 49:7da71f479dac | 90 | { |
seas726 | 49:7da71f479dac | 91 | printf("Initial State\n"); // TODO: REMOVE PRINT |
seas726 | 49:7da71f479dac | 92 | // initialize the robot. |
seas726 | 49:7da71f479dac | 93 | // enable_motors = 1; |
seas726 | 49:7da71f479dac | 94 | // motors_enabled = false; |
seas726 | 49:7da71f479dac | 95 | robot_speed_desired(0) = 0.0f; // set speed and rotational velocity to zero |
seas726 | 49:7da71f479dac | 96 | robot_speed_desired(1) = 0.0f; |
seas726 | 49:7da71f479dac | 97 | |
seas726 | 49:7da71f479dac | 98 | if(controller.GetTurnedOn()) // check to see if blue button is toggled |
seas726 | 49:7da71f479dac | 99 | { |
seas726 | 49:7da71f479dac | 100 | state = FOLLOWING_LINE; |
seas726 | 49:7da71f479dac | 101 | } |
seas726 | 49:7da71f479dac | 102 | } |
seas726 | 49:7da71f479dac | 103 | |
seas726 | 49:7da71f479dac | 104 | void Robot::Idle() |
seas726 | 49:7da71f479dac | 105 | { |
seas726 | 49:7da71f479dac | 106 | printf("Idle\n"); // TODO: REMOVE PRINT |
seas726 | 49:7da71f479dac | 107 | robot_speed_desired(0) = 0.0f; // set speed and rotational velocity to zero |
seas726 | 49:7da71f479dac | 108 | robot_speed_desired(1) = 0.0f; |
seas726 | 49:7da71f479dac | 109 | } |
seas726 | 49:7da71f479dac | 110 | |
seas726 | 56:3fce0a9bb6df | 111 | void Robot::FollowingLine() // Updates once per cycle. |
seas726 | 49:7da71f479dac | 112 | { |
seas726 | 56:3fce0a9bb6df | 113 | if(!controller.GetTurnedOn()) |
seas726 | 56:3fce0a9bb6df | 114 | { |
seas726 | 56:3fce0a9bb6df | 115 | state = IDLE; |
seas726 | 56:3fce0a9bb6df | 116 | return; |
seas726 | 56:3fce0a9bb6df | 117 | } |
seas726 | 56:3fce0a9bb6df | 118 | |
seas726 | 49:7da71f479dac | 119 | printf("FollowingLine\n"); // TODO: REMOVE PRINT |
seas726 | 56:3fce0a9bb6df | 120 | printf("%d", line_sensor.getRaw()); // print raw line sensor data |
eversonrosed | 59:f2d7ef0db12b | 121 | uint8_t binary_sensor_data = line_sensor.getRaw(); // convert line sensor data into binary representation of it |
seas726 | 56:3fce0a9bb6df | 122 | |
seas726 | 56:3fce0a9bb6df | 123 | // if(IsSharpTurn(binary_sensor_data)) { return; } // check if the sensor reads in any sharp turns. if so, exit the PID movement and turn sharply. |
seas726 | 56:3fce0a9bb6df | 124 | // first test PID movement. it is possible that PID movement works just as well. |
seas726 | 56:3fce0a9bb6df | 125 | |
seas726 | 56:3fce0a9bb6df | 126 | PID_Move(binary_sensor_data); // move the robot smoothly with error calculation and stuff? |
seas726 | 56:3fce0a9bb6df | 127 | } |
seas726 | 56:3fce0a9bb6df | 128 | |
seas726 | 56:3fce0a9bb6df | 129 | void Robot::RightTurn_90() |
seas726 | 56:3fce0a9bb6df | 130 | { |
seas726 | 56:3fce0a9bb6df | 131 | // count encoder values and turn until the motor has rotated ~ 90 degrees |
seas726 | 56:3fce0a9bb6df | 132 | // im actually not sure if we need this, try testing with just the PID system first |
seas726 | 56:3fce0a9bb6df | 133 | } |
seas726 | 56:3fce0a9bb6df | 134 | |
seas726 | 56:3fce0a9bb6df | 135 | void Robot::LeftTurn_90() |
seas726 | 56:3fce0a9bb6df | 136 | { |
seas726 | 56:3fce0a9bb6df | 137 | // count encoder values and turn until the motor has rotated ~ 90 degrees |
seas726 | 56:3fce0a9bb6df | 138 | // im actually not sure if we need this, try testing with just the PID system first |
seas726 | 56:3fce0a9bb6df | 139 | } |
seas726 | 56:3fce0a9bb6df | 140 | |
seas726 | 56:3fce0a9bb6df | 141 | void Robot::PID_Move (std::uint8_t s_binary) // for following smooth lines ONLY |
seas726 | 56:3fce0a9bb6df | 142 | { |
seas726 | 56:3fce0a9bb6df | 143 | |
seas726 | 56:3fce0a9bb6df | 144 | int errval = 0; |
seas726 | 56:3fce0a9bb6df | 145 | |
seas726 | 56:3fce0a9bb6df | 146 | if (s_binary&0b00000001) |
seas726 | 56:3fce0a9bb6df | 147 | errval += 3; |
seas726 | 56:3fce0a9bb6df | 148 | else if (s_binary&0b00000010) |
seas726 | 56:3fce0a9bb6df | 149 | errval += 2; |
seas726 | 56:3fce0a9bb6df | 150 | else if (s_binary&0b00000100) |
seas726 | 56:3fce0a9bb6df | 151 | errval += 1; |
seas726 | 56:3fce0a9bb6df | 152 | else if (s_binary&0b00001000) |
seas726 | 56:3fce0a9bb6df | 153 | errval += 0; |
seas726 | 56:3fce0a9bb6df | 154 | |
seas726 | 56:3fce0a9bb6df | 155 | if (s_binary&0b10000000) |
seas726 | 56:3fce0a9bb6df | 156 | errval -= 3; |
seas726 | 56:3fce0a9bb6df | 157 | else if (s_binary&0b01000000) |
seas726 | 56:3fce0a9bb6df | 158 | errval -= 2; |
seas726 | 56:3fce0a9bb6df | 159 | else if (s_binary&0b00100000) |
seas726 | 56:3fce0a9bb6df | 160 | errval -= 1; |
seas726 | 56:3fce0a9bb6df | 161 | else if (s_binary&0b00010000) |
seas726 | 56:3fce0a9bb6df | 162 | errval -= 0; |
seas726 | 49:7da71f479dac | 163 | |
seas726 | 56:3fce0a9bb6df | 164 | int principle_error = kP * errval; |
eversonrosed | 58:c9a55b0c3121 | 165 | integral_error = kI * (integral_error + errval); |
seas726 | 56:3fce0a9bb6df | 166 | int derivative_error = kD * (errval - previous_error_value); |
seas726 | 56:3fce0a9bb6df | 167 | |
eversonrosed | 58:c9a55b0c3121 | 168 | int total_error = (principle_error + integral_error + derivative_error) / 10; // TODO: find out why we divide by 10 |
seas726 | 49:7da71f479dac | 169 | |
seas726 | 56:3fce0a9bb6df | 170 | if(total_error > 0) |
seas726 | 56:3fce0a9bb6df | 171 | { // call this every frame until it does not need it? set rotational velocity relative to the calculated error? |
seas726 | 56:3fce0a9bb6df | 172 | // go slightly right |
seas726 | 56:3fce0a9bb6df | 173 | robot_speed_desired(0) = TRANSLATIONAL_VELOCITY; // forward velocity |
eversonrosed | 58:c9a55b0c3121 | 174 | robot_speed_desired(1) = ROTATIONAL_VELOCITY; // rotational velocity |
seas726 | 56:3fce0a9bb6df | 175 | } |
seas726 | 56:3fce0a9bb6df | 176 | else if(total_error < 0) |
seas726 | 56:3fce0a9bb6df | 177 | { |
seas726 | 56:3fce0a9bb6df | 178 | // go slightly left |
seas726 | 56:3fce0a9bb6df | 179 | robot_speed_desired(0) = TRANSLATIONAL_VELOCITY; // forward velocity |
eversonrosed | 58:c9a55b0c3121 | 180 | robot_speed_desired(1) = -ROTATIONAL_VELOCITY; // rotational velocity |
seas726 | 56:3fce0a9bb6df | 181 | } |
seas726 | 56:3fce0a9bb6df | 182 | else |
seas726 | 56:3fce0a9bb6df | 183 | { |
seas726 | 56:3fce0a9bb6df | 184 | robot_speed_desired(0) = TRANSLATIONAL_VELOCITY; // forward velocity |
eversonrosed | 58:c9a55b0c3121 | 185 | robot_speed_desired(1) = 0.0f; // rotational velocity |
seas726 | 56:3fce0a9bb6df | 186 | } |
seas726 | 49:7da71f479dac | 187 | |
seas726 | 56:3fce0a9bb6df | 188 | // Delay total_error/2. not exactly sure why. |
seas726 | 56:3fce0a9bb6df | 189 | } |
seas726 | 56:3fce0a9bb6df | 190 | |
seas726 | 56:3fce0a9bb6df | 191 | bool Robot::IsSharpTurn(int binary_sensor_data) |
seas726 | 56:3fce0a9bb6df | 192 | { |
seas726 | 56:3fce0a9bb6df | 193 | return binary_sensor_data&0b11110000 || binary_sensor_data&0b00001111; |
seas726 | 56:3fce0a9bb6df | 194 | } |
seas726 | 56:3fce0a9bb6df | 195 | |
seas726 | 56:3fce0a9bb6df | 196 | void Robot::PID_Delay(int ms) |
seas726 | 56:3fce0a9bb6df | 197 | { |
seas726 | 56:3fce0a9bb6df | 198 | // add in delay ? |
eversonrosed | 58:c9a55b0c3121 | 199 | // implement |
seas726 | 56:3fce0a9bb6df | 200 | } |