amiro-os / components / DistControl.cpp @ 4270bbde
History | View | Annotate | Download (5.958 KB)
| 1 |
#include <ch.hpp> |
|---|---|
| 2 |
#include <hal.h> |
| 3 |
|
| 4 |
#include <qei.h> |
| 5 |
|
| 6 |
#include <amiro/DistControl.h> |
| 7 |
|
| 8 |
#include <global.hpp> |
| 9 |
|
| 10 |
using namespace chibios_rt; |
| 11 |
using namespace amiro; |
| 12 |
using namespace types; |
| 13 |
using namespace constants; |
| 14 |
using namespace constants::DiWheelDrive; |
| 15 |
|
| 16 |
extern Global global;
|
| 17 |
|
| 18 |
DistControl::DistControl(MotorControl* mc, MotorIncrements* mi) |
| 19 |
: BaseStaticThread<256>(),
|
| 20 |
motorControl(mc), |
| 21 |
motorIncrements(mi), |
| 22 |
period(10)
|
| 23 |
{
|
| 24 |
|
| 25 |
// initialize velocities
|
| 26 |
this->maxVelocity.y = 0; |
| 27 |
this->maxVelocity.z = 0; |
| 28 |
this->maxVelocity.w_x = 0; |
| 29 |
this->maxVelocity.w_y = 0; |
| 30 |
this->targetVelocity.x = 0; |
| 31 |
this->targetVelocity.y = 0; |
| 32 |
this->targetVelocity.z = 0; |
| 33 |
this->targetVelocity.w_x = 0; |
| 34 |
this->targetVelocity.w_y = 0; |
| 35 |
this->targetVelocity.w_z = 0; |
| 36 |
this->minVelocity.y = 0; |
| 37 |
this->minVelocity.z = 0; |
| 38 |
this->minVelocity.w_x = 0; |
| 39 |
this->minVelocity.w_y = 0; |
| 40 |
this->minVelocity.w_z = 0; |
| 41 |
|
| 42 |
// set max and min velocities
|
| 43 |
this->maxVelocity.x = 0.15 * 1e6; // 15 cm/s |
| 44 |
this->minVelocity.x = 0.02 * 1e6; // 2 cm/s |
| 45 |
this->maxVelocity.w_z = 2*maxVelocity.x / MotorControl::actualWheelBaseDistanceSI; |
| 46 |
this->minVelocity.w_z = 2*minVelocity.x / MotorControl::actualWheelBaseDistanceSI; |
| 47 |
} |
| 48 |
|
| 49 |
int DistControl::getCurrentTargetDist() {
|
| 50 |
return (int)(targetDistance*1e6); |
| 51 |
} |
| 52 |
|
| 53 |
int DistControl::getCurrentTargetAngle() {
|
| 54 |
return (int)(targetAngle*1e6); |
| 55 |
} |
| 56 |
|
| 57 |
void DistControl::setTargetPosition(int32_t distance, int32_t angle, uint16_t time) {
|
| 58 |
chSysLock(); |
| 59 |
targetDistance = distance; // um
|
| 60 |
drivingForward = distance > 0;
|
| 61 |
if (!drivingForward) {
|
| 62 |
targetDistance *= -1;
|
| 63 |
} |
| 64 |
targetAngle = angle; // urad
|
| 65 |
turningLeft = angle > 0;
|
| 66 |
if (!turningLeft) {
|
| 67 |
targetAngle *= -1;
|
| 68 |
} |
| 69 |
restTime = time * 1e3; // us |
| 70 |
controllerActive = true;
|
| 71 |
chSysUnlock(); |
| 72 |
fullDistance[LEFT_WHEEL] = 0;
|
| 73 |
fullDistance[RIGHT_WHEEL] = 0;
|
| 74 |
motorControl->updateIncrements(motorIncrements, increment, incrementDifference); |
| 75 |
} |
| 76 |
|
| 77 |
bool DistControl::isActive(void) { |
| 78 |
return controllerActive;
|
| 79 |
} |
| 80 |
|
| 81 |
void DistControl::deactivateController(void) { |
| 82 |
chSysLock(); |
| 83 |
controllerActive = false;
|
| 84 |
targetDistance = 0;
|
| 85 |
targetAngle = 0;
|
| 86 |
restTime = 0;
|
| 87 |
for (int idx=0; idx < 2; idx++) { |
| 88 |
increment[idx] = 0;
|
| 89 |
incrementDifference[idx] = 0;
|
| 90 |
actualDistance[idx] = 0;
|
| 91 |
fullDistance[idx] = 0;
|
| 92 |
} |
| 93 |
chSysUnlock(); |
| 94 |
} |
| 95 |
|
| 96 |
msg_t DistControl::main(void) {
|
| 97 |
systime_t time = System::getTime(); |
| 98 |
systime_t printTime = time; |
| 99 |
this->setName("DistControl"); |
| 100 |
|
| 101 |
DistControl::deactivateController(); |
| 102 |
|
| 103 |
while (!this->shouldTerminate()) { |
| 104 |
time += MS2ST(this->period);
|
| 105 |
|
| 106 |
if (controllerActive) {
|
| 107 |
// get increment differences for each wheel
|
| 108 |
motorControl->updateIncrements(motorIncrements, increment, incrementDifference); // ticks
|
| 109 |
|
| 110 |
// calculate driven distance difference for each wheel
|
| 111 |
motorControl->updateDistance(incrementDifference, actualDistance); // m
|
| 112 |
|
| 113 |
// calculate full driven distance for each wheel
|
| 114 |
for (int idxWheel = 0; idxWheel < 2; idxWheel++) { |
| 115 |
fullDistance[idxWheel] += (int32_t)(actualDistance[idxWheel]*1e6);
|
| 116 |
} |
| 117 |
|
| 118 |
// calculate whole driven distance and angle
|
| 119 |
realDistance = (fullDistance[LEFT_WHEEL] + fullDistance[RIGHT_WHEEL]) / 2.0; // um |
| 120 |
if (!drivingForward) {
|
| 121 |
realDistance *= -1;
|
| 122 |
} |
| 123 |
realAngle = (fullDistance[RIGHT_WHEEL] - fullDistance[LEFT_WHEEL]) / MotorControl::actualWheelBaseDistanceSI; // urad
|
| 124 |
if (!turningLeft) {
|
| 125 |
realAngle *= -1;
|
| 126 |
} |
| 127 |
|
| 128 |
// calculate distance and angle to drive
|
| 129 |
errorDistance = targetDistance - realDistance; // um
|
| 130 |
if (errorDistance < 0) { |
| 131 |
errorDistance = 0;
|
| 132 |
} |
| 133 |
errorAngle = targetAngle - realAngle; // urad
|
| 134 |
if (errorAngle < 0) { |
| 135 |
errorAngle = 0;
|
| 136 |
} |
| 137 |
|
| 138 |
// calculate velocities for motor control
|
| 139 |
DistControl::calcVelocities(); |
| 140 |
|
| 141 |
if (controllerActive && newVelocities) {
|
| 142 |
// set target velocities
|
| 143 |
this->motorControl->setTargetSpeed(targetVelocity);
|
| 144 |
newVelocities = false;
|
| 145 |
} |
| 146 |
|
| 147 |
/*
|
| 148 |
if (time-printTime > MS2ST(100)) {
|
| 149 |
chprintf((BaseSequentialStream*) &global.sercanmux1, "dist = %i um, angle = %i urad, ed = %i um, ea = %i, v = %i um/s, w = %i urad/s\n", realDistance, realAngle, errorDistance, errorAngle, targetVelocity.x, targetVelocity.w_z);
|
| 150 |
printTime = time;
|
| 151 |
}
|
| 152 |
*/
|
| 153 |
|
| 154 |
// reduce rest time (us)
|
| 155 |
restTime -= period*1e3;
|
| 156 |
if (restTime < 1) { |
| 157 |
restTime = 1;
|
| 158 |
} |
| 159 |
|
| 160 |
// deactivate controller if necessary
|
| 161 |
if (errorDistance == 0 && errorAngle == 0) { |
| 162 |
deactivateController(); |
| 163 |
} |
| 164 |
|
| 165 |
} |
| 166 |
|
| 167 |
chThdSleepUntil(time); |
| 168 |
} |
| 169 |
|
| 170 |
return true; |
| 171 |
} |
| 172 |
|
| 173 |
void DistControl::calcVelocities(void) { |
| 174 |
// TODO calculate target velocities better
|
| 175 |
|
| 176 |
// set intuitive velocities
|
| 177 |
int32_t forwardSpeed = (int32_t) (errorDistance * 1e6 / (1.0f*restTime)); // um/s |
| 178 |
int32_t angleSpeed = (int32_t) (errorAngle * 1e6 / (1.0f*restTime)); // urad/s |
| 179 |
|
| 180 |
int32_t maxForward = maxVelocity.x; |
| 181 |
if (maxForward > errorDistance) {
|
| 182 |
maxForward = errorDistance; |
| 183 |
} |
| 184 |
|
| 185 |
int32_t maxTurn = maxVelocity.w_z; |
| 186 |
if (maxTurn > errorAngle) {
|
| 187 |
maxTurn = errorAngle; |
| 188 |
} |
| 189 |
|
| 190 |
// check max forward speed
|
| 191 |
if (forwardSpeed > maxForward) {
|
| 192 |
forwardSpeed = maxForward; |
| 193 |
angleSpeed = (int32_t) (forwardSpeed * ((1.0f*errorAngle) / (1.0f*errorDistance))); |
| 194 |
} |
| 195 |
|
| 196 |
// check max angle speed
|
| 197 |
if (angleSpeed > maxTurn) {
|
| 198 |
angleSpeed = maxTurn; |
| 199 |
forwardSpeed = (int32_t) (angleSpeed * ((1.0f*errorDistance) / (1.0f*errorAngle))); |
| 200 |
} |
| 201 |
|
| 202 |
// check for too small speeds
|
| 203 |
if (errorDistance > 0 && forwardSpeed < minVelocity.x) { |
| 204 |
forwardSpeed = minVelocity.x; |
| 205 |
} |
| 206 |
if (errorAngle > 0 && errorDistance == 0 && angleSpeed < minVelocity.w_z) { |
| 207 |
angleSpeed = minVelocity.w_z; |
| 208 |
} |
| 209 |
|
| 210 |
// set velocity directions
|
| 211 |
if (!drivingForward) {
|
| 212 |
forwardSpeed *= -1;
|
| 213 |
} |
| 214 |
if (!turningLeft) {
|
| 215 |
angleSpeed *= -1;
|
| 216 |
} |
| 217 |
|
| 218 |
// if nessecary set new target velocities
|
| 219 |
if (forwardSpeed != targetVelocity.x || angleSpeed != targetVelocity.w_z) {
|
| 220 |
newVelocities = true;
|
| 221 |
targetVelocity.x = forwardSpeed; |
| 222 |
targetVelocity.w_z = angleSpeed; |
| 223 |
} |
| 224 |
} |