Statistics
| Branch: | Tag: | Revision:

amiro-os / components / DistControl.cpp @ 58fe0e0b

History | View | Annotate | Download (5.899 KB)

1 58fe0e0b Thomas Schöpping
#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
}