Statistics
| Branch: | Tag: | Revision:

amiro-os / components / DistControl.cpp @ f8cf404d

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
}