amiro-os / components / DistControl.cpp @ b8b3a9c9
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 |
} |