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