Statistics
| Branch: | Tag: | Revision:

amiro-os / devices / DiWheelDrive / userthread.cpp @ 3c3c3bb9

History | View | Annotate | Download (36.732 KB)

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