Statistics
| Branch: | Tag: | Revision:

amiro-os / devices / DiWheelDrive / userthread.cpp @ d02c536e

History | View | Annotate | Download (35.063 KB)

1 d4c6efa9 galberding
#include "userthread.hpp"
2 e404e6c0 galberding
#include "amiro_map.hpp"
3 d02c536e galberding
#include "global.hpp"
4
#include "linefollow.hpp"
5 e404e6c0 galberding
6 58fe0e0b Thomas Schöpping
using namespace amiro;
7
8
extern Global global;
9
10
// a buffer for the z-value of the accelerometer
11
int16_t accel_z;
12 5d138bca galberding
bool running = false;
13 58fe0e0b Thomas Schöpping
14
15 181f2892 galberding
/**
16
 * Set speed.
17 8dced1c9 galberding
 *
18 181f2892 galberding
 * @param rpmSpeed speed for left and right wheel in rounds/min
19
 */
20 c9fa414d galberding
void UserThread::setRpmSpeedFuzzy(const int (&rpmSpeed)[2]) {
21 5d138bca galberding
  global.motorcontrol.setTargetRPM(rpmSpeed[constants::DiWheelDrive::LEFT_WHEEL] * 1000000, rpmSpeed[constants::DiWheelDrive::RIGHT_WHEEL] * 1000000);
22 58fe0e0b Thomas Schöpping
}
23
24 c9fa414d galberding
void UserThread::setRpmSpeed(const int (&rpmSpeed)[2]) {
25
  global.motorcontrol.setTargetRPM(rpmSpeed[constants::DiWheelDrive::LEFT_WHEEL], rpmSpeed[constants::DiWheelDrive::RIGHT_WHEEL]);
26
}
27
28 181f2892 galberding
void UserThread::lightOneLed(Color color, int idx){
29 5d138bca galberding
  global.robot.setLightColor(idx, Color(color));
30
}
31 58fe0e0b Thomas Schöpping
32 181f2892 galberding
void UserThread::lightAllLeds(Color color){
33 5d138bca galberding
  int led = 0;
34
  for(led=0; led<8; led++){
35
        lightOneLed(color, led);
36
      }
37 58fe0e0b Thomas Schöpping
}
38
39 181f2892 galberding
void UserThread::showChargingState(){
40
  uint8_t numLeds = global.robot.getPowerStatus().state_of_charge / 12;
41
  Color color = Color::GREEN;
42
  if (numLeds <= 2){
43
    color = Color::RED;
44
  }else if(numLeds <= 6){
45
    color = Color::YELLOW;
46
  }
47
  for (int i=0; i<numLeds; i++){
48
    lightOneLed(color, i);
49
    this->sleep(300);
50 9c46b728 galberding
  }
51 181f2892 galberding
  this->sleep(1000);
52
  lightAllLeds(Color::BLACK);
53 9c46b728 galberding
}
54
55 10bf9cc0 galberding
void UserThread::chargeAsLED(){
56
  uint8_t numLeds = global.robot.getPowerStatus().state_of_charge / 12;
57
  Color color = Color::GREEN;
58
  if (numLeds <= 2){
59
    color = Color::RED;
60
  }else if(numLeds <= 6){
61
    color = Color::YELLOW;
62
  }
63
  for (int i=0; i<numLeds; i++){
64
    lightOneLed(color, i);
65
    // this->sleep(300);
66
  }
67
  // this->sleep(1000);
68
  // lightAllLeds(Color::BLACK);
69
}
70
71
// ----------------------------------------------------------------
72
73
void UserThread::getProxySectorVals(uint16_t (&proxVals)[8], uint16_t (&sProx)[8]){
74
  for (int i=0; i<8; i++){
75
    sProx[i] = (proxVals[i] < proxVals[(i+1) % 8]) ? proxVals[i] : proxVals[(i+1) % 8];
76
    // chprintf((BaseSequentialStream*)&global.sercanmux1, "%d: %d, ", i, sProx[i]);
77 8dced1c9 galberding
78 10bf9cc0 galberding
  }
79
    // chprintf((BaseSequentialStream*)&global.sercanmux1, "\n");
80
81
}
82
83
84
void UserThread::getMaxFrontSectorVal(uint16_t (&sProx)[8], int32_t &sPMax){
85
  for (int i=2; i<5; i++){
86
    sPMax = (sPMax < sProx[i]) ? sProx[i] : sPMax;
87
  }
88
}
89
90
void UserThread::proxSectorSpeedCorrection(int (&rpmSpeed)[2], uint16_t (&proxVals)[8]){
91
  int i;
92
  uint16_t sProx[8];
93
  int32_t sPMax = 0;
94
  getProxySectorVals(proxVals, sProx);
95
  getMaxFrontSectorVal(sProx, sPMax);
96 8dced1c9 galberding
97 10bf9cc0 galberding
  int32_t speedL = rpmSpeed[0] - (sPMax * pCtrl.pFactor);
98
  int32_t speedR = rpmSpeed[1] - (sPMax * pCtrl.pFactor);
99
100
101
102
  if(sPMax > pCtrl.threshMid){
103
      rpmSpeed[0] = 0;
104
      rpmSpeed[1] = 0;
105
      pCtrl.staticCont++;
106
  }else if((speedL > 0) || (speedR > 0)){
107
    pCtrl.staticCont = 0;
108
    rpmSpeed[0] = speedL;
109
    rpmSpeed[1] = speedR;
110
  }else{
111
    rpmSpeed[0] = 4000000 + (rpmSpeed[0] - global.rpmForward[0] * 1000000);
112
    rpmSpeed[1] = 4000000 + (rpmSpeed[1] - global.rpmForward[0] * 1000000);
113
  }
114
115
  for(i=4; i<5; i++){
116
    if ((proxVals[i] > pCtrl.threshMid) && (proxVals[i+1] > pCtrl.threshLow)){
117
      rpmSpeed[0] = -5000000 ;
118
      rpmSpeed[1] = -5000000 ;
119
      // pCtrl.staticCont++;
120
      break;
121
    }
122
  }
123
  chargeAsLED();
124 8dced1c9 galberding
125 10bf9cc0 galberding
  // chprintf((BaseSequentialStream*)&global.sercanmux1, "Max: %d factor: %d, Panel: %d SpeedL: %d SpeedR: %d ActualL: %d ActualR: %d\n",sPMax,  pCtrl.pFactor,  sPMax * pCtrl.pFactor, speedL, speedR, rpmSpeed[0], rpmSpeed[1]);
126
127
128
}
129
// -------------------------------------------------------------------
130
131
132
void UserThread::preventCollision( int (&rpmSpeed)[2], uint16_t (&proxVals)[8]) {
133
134
  if((proxVals[3] > pCtrl.threshLow) || (proxVals[4] > pCtrl.threshLow)){
135
      rpmSpeed[0] = rpmSpeed[0] / 2;
136
      rpmSpeed[1] = rpmSpeed[1] / 2;
137
  }
138
139
  if((proxVals[3] > pCtrl.threshMid) || (proxVals[4] > pCtrl.threshMid)){
140 d4c6efa9 galberding
      rpmSpeed[0] = rpmSpeed[0] / 3;
141
      rpmSpeed[1] = rpmSpeed[1] / 3;
142 10bf9cc0 galberding
  }
143
144
  if((proxVals[3] > pCtrl.threshHigh) || (proxVals[4] > pCtrl.threshHigh)){
145
      rpmSpeed[0] = 0;
146
      rpmSpeed[1] = 0;
147
      utCount.ringProxCount++;
148
  }else{
149
    utCount.ringProxCount = 0;
150
  }
151 8dced1c9 galberding
152 10bf9cc0 galberding
}
153
154
155 9c46b728 galberding
/**
156
 * Blocks as long as the position changes.
157
 */
158 181f2892 galberding
void UserThread::checkForMotion(){
159 8dced1c9 galberding
  bool motion = true;
160 9c46b728 galberding
  int led = 0;
161
  types::position oldPos = global.odometry.getPosition();
162
  while(motion){
163 8dced1c9 galberding
    this->sleep(200);
164 9c46b728 galberding
    types::position tmp = global.odometry.getPosition();
165 8dced1c9 galberding
    motion = oldPos.x != tmp.x; //abs(oldPos.x - tmp.x)+ abs(oldPos.y - tmp.y)+abs(oldPos.z - tmp.z);
166 9c46b728 galberding
    oldPos = tmp;
167 8dced1c9 galberding
    global.robot.setLightColor((led + 1) % 8, Color(Color::YELLOW));
168
    global.robot.setLightColor(led % 8, Color(Color::BLACK));
169
    led++;
170 9c46b728 galberding
  }
171 10bf9cc0 galberding
  lightAllLeds(Color::BLACK);
172 9c46b728 galberding
}
173
174 fbcb25cc galberding
bool UserThread::checkFrontalObject(){
175 10bf9cc0 galberding
  uint32_t thresh = pCtrl.threshMid;
176 fbcb25cc galberding
  uint32_t prox;
177
  for(int i=0; i<8; i++){
178
    prox = global.robot.getProximityRingValue(i);
179
    if((i == 3) || (i == 4)){
180
      if(prox < thresh){
181
        return false;
182
      }
183
    }else{
184
      if(prox > thresh){
185
        return false;
186
      }
187
    }
188
  }
189
  return true;
190
}
191
192 181f2892 galberding
bool UserThread::checkPinVoltage(){
193 8dced1c9 galberding
  return global.ltc4412.isPluggedIn();
194 181f2892 galberding
}
195 9c46b728 galberding
196 181f2892 galberding
bool UserThread::checkPinEnabled(){
197
  return global.ltc4412.isEnabled();
198
}
199
200
int UserThread::checkDockingSuccess(){
201
  // setRpmSpeed(stop);
202
  checkForMotion();
203 9c46b728 galberding
  int success = 0;
204 10bf9cc0 galberding
  // global.odometry.resetPosition();
205 9c46b728 galberding
  types::position start = global.startPos = global.odometry.getPosition();
206 27d4e1fa galberding
  global.motorcontrol.setMotorEnable(false);
207
  this->sleep(1000);
208 181f2892 galberding
  types::position stop_ = global.endPos = global.odometry.getPosition();
209 8dced1c9 galberding
210 9c46b728 galberding
  // Amiro moved, docking was not successful
211 10bf9cc0 galberding
  // if ((start.x + stop_.x)  || (start.y + stop_.y)){
212 84b4c632 galberding
  if (abs(start.x - stop_.x) > 200 /* || (start.y + stop_.y) */){
213 181f2892 galberding
    lightAllLeds(Color::RED);
214
    // Enable Motor again if docking was not successful
215 27d4e1fa galberding
    global.motorcontrol.setMotorEnable(true);
216 9c46b728 galberding
    success = 0;
217
  }else{
218 181f2892 galberding
    lightAllLeds(Color::GREEN);
219 9c46b728 galberding
    success = 1;
220
  }
221 8dced1c9 galberding
222 61544eee galberding
  // this->sleep(500);
223 181f2892 galberding
  lightAllLeds(Color::BLACK);
224 9c46b728 galberding
  return success;
225
}
226
227 c9fa414d galberding
int UserThread::getProxyRingSum(){
228
  int prox_sum = 0;
229 e2002d0e galberding
  for(int i=0; i<8;i++){
230
    prox_sum += global.robot.getProximityRingValue(i);;
231
  }
232
  return prox_sum;
233
}
234
235 b24df8ad galberding
int32_t UserThread::meanDeviation(uint16_t a, uint16_t b){
236
  int32_t diff = a - b;
237 8dced1c9 galberding
  int32_t res = 0;
238 b24df8ad galberding
  devCor.proxbuf[devCor.pCount] = (diff*100)/((a+b)/2);
239
  for (int i = 0; i< PROX_DEVIATION_MEAN_WINDOW; i++){
240
    res += devCor.proxbuf[i];
241
  }
242
  devCor.pCount++;
243
  devCor.pCount = devCor.pCount % PROX_DEVIATION_MEAN_WINDOW;
244
245
  devCor.currentDeviation =  res / PROX_DEVIATION_MEAN_WINDOW;
246
  return devCor.currentDeviation;
247
}
248
249 e404e6c0 galberding
void setAttributes(uint8_t (&map)[MAX_NODES][NODE_ATTRIBUTES],
250
                          uint8_t id, uint8_t l, uint8_t r, uint8_t att) {
251
  map[id][0] = l;
252
  map[id][1] = r;
253
  map[id][2] = att;
254
}
255 e2002d0e galberding
256 58fe0e0b Thomas Schöpping
UserThread::UserThread() :
257
  chibios_rt::BaseStaticThread<USER_THREAD_STACK_SIZE>()
258
{
259
}
260
261
UserThread::~UserThread()
262
{
263
}
264
265
msg_t
266
UserThread::main()
267
{
268 5d138bca galberding
  /*
269
   * SETUP
270
   */
271 181f2892 galberding
  // User thread state:
272
273 5d138bca galberding
  for (uint8_t led = 0; led < 8; ++led) {
274
    global.robot.setLightColor(led, Color(Color::BLACK));
275
  }
276
  running = false;
277 10bf9cc0 galberding
  LineFollowStrategy lStrategy = LineFollowStrategy::EDGE_RIGHT;
278 5d138bca galberding
  LineFollow lf(&global);
279 e404e6c0 galberding
  AmiroMap map(&global);
280 5d138bca galberding
  /*
281
   * LOOP
282
   */
283
  while (!this->shouldTerminate())
284
  {
285 181f2892 galberding
    /*
286
    * read accelerometer z-value
287
    */
288
    accel_z = global.lis331dlh.getAccelerationForce(LIS331DLH::AXIS_Z);
289 8dced1c9 galberding
290
    if (accel_z < -900 /*-0.9g*/) {
291 181f2892 galberding
      // Start line following when AMiRo is rotated
292 10bf9cc0 galberding
      if(currentState == states::INACTIVE){
293 fbcb25cc galberding
        newState = states::FOLLOW_LINE;
294 181f2892 galberding
      }else{
295 fbcb25cc galberding
        newState = states::IDLE;
296 181f2892 galberding
      }
297
      lightAllLeds(Color::GREEN);
298
      this->sleep(1000);
299
      lightAllLeds(Color::BLACK);
300 c76baf23 Georg Alberding
301 d607fcef galberding
    // If message was received handle it here:
302
    } else if(global.msgReceived){
303
      global.msgReceived = false;
304 181f2892 galberding
      // running = true;
305 d607fcef galberding
      switch(global.lfStrategy){
306 e404e6c0 galberding
      case msg_content::MSG_START:
307
        newState = states::CALIBRATION_CHECK;
308 10bf9cc0 galberding
        break;
309 e404e6c0 galberding
      case msg_content::MSG_STOP:
310
        newState = states::IDLE;
311 10bf9cc0 galberding
        break;
312 e404e6c0 galberding
      case msg_content::MSG_EDGE_RIGHT:
313
        // newState = states::FOLLOW_LINE;
314
        lStrategy = LineFollowStrategy::EDGE_RIGHT;
315 10bf9cc0 galberding
        break;
316 e404e6c0 galberding
      case  msg_content::MSG_EDGE_LEFT:
317
        // newState = states::FOLLOW_LINE;
318
        lStrategy = LineFollowStrategy::EDGE_LEFT;
319 10bf9cc0 galberding
        break;
320 e404e6c0 galberding
      case msg_content::MSG_FUZZY:
321
        // newState = states::FOLLOW_LINE;
322
        lStrategy = LineFollowStrategy::FUZZY;
323 10bf9cc0 galberding
        break;
324 e404e6c0 galberding
      case msg_content::MSG_DOCK:
325
        newState = states::DETECT_STATION;
326 10bf9cc0 galberding
        break;
327 e404e6c0 galberding
      case msg_content::MSG_UNDOCK:
328
        newState = states::RELEASE;
329
        break;
330
      case msg_content::MSG_CHARGE:
331
        newState = states::CHARGING;
332 10bf9cc0 galberding
        break;
333 e404e6c0 galberding
      case msg_content::MSG_RESET_ODOMETRY:
334
        global.odometry.resetPosition();
335 10bf9cc0 galberding
        break;
336 e404e6c0 galberding
      case msg_content::MSG_CALIBRATE_BLACK:
337
        proxCalib.calibrateBlack = true;
338
        // global.odometry.resetPosition();
339
        newState = states::CALIBRATION;
340 10bf9cc0 galberding
        break;
341 e404e6c0 galberding
      case msg_content::MSG_CALIBRATE_WHITE:
342
        proxCalib.calibrateBlack = false;
343
        newState = states::CALIBRATION;
344 10bf9cc0 galberding
        break;
345 e404e6c0 galberding
      case msg_content::MSG_TEST_MAP_STATE:
346
        newState = states::TEST_MAP_STATE;
347 10bf9cc0 galberding
        break;
348 e404e6c0 galberding
349
      default:
350
        newState = states::IDLE;
351 10bf9cc0 galberding
        break;
352 d607fcef galberding
      }
353 5d138bca galberding
    }
354 10bf9cc0 galberding
    // newState = currentState;
355 d607fcef galberding
356 8dced1c9 galberding
    // Get sensor data
357 fbcb25cc galberding
    // uint16_t WL = global.vcnl4020[constants::DiWheelDrive::PROX_WHEEL_LEFT].getProximityScaledWoOffset();
358
    // uint16_t WR = global.vcnl4020[constants::DiWheelDrive::PROX_WHEEL_RIGHT].getProximityScaledWoOffset();
359 019224ff galberding
    for(int i=0; i<8;i++){
360
      rProx[i] = global.robot.getProximityRingValue(i);
361
    }
362 b24df8ad galberding
363
    // Continously update devication values
364
    meanDeviation(rProx[0] & 0xFFF0, rProx[7] & 0xFFF0);
365 181f2892 galberding
    // int FL = global.vcnl4020[constants::DiWheelDrive::PROX_FRONT_LEFT].getProximityScaledWoOffset();
366
    // int FR = global.vcnl4020[constants::DiWheelDrive::PROX_FRONT_RIGHT].getProximityScaledWoOffset();
367 10bf9cc0 galberding
    switch(currentState){
368
      case states::INACTIVE:
369
        // Dummy state to deactivate every interaction
370
      break;
371
      // ---------------------------------------
372
      case states::CALIBRATION_CHECK:
373
        // global.robot.calibrate();
374
        if(global.linePID.BThresh >= global.linePID.WThresh){
375
          newState = states::CALIBRATION_ERROR;
376
        }else{
377
          newState = states::FOLLOW_LINE;
378
        }
379
      break;
380
      // ---------------------------------------
381
      case states::CALIBRATION:
382
        /* Calibrate the global thresholds for black or white.
383
            This values will be used by the line follow object
384
        */
385
386
        proxCalib.buf = 0;
387
        if(proxCalib.calibrateBlack){
388
          chprintf((BaseSequentialStream*)&global.sercanmux1, "Black Calibration, Place AMiRo on black Surface!\n");
389
          global.robot.calibrate();
390
        }
391
        for(int i=0; i <= proxCalib.meanWindow; i++){
392 8dced1c9 galberding
          proxCalib.buf += global.vcnl4020[constants::DiWheelDrive::PROX_FRONT_LEFT].getProximityScaledWoOffset()
393
                          + global.vcnl4020[constants::DiWheelDrive::PROX_FRONT_RIGHT].getProximityScaledWoOffset();
394 10bf9cc0 galberding
          this->sleep(CAN::UPDATE_PERIOD);
395
        }
396
        proxCalib.buf = proxCalib.buf / (2*proxCalib.meanWindow);
397 8dced1c9 galberding
398 10bf9cc0 galberding
        if(proxCalib.calibrateBlack){
399
          global.linePID.BThresh = proxCalib.buf;
400
        }else  {
401
          global.linePID.WThresh  = proxCalib.buf;
402
        }
403
          chprintf((BaseSequentialStream*)&global.sercanmux1, "Black: %d, White: %d!\n", global.linePID.BThresh, global.linePID.WThresh);
404
405
        newState = states::IDLE;
406
      break;
407
      // ---------------------------------------
408 181f2892 galberding
      case states::IDLE:
409 27d4e1fa galberding
        global.motorcontrol.setMotorEnable(true);
410 181f2892 galberding
        setRpmSpeed(stop);
411
        if(/* checkPinVoltage() && */ checkPinEnabled()){
412
          global.robot.requestCharging(0);
413
        }
414 10bf9cc0 galberding
        // pCtrl.pFactor = 0;
415
        pCtrl.staticCont = 0;
416 fbcb25cc galberding
        utCount.whiteCount = 0;
417 10bf9cc0 galberding
        utCount.ringProxCount = 0;
418 27d4e1fa galberding
        utCount.errorCount = 0;
419 10bf9cc0 galberding
        newState = states::INACTIVE;
420
      break;
421 181f2892 galberding
      // ---------------------------------------
422
      case states::FOLLOW_LINE:
423
      // Set correct forward speed to every strategy
424
        if (global.forwardSpeed != global.rpmForward[0]){
425
          global.forwardSpeed = global.rpmForward[0];
426
        }
427 8dced1c9 galberding
428 181f2892 galberding
        if(lf.getStrategy() != lStrategy){
429 9c46b728 galberding
          lf.setStrategy(lStrategy);
430
        }
431 5d138bca galberding
432 181f2892 galberding
        if(lf.followLine(rpmSpeed)){
433 fbcb25cc galberding
          utCount.whiteCount++;
434 10bf9cc0 galberding
          if(utCount.whiteCount >= WHITE_DETETION_TIMEOUT){
435
            setRpmSpeed(stop);
436
            utCount.whiteCount = 0;
437
            newState = states::WHITE_DETECTION_ERROR;
438 9c46b728 galberding
          }
439 181f2892 galberding
        }else{
440 fbcb25cc galberding
          utCount.whiteCount = 0;
441 9c46b728 galberding
        }
442 e2002d0e galberding
443 10bf9cc0 galberding
        preventCollision(rpmSpeed, rProx);
444
        // proxSectorSpeedCorrection(rpmSpeed, rProx);
445 61544eee galberding
446 10bf9cc0 galberding
        if(utCount.ringProxCount > RING_PROX_DETECTION_TIMEOUT){
447
          utCount.ringProxCount = 0;
448 8dced1c9 galberding
449 d4c6efa9 galberding
450
          checkForMotion();
451
          // Check if only front sensors are active
452
          if (checkFrontalObject()) {
453
            // global.distcontrol.setTargetPosition(0, 2792526, ROTATION_DURATION);
454
            // // BaseThread::sleep(8000);
455
            // checkForMotion();
456
            this->utCount.whiteCount = 0;
457
            newState = states::TURN;
458
            // lf.promptStrategyChange(LineFollowStrategy::EDGE_LEFT);
459
          } else {
460
            newState = states::PROXY_DETECTION_ERROR;
461
          }
462 61544eee galberding
        }
463
464 c9fa414d galberding
        if (lf.getStrategy() == LineFollowStrategy::FUZZY){
465
          setRpmSpeedFuzzy(rpmSpeed);
466
        }else{
467
468
          setRpmSpeed(rpmSpeed);
469
        }
470 8dced1c9 galberding
471 10bf9cc0 galberding
      break;
472 181f2892 galberding
      // ---------------------------------------
473 d4c6efa9 galberding
    case states::TURN:{
474
        // Check the line strategy in order to continue driving on the right side
475
      int factor = SPEED_CONVERSION_FACTOR;
476
      int frontL = global.vcnl4020[constants::DiWheelDrive::PROX_FRONT_LEFT].getProximityScaledWoOffset();
477
      int frontR = global.vcnl4020[constants::DiWheelDrive::PROX_FRONT_RIGHT].getProximityScaledWoOffset();
478 8dced1c9 galberding
      int blackSensor = 0;
479 d4c6efa9 galberding
      if (lf.getStrategy() == LineFollowStrategy::EDGE_RIGHT) {
480
        factor = -factor;
481 8dced1c9 galberding
        blackSensor = frontL;
482
      }else{
483
        blackSensor = frontR;
484 d4c6efa9 galberding
      }
485 8dced1c9 galberding
486 d4c6efa9 galberding
      rpmSpeed[0] = factor * CHARGING_SPEED;
487
      rpmSpeed[1] = -factor * CHARGING_SPEED;
488
      setRpmSpeed(rpmSpeed);
489 8dced1c9 galberding
490
      if ((blackSensor >= global.linePID.WThresh )){
491 d4c6efa9 galberding
        utCount.whiteCount = 1;
492 8dced1c9 galberding
      }else {
493
        if((utCount.whiteCount == 1) && (blackSensor <= global.linePID.BThresh)){
494 d4c6efa9 galberding
          utCount.whiteCount = 0;
495 fbcb25cc galberding
          newState = states::FOLLOW_LINE;
496 d4c6efa9 galberding
          setRpmSpeed(stop);
497 fbcb25cc galberding
        }
498 d4c6efa9 galberding
      }
499 10bf9cc0 galberding
      break;
500 d4c6efa9 galberding
    }
501 fbcb25cc galberding
      // ---------------------------------------
502 e404e6c0 galberding
    case states::DETECT_STATION:
503 8dced1c9 galberding
504 61544eee galberding
        if (global.forwardSpeed != DETECTION_SPEED){
505
          global.forwardSpeed = DETECTION_SPEED;
506
        }
507 181f2892 galberding
        if(lf.getStrategy() != LineFollowStrategy::EDGE_RIGHT){
508
          lf.setStrategy(LineFollowStrategy::EDGE_RIGHT);
509
        }
510 8dced1c9 galberding
511 181f2892 galberding
        lf.followLine(rpmSpeed);
512
        setRpmSpeed(rpmSpeed);
513
        // // Detect marker before docking station
514 019224ff galberding
        // if ((WL+WR) < PROXY_WHEEL_THRESH){
515 8dced1c9 galberding
        // Use proxy ring
516 019224ff galberding
        if ((rProx[3]+rProx[4]) > RING_PROX_FRONT_THRESH){
517
518 d607fcef galberding
          setRpmSpeed(stop);
519 181f2892 galberding
          checkForMotion();
520 8dced1c9 galberding
          // 180° Rotation
521 181f2892 galberding
          global.distcontrol.setTargetPosition(0, ROTATION_180, ROTATION_DURATION);
522
          // BaseThread::sleep(8000);
523
          checkForMotion();
524
          newState = states::CORRECT_POSITIONING;
525 9c46b728 galberding
        }
526 10bf9cc0 galberding
      break;
527 181f2892 galberding
      // ---------------------------------------
528 e404e6c0 galberding
    case states::CORRECT_POSITIONING:
529 019224ff galberding
        if (global.forwardSpeed != CHARGING_SPEED){
530
          global.forwardSpeed = CHARGING_SPEED;
531
        }
532 181f2892 galberding
        if(lf.getStrategy() != LineFollowStrategy::EDGE_LEFT){
533
          lf.promptStrategyChange(LineFollowStrategy::EDGE_LEFT);
534 9c46b728 galberding
        }
535 181f2892 galberding
        lf.followLine(rpmSpeed);
536
        setRpmSpeed(rpmSpeed);
537 9c46b728 galberding
538 10bf9cc0 galberding
        utCount.stateTime++;
539
        if (utCount.stateTime >= DOCKING_CORRECTION_TIMEOUT){
540
          utCount.stateTime = 0;
541 181f2892 galberding
          newState = states::REVERSE;
542
          setRpmSpeed(stop);
543
          checkForMotion();
544
        }
545 10bf9cc0 galberding
      break;
546 181f2892 galberding
      // ---------------------------------------
547 e404e6c0 galberding
    case states::REVERSE:
548 181f2892 galberding
        if(lf.getStrategy() != LineFollowStrategy::REVERSE){
549
          lf.setStrategy(LineFollowStrategy::REVERSE);
550
        }
551
        lf.followLine(rpmSpeed);
552
        setRpmSpeed(rpmSpeed);
553 b24df8ad galberding
        // utCount.stateTime++;
554 58fe0e0b Thomas Schöpping
555 b24df8ad galberding
        // Docking is only successful if Deviation is in range and sensors are at their max values.
556 d4c6efa9 galberding
        if((rProx[0] >= PROX_MAX_VAL)
557
           && (rProx[7] >= PROX_MAX_VAL)
558
           && ((devCor.currentDeviation > -MAX_DEVIATION_FACTOR) && (devCor.currentDeviation < MAX_DEVIATION_FACTOR) )){
559 61544eee galberding
          // setRpmSpeed(stop);
560
          // checkForMotion();
561 10bf9cc0 galberding
          utCount.stateTime = 0;
562 27d4e1fa galberding
          newState = states::PUSH_BACK;
563 b24df8ad galberding
        }else if ((devCor.currentDeviation <= -MAX_DEVIATION_FACTOR) && ((rProx[0] > DEVIATION_DIST_THRESH) || (rProx[7] > DEVIATION_DIST_THRESH))){
564 8dced1c9 galberding
          // Case R
565 b24df8ad galberding
          utCount.stateTime = 0;
566
          setRpmSpeed(stop);
567
          devCor.RCase = true;
568
          lightAllLeds(Color::YELLOW);
569
          newState = states::DEVIATION_CORRECTION;
570
        }else if ((devCor.currentDeviation >= MAX_DEVIATION_FACTOR) && ((rProx[0] > DEVIATION_DIST_THRESH) || (rProx[7] > DEVIATION_DIST_THRESH))){
571 8dced1c9 galberding
          // Case L
572 b24df8ad galberding
          utCount.stateTime = 0;
573
          setRpmSpeed(stop);
574
          devCor.RCase = false;
575
          lightAllLeds(Color::WHITE);
576
          newState = states::DEVIATION_CORRECTION;
577 10bf9cc0 galberding
        }else if (utCount.stateTime >= REVERSE_DOCKING_TIMEOUT){
578
          setRpmSpeed(stop);
579
          utCount.stateTime = 0;
580
          utCount.errorCount++;
581
          if (utCount.errorCount >= DOCKING_ERROR_THRESH){
582
            newState = states::DOCKING_ERROR;
583
          }else{
584
            newState = states::CORRECT_POSITIONING;
585
          }
586 27d4e1fa galberding
        }
587 10bf9cc0 galberding
588 84b4c632 galberding
        // if((devCor.currentDeviation <= -10)){
589
        //   rpmSpeed[0] -= 2000000;
590
        // }else if(devCor.currentDeviation >= 10){
591
        //   rpmSpeed[1] -= 2000000;
592
        // }
593
        // setRpmSpeed(rpmSpeed);
594 10bf9cc0 galberding
      break;
595 27d4e1fa galberding
      // ---------------------------------------
596 e404e6c0 galberding
    case states::DEVIATION_CORRECTION:
597 b24df8ad galberding
        // if(lf.getStrategy() != LineFollowStrategy::REVERSE){
598
        //   lf.setStrategy(LineFollowStrategy::REVERSE);
599
        // }
600
        // lf.followLine(rpmSpeed);
601
        // setRpmSpeed(rpmSpeed);
602
        if(utCount.stateTime < DEVIATION_CORRECTION_DURATION / 2 ){
603
          if(devCor.RCase){
604
            rpmSpeed[0] = 0;
605
            rpmSpeed[1] = DEVIATION_CORRECTION_SPEED;
606
          }else {
607
            rpmSpeed[0] = DEVIATION_CORRECTION_SPEED;
608
            rpmSpeed[1] = 0;
609
          }
610
          setRpmSpeed(rpmSpeed);
611 84b4c632 galberding
        }else if (((utCount.stateTime >= DEVIATION_CORRECTION_DURATION / 2) && (utCount.stateTime < DEVIATION_CORRECTION_DURATION +10)) ){
612 b24df8ad galberding
          if(devCor.RCase){
613
            rpmSpeed[0] = DEVIATION_CORRECTION_SPEED;
614
            rpmSpeed[1] = 0;
615
          }else {
616
            rpmSpeed[0] = 0;
617
            rpmSpeed[1] = DEVIATION_CORRECTION_SPEED;
618
          }
619
          setRpmSpeed(rpmSpeed);
620 84b4c632 galberding
          if(((devCor.currentDeviation >= -5) && (devCor.currentDeviation <= 5))){
621
            utCount.stateTime = 0;
622
            newState = states::REVERSE;
623
            setRpmSpeed(stop);
624
          }
625 b24df8ad galberding
        }else{
626
          utCount.stateTime = 0;
627
          newState = states::REVERSE;
628
          setRpmSpeed(stop);
629
        }
630
631
        utCount.stateTime++;
632
633
634
        // if (utCount.stateTime > PUSH_BACK_TIMEOUT){
635
        //   utCount.stateTime = 0;
636
        //   newState = states::CHECK_POSITIONING;
637
        // }
638
      break;
639
      // ---------------------------------------
640 e404e6c0 galberding
    case states::PUSH_BACK:
641 27d4e1fa galberding
        if(lf.getStrategy() != LineFollowStrategy::REVERSE){
642
          lf.setStrategy(LineFollowStrategy::REVERSE);
643
        }
644
        lf.followLine(rpmSpeed);
645
        setRpmSpeed(rpmSpeed);
646
647 10bf9cc0 galberding
        utCount.stateTime++;
648
        if (utCount.stateTime > PUSH_BACK_TIMEOUT){
649
          utCount.stateTime = 0;
650 181f2892 galberding
          newState = states::CHECK_POSITIONING;
651
        }
652 10bf9cc0 galberding
      break;
653 181f2892 galberding
      // ---------------------------------------
654 e404e6c0 galberding
    case states::CHECK_POSITIONING:
655 61544eee galberding
        setRpmSpeed(stop);
656
        checkForMotion();
657 27d4e1fa galberding
        if(checkDockingSuccess()){
658
          newState = states::CHECK_VOLTAGE;
659
        }else{
660
          utCount.errorCount++;
661
          newState = states::CORRECT_POSITIONING;
662 10bf9cc0 galberding
          if (utCount.errorCount >= DOCKING_ERROR_THRESH){
663
              newState = states::DOCKING_ERROR;
664 27d4e1fa galberding
            }
665
        }
666 10bf9cc0 galberding
      break;
667 181f2892 galberding
      // ---------------------------------------
668 e404e6c0 galberding
    case states::CHECK_VOLTAGE:
669 ba75ee1d galberding
        if(!checkPinEnabled()){
670
          global.robot.requestCharging(1);
671
        } else {
672
          if(checkPinVoltage()){
673 8dced1c9 galberding
            // Pins are under voltage -> correctly docked
674
675 ba75ee1d galberding
            newState = states::CHARGING;
676
          }else{
677 27d4e1fa galberding
            utCount.errorCount++;
678 ba75ee1d galberding
            // No voltage on pins -> falsely docked
679
            // deactivate pins
680 27d4e1fa galberding
            global.motorcontrol.setMotorEnable(true);
681 ba75ee1d galberding
            global.robot.requestCharging(0);
682 27d4e1fa galberding
            // TODO: Soft release when docking falsely
683 61544eee galberding
            if((rProx[0] >= PROX_MAX_VAL) && (rProx[7] >= PROX_MAX_VAL)){
684
              newState = states::RELEASE_TO_CORRECT;
685
            } else {
686 8dced1c9 galberding
              newState = states::RELEASE_TO_CORRECT; //states::CORRECT_POSITIONING;
687 27d4e1fa galberding
            }
688
689
            if (utCount.errorCount > DOCKING_ERROR_THRESH){
690 10bf9cc0 galberding
              newState = states::DOCKING_ERROR;
691 61544eee galberding
            }
692 ba75ee1d galberding
          }
693
        }
694 10bf9cc0 galberding
      break;
695 019224ff galberding
      // ---------------------------------------
696 e404e6c0 galberding
    case states::RELEASE_TO_CORRECT:
697 8dced1c9 galberding
698 019224ff galberding
        global.distcontrol.setTargetPosition(0, ROTATION_20, ROTATION_DURATION);
699
        checkForMotion();
700
        // move 1cm forward
701
        global.distcontrol.setTargetPosition(5000, 0, ROTATION_DURATION);
702
        checkForMotion();
703
        // rotate back
704
        global.distcontrol.setTargetPosition(0, -2*ROTATION_20, ROTATION_DURATION);
705
        checkForMotion();
706
707 10bf9cc0 galberding
        global.distcontrol.setTargetPosition(1500, 0, ROTATION_DURATION);
708 019224ff galberding
        checkForMotion();
709
        newState = states::CORRECT_POSITIONING;
710 10bf9cc0 galberding
      break;
711 27d4e1fa galberding
      // ---------------------------------------
712 e404e6c0 galberding
    case states::CHARGING:
713 27d4e1fa galberding
        global.motorcontrol.setMotorEnable(false);
714 10bf9cc0 galberding
        utCount.errorCount = 0;
715 181f2892 galberding
        // Formulate Request to enable charging
716
        if(/* checkPinVoltage() && */ !checkPinEnabled()){
717
          global.robot.requestCharging(1);
718
        }
719
        if(checkPinEnabled()){
720
          showChargingState();
721
        }
722 10bf9cc0 galberding
      break;
723 181f2892 galberding
      // ---------------------------------------
724 e404e6c0 galberding
    case states::RELEASE:
725 e5606def galberding
726 61544eee galberding
      if (global.forwardSpeed != DETECTION_SPEED){
727
          global.rpmForward[0] = DETECTION_SPEED;
728
        }
729 181f2892 galberding
        if(/* checkPinVoltage() && */ checkPinEnabled()){
730
          global.robot.requestCharging(0);
731
        }else{
732 27d4e1fa galberding
          global.motorcontrol.setMotorEnable(true);
733 8dced1c9 galberding
          // TODO: Use controlled
734 181f2892 galberding
          //Rotate -20° to free from magnet
735
          global.distcontrol.setTargetPosition(0, ROTATION_20, ROTATION_DURATION);
736 61544eee galberding
          checkForMotion();
737
          // move 1cm forward
738
          global.distcontrol.setTargetPosition(5000, 0, ROTATION_DURATION);
739
          checkForMotion();
740
          // rotate back
741 10bf9cc0 galberding
          // global.distcontrol.setTargetPosition(0, -ROTATION_20, ROTATION_DURATION);
742
          // checkForMotion();
743 019224ff galberding
744 61544eee galberding
          // global.distcontrol.setTargetPosition(5000, 0, ROTATION_DURATION);
745
          // checkForMotion();
746 181f2892 galberding
          lStrategy = LineFollowStrategy::EDGE_RIGHT;
747
          newState = states::FOLLOW_LINE;
748 61544eee galberding
            // whiteBuf = -100;
749
          // lf.followLine(rpmSpeed);
750
          // setRpmSpeed(rpmSpeed);
751 181f2892 galberding
        }
752 61544eee galberding
        // lightAllLeds(Color::BLACK);
753 10bf9cc0 galberding
      break;
754
      // ---------------------------------------
755 e404e6c0 galberding
    case states::DOCKING_ERROR:
756
      newState = states::RELEASE;
757 10bf9cc0 galberding
      break;
758
      // ---------------------------------------
759 e404e6c0 galberding
    case states::REVERSE_TIMEOUT_ERROR:
760
      newState = states::IDLE;
761 10bf9cc0 galberding
      break;
762
      // ---------------------------------------
763 e404e6c0 galberding
    case states::CALIBRATION_ERROR:
764
      newState = states::IDLE;
765 10bf9cc0 galberding
      break;
766
      // ---------------------------------------
767 e404e6c0 galberding
    case states::WHITE_DETECTION_ERROR:
768
      newState = states::IDLE;
769 10bf9cc0 galberding
      break;
770
      // ---------------------------------------
771 e404e6c0 galberding
    case states::PROXY_DETECTION_ERROR:
772
      newState = states::IDLE;
773 10bf9cc0 galberding
      break;
774
      // ---------------------------------------
775 e404e6c0 galberding
    case states::NO_CHARGING_POWER_ERROR:
776
      newState = states::IDLE;
777 10bf9cc0 galberding
      break;
778
      // ---------------------------------------
779 e404e6c0 galberding
    case states::UNKNOWN_STATE_ERROR:
780 10bf9cc0 galberding
        newState = states::IDLE;
781
      break;
782
      // ---------------------------------------
783 e404e6c0 galberding
    case states::TEST_MAP_STATE:{
784 e5606def galberding
      // Test suit for amiro map
785 e404e6c0 galberding
786
787 bdac5bec galberding
788 e404e6c0 galberding
      // AmiroMap map = AmiroMap(&global);
789
790 e5606def galberding
      // --------------------------------------------------
791 e404e6c0 galberding
792
      global.tcase = 0;
793 bdac5bec galberding
      // Set basic valid map configuration
794
      setAttributes(global.testmap, 0, 1, 2, 1);
795
      setAttributes(global.testmap, 1, 2, 2, 0);
796
      setAttributes(global.testmap, 2, 1, 0, 0);
797
      setAttributes(global.testmap, 3, 0, 0, 0xff);
798
      chprintf((BaseSequentialStream *)&global.sercanmux1, "Init Case: %d, res: %d\n",global.tcase, map.initialize());
799 e404e6c0 galberding
      global.testres[global.tcase] = map.get_state()->valid;
800
801 bdac5bec galberding
      global.tcase++; // 1
802
      // Test map fail if first node is flagged with end
803 e404e6c0 galberding
      setAttributes(global.testmap, 0, 1, 2, 0xff);
804
      map.initialize();
805
      global.testres[global.tcase] = !map.get_state()->valid;
806
807
      global.tcase++; // 2
808 bdac5bec galberding
      // Test if node 2 is set as start node
809 e404e6c0 galberding
      setAttributes(global.testmap, 0, 1, 2, 0);
810
      setAttributes(global.testmap, 2, 1, 0, 1);
811
      map.initialize();
812
      global.testres[global.tcase] = map.get_state()->current == 2;
813
814
      global.tcase++; // 3
815 bdac5bec galberding
      // Test if non reachable nodes will trigger invalid map
816 e404e6c0 galberding
      setAttributes(global.testmap, 3, 0, 0, 0);
817
      setAttributes(global.testmap, 4, 0, 0, 0xff);
818
      map.initialize();
819
      global.testres[global.tcase] = !map.get_state()->valid;
820
821 bdac5bec galberding
      global.tcase++; // 4
822
      // Test Reinitialization
823
      setAttributes(global.testmap, 0, 1, 2, 1);
824
      setAttributes(global.testmap, 1, 2, 2, 0);
825
      setAttributes(global.testmap, 2, 1, 0, 0);
826
      setAttributes(global.testmap, 3, 0, 0, 0xff);
827
      map.initialize();
828
      global.testres[global.tcase] = map.get_state()->valid;
829
830
      global.odometry.resetPosition();
831
      uint8_t ret = 0;
832
      global.tcase++; // 5
833
      // Test update under normal linefollowing without fixpoint
834
      ret = map.update(20000, 20000, LineFollowStrategy::EDGE_RIGHT);
835
      chprintf((BaseSequentialStream *)&global.sercanmux1,
836
               "Update test %d: Ret %d, cur %d, nex %d\n", global.tcase, ret,
837
               map.get_state()->current, map.get_state()->next);
838
      // No case should be true because neither was a node visited nor
839
      // was a fixpoint detected.
840
      global.testres[global.tcase] = (ret == 0x4);
841
842
843
      global.odometry.setPosition(1.0, 0.0, 0.0);
844 d02c536e galberding
      chprintf((BaseSequentialStream *)&global.sercanmux1, "Current Point: %d\n", global.odometry.getPosition().x);
845 bdac5bec galberding
      global.tcase++; // 6
846
      // Fixpoint on left side
847
      ret = map.update(0, 20000, LineFollowStrategy::EDGE_RIGHT);
848
      chprintf((BaseSequentialStream *)&global.sercanmux1,
849
               "Update test %d: Ret %d, cur %d, nex %d\n", global.tcase, ret,
850
               map.get_state()->current, map.get_state()->next);
851
      // No case should be true because neither was a node visited nor
852
      // was a fixpoint detected.
853
      // global.odometry
854
      global.testres[global.tcase] = (ret == 0x1)
855
        && (map.get_state()->strategy == 0x01)
856
        && (map.get_state()->dist == 0)
857
        && (map.get_state()->current == 2);
858
859
860
      global.odometry.setPosition(1.5, 0.0, 0.0);
861 d02c536e galberding
      chprintf((BaseSequentialStream *)&global.sercanmux1,
862
               "Current Point: %d\n", global.odometry.getPosition().x);
863 bdac5bec galberding
      global.tcase++; // 7
864
      // Fixpoint on left side, no update should appear because fixpoint already
865
      // marked
866
      ret = map.update(0, 20000, LineFollowStrategy::EDGE_RIGHT);
867
      chprintf((BaseSequentialStream *)&global.sercanmux1,
868
               "Update test %d: Ret %d, cur %d, nex %d\n", global.tcase, ret,
869
               map.get_state()->current, map.get_state()->next);
870
      // No case should be true because neither was a node visited nor
871
      // was a fixpoint detected.
872
      global.testres[global.tcase] = (ret == 0x00)
873
        && (map.get_state()->strategy == 0x01);
874
        // && (map.get_state()->dist == 0);
875
876 d02c536e galberding
      global.odometry.setPosition(1.2, 0.0, 0.0);
877
      global.tcase++; // 8
878
      // Fixpoint on left side, no update should appear because fixpoint already
879
      // marked
880
      ret = map.update(20000, 20000, LineFollowStrategy::EDGE_RIGHT);
881
      chprintf((BaseSequentialStream *)&global.sercanmux1,
882
               "Update test %d: Ret %d, cur %d, nex %d, dist %d, len %d\n", global.tcase, ret,
883
               map.get_state()->current, map.get_state()->next, map.get_state()->dist, map.get_state()->eLength);
884
      // No case should be true because neither was a node visited nor
885
      // was a fixpoint detected.
886
      global.testres[global.tcase] =
887
          (ret == 0x04) && (map.get_state()->strategy == 0x01)
888
        && (map.get_state()->dist == 0);
889 bdac5bec galberding
890 d02c536e galberding
      global.odometry.setPosition(.5, 0.0, 0.0);
891
      chprintf((BaseSequentialStream *)&global.sercanmux1,
892
               "Current Point: %d\n", global.odometry.getPosition().x);
893
      global.tcase++; // 9
894
      // Fixpoint on left side, no update should appear because fixpoint already
895
      // marked
896
      ret = map.update(0, 20000, LineFollowStrategy::EDGE_RIGHT);
897
      chprintf((BaseSequentialStream *)&global.sercanmux1,
898
               "Update test %d: Ret %d, cur %d, nex %d, dist %d, len %d\n",
899
               global.tcase, ret, map.get_state()->current,
900
               map.get_state()->next, map.get_state()->dist,
901
               map.get_state()->eLength);
902
      // No case should be true because neither was a node visited nor
903
      // was a fixpoint detected.
904
      global.testres[global.tcase] =
905
        (ret == 9) &&
906
        (map.get_state()->strategy == 1) &&
907
        (map.get_state()->dist == 0) &&
908
        (map.get_state()->eLength == 50);
909 bdac5bec galberding
910 d02c536e galberding
      global.odometry.setPosition(.75, 0.0, 0.0);
911
      chprintf((BaseSequentialStream *)&global.sercanmux1,
912
               "Current Point: %d\n", global.odometry.getPosition().x);
913
      global.tcase++; // 10
914
      // Fixpoint on left side, no update should appear because fixpoint already
915
      // marked
916
      ret = map.update(20000, 20000, LineFollowStrategy::EDGE_RIGHT);
917
      chprintf((BaseSequentialStream *)&global.sercanmux1,
918
               "Update test %d: Ret %d, cur %d, nex %d, dist %d, len %d\n",
919
               global.tcase, ret, map.get_state()->current,
920
               map.get_state()->next, map.get_state()->dist,
921
               map.get_state()->eLength);
922
      // No case should be true because neither was a node visited nor
923
      // was a fixpoint detected.
924
      global.testres[global.tcase] =
925
          (ret == 12) && (map.get_state()->strategy == 1) &&
926
          (map.get_state()->dist == 50) && (map.get_state()->eLength == 50);
927 bdac5bec galberding
928 e404e6c0 galberding
      int failed = 0;
929
      int passed = 0;
930
      for (int i = 0; i <= global.tcase; i++) {
931
        if (global.testres[i]) {
932
          passed++;
933
          chprintf((BaseSequentialStream *)&global.sercanmux1,
934
                   "Test %d Passed!\n", i);
935
        } else {
936
          failed++;
937
          chprintf((BaseSequentialStream *)&global.sercanmux1,
938
                   "Test %d Failed\n", i);
939
        }
940 27d4e1fa galberding
      }
941 e404e6c0 galberding
      chprintf((BaseSequentialStream *)&global.sercanmux1,
942
               "Total: %d, Passed: %d, Failed: %d\n", global.tcase + 1, passed,
943
               failed);
944
945
      newState = states::IDLE;
946
      break;
947
    }
948
      // --------------------------------------------------
949
    default:
950
      newState = states::UNKNOWN_STATE_ERROR;
951
      break;
952
    }
953
954 e5606def galberding
    // In case a new state is set:
955
    // 1. Record the state transition
956 e404e6c0 galberding
    if (currentState != newState){
957 e5606def galberding
958
      global.stateTransitionCounter++;
959
      // Clear all state transitions to prevent overflow
960
      if (global.stateTransitionCounter >= 255) {
961
        global.stateTransitionCounter = 0;
962
        for (int i = 0; i < 24; i++) {
963
          global.stateTracker[i] = 0;
964
        }
965
}
966
      // Transmit the new state over can
967 e404e6c0 galberding
      chprintf((BaseSequentialStream*)&global.sercanmux1, "Transmit state %d\n", newState);
968
      global.robot.transmitState(newState);
969 e5606def galberding
970
      // Increase state count for specific state
971
      // TODO: Improve with dictionary or other than switch case
972
      if (newState == states::IDLE)
973
        {global.stateTracker[states::IDLE] += 1;}
974
      else if (newState == states::FOLLOW_LINE)
975
        {global.stateTracker[states::FOLLOW_LINE] += 1;}
976
      else if (newState == states::DETECT_STATION)
977
        {global.stateTracker[states::DETECT_STATION] += 1;}
978
      else if (newState == states::REVERSE)
979
        {global.stateTracker[states::REVERSE] += 1;}
980
      else if (newState == states::PUSH_BACK)
981
        {global.stateTracker[states::PUSH_BACK] += 1;}
982
      else if (newState == states::CHECK_POSITIONING)
983
        {global.stateTracker[states::CHECK_POSITIONING] += 1;}
984
      else if (newState == states::CHECK_VOLTAGE)
985
        {global.stateTracker[states::CHECK_VOLTAGE] += 1;}
986
      else if (newState == states::CHARGING)
987
        {global.stateTracker[states::CHARGING] += 1;}
988
      else if (newState == states::RELEASE)
989
        {global.stateTracker[states::RELEASE] += 1;}
990
      else if (newState == states::RELEASE_TO_CORRECT)
991
        {global.stateTracker[states::RELEASE_TO_CORRECT] += 1;}
992
      else if (newState == states::CORRECT_POSITIONING)
993
        {global.stateTracker[states::CORRECT_POSITIONING] += 1;}
994
      else if (newState == states::TURN)
995
        {global.stateTracker[states::TURN] += 1;}
996
      else if (newState == states::INACTIVE)
997
        {global.stateTracker[states::INACTIVE] += 1;}
998
      else if (newState == states::CALIBRATION)
999
        {global.stateTracker[states::CALIBRATION] += 1;}
1000
      else if (newState == states::CALIBRATION_CHECK)
1001
        {global.stateTracker[states::CALIBRATION_CHECK] += 1;}
1002
      else if (newState == states::DEVIATION_CORRECTION)
1003
        {global.stateTracker[states::DEVIATION_CORRECTION] += 1;}
1004
      else if (newState == states::DOCKING_ERROR)
1005
        {global.stateTracker[16+(-states::DOCKING_ERROR)] += 1;}
1006
      else if (newState == states::REVERSE_TIMEOUT_ERROR)
1007
        {global.stateTracker[16+(-states::REVERSE_TIMEOUT_ERROR)] += 1;}
1008
      else if (newState == states::CALIBRATION_ERROR)
1009
        {global.stateTracker[16+(-states::CALIBRATION_ERROR)] += 1;}
1010
      else if (newState == states::WHITE_DETECTION_ERROR)
1011
        {global.stateTracker[16+(-states::WHITE_DETECTION_ERROR)] += 1;}
1012
      else if (newState == states::PROXY_DETECTION_ERROR)
1013
        {global.stateTracker[16+(-states::PROXY_DETECTION_ERROR)] += 1;}
1014
      else if (newState == states::NO_CHARGING_POWER_ERROR)
1015
        {global.stateTracker[16+(-states::NO_CHARGING_POWER_ERROR)] += 1;}
1016
      else if (newState == states::UNKNOWN_STATE_ERROR)
1017
        {global.stateTracker[16+(-states::UNKNOWN_STATE_ERROR)] += 1;}
1018 e404e6c0 galberding
    }
1019 e5606def galberding
1020
    // Keep track of last state and set the new state for next iteration
1021 e404e6c0 galberding
    prevState = currentState;
1022
    currentState = newState;
1023
1024 5d138bca galberding
    this->sleep(CAN::UPDATE_PERIOD);
1025
  }
1026 58fe0e0b Thomas Schöpping
1027
  return RDY_OK;
1028
}