Statistics
| Branch: | Tag: | Revision:

amiro-os / devices / DiWheelDrive / userthread.cpp @ 4d54a507

History | View | Annotate | Download (36.949 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 3c3c3bb9 galberding
277
  // State Variables
278
  ut_states prevState = ut_states::UT_IDLE;
279
  ut_states currentState = ut_states::UT_INACTIVE;
280
  ut_states newState = ut_states::UT_INACTIVE;
281
282
283 5d138bca galberding
  running = false;
284 10bf9cc0 galberding
  LineFollowStrategy lStrategy = LineFollowStrategy::EDGE_RIGHT;
285 5d138bca galberding
  LineFollow lf(&global);
286 4d54a507 galberding
  AmiroMap map(&global, lStrategy);
287 5d138bca galberding
  /*
288
   * LOOP
289
   */
290
  while (!this->shouldTerminate())
291
  {
292 181f2892 galberding
    /*
293
    * read accelerometer z-value
294
    */
295
    accel_z = global.lis331dlh.getAccelerationForce(LIS331DLH::AXIS_Z);
296 8dced1c9 galberding
297
    if (accel_z < -900 /*-0.9g*/) {
298 181f2892 galberding
      // Start line following when AMiRo is rotated
299 3c3c3bb9 galberding
      if(currentState == ut_states::UT_INACTIVE){
300
        newState = ut_states::UT_FOLLOW_LINE;
301 181f2892 galberding
      }else{
302 3c3c3bb9 galberding
        newState = ut_states::UT_IDLE;
303 181f2892 galberding
      }
304
      lightAllLeds(Color::GREEN);
305
      this->sleep(1000);
306
      lightAllLeds(Color::BLACK);
307 c76baf23 Georg Alberding
308 d607fcef galberding
    // If message was received handle it here:
309
    } else if(global.msgReceived){
310
      global.msgReceived = false;
311 181f2892 galberding
      // running = true;
312 d607fcef galberding
      switch(global.lfStrategy){
313 e404e6c0 galberding
      case msg_content::MSG_START:
314 3c3c3bb9 galberding
        newState = ut_states::UT_CALIBRATION_CHECK;
315 10bf9cc0 galberding
        break;
316 e404e6c0 galberding
      case msg_content::MSG_STOP:
317 3c3c3bb9 galberding
        newState = ut_states::UT_IDLE;
318 10bf9cc0 galberding
        break;
319 e404e6c0 galberding
      case msg_content::MSG_EDGE_RIGHT:
320 3c3c3bb9 galberding
        // newState = ut_states::UT_FOLLOW_LINE;
321 e404e6c0 galberding
        lStrategy = LineFollowStrategy::EDGE_RIGHT;
322 10bf9cc0 galberding
        break;
323 e404e6c0 galberding
      case  msg_content::MSG_EDGE_LEFT:
324 3c3c3bb9 galberding
        // newState = ut_states::UT_FOLLOW_LINE;
325 e404e6c0 galberding
        lStrategy = LineFollowStrategy::EDGE_LEFT;
326 10bf9cc0 galberding
        break;
327 e404e6c0 galberding
      case msg_content::MSG_FUZZY:
328 3c3c3bb9 galberding
        // newState = ut_states::UT_FOLLOW_LINE;
329 e404e6c0 galberding
        lStrategy = LineFollowStrategy::FUZZY;
330 10bf9cc0 galberding
        break;
331 e404e6c0 galberding
      case msg_content::MSG_DOCK:
332 3c3c3bb9 galberding
        newState = ut_states::UT_DETECT_STATION;
333 10bf9cc0 galberding
        break;
334 e404e6c0 galberding
      case msg_content::MSG_UNDOCK:
335 3c3c3bb9 galberding
        newState = ut_states::UT_RELEASE;
336 e404e6c0 galberding
        break;
337
      case msg_content::MSG_CHARGE:
338 3c3c3bb9 galberding
        newState = ut_states::UT_CHARGING;
339 10bf9cc0 galberding
        break;
340 e404e6c0 galberding
      case msg_content::MSG_RESET_ODOMETRY:
341
        global.odometry.resetPosition();
342 10bf9cc0 galberding
        break;
343 e404e6c0 galberding
      case msg_content::MSG_CALIBRATE_BLACK:
344
        proxCalib.calibrateBlack = true;
345
        // global.odometry.resetPosition();
346 3c3c3bb9 galberding
        newState = ut_states::UT_CALIBRATION;
347 10bf9cc0 galberding
        break;
348 e404e6c0 galberding
      case msg_content::MSG_CALIBRATE_WHITE:
349
        proxCalib.calibrateBlack = false;
350 3c3c3bb9 galberding
        newState = ut_states::UT_CALIBRATION;
351 10bf9cc0 galberding
        break;
352 e404e6c0 galberding
      case msg_content::MSG_TEST_MAP_STATE:
353 3c3c3bb9 galberding
        if (AMIRO_MAP_AUTO_TRACKING){
354
          newState = ut_states::UT_TEST_MAP_AUTO_STATE;
355
        }else {
356
          newState = ut_states::UT_TEST_MAP_STATE;
357
        }
358 10bf9cc0 galberding
        break;
359 309980f0 galberding
      case msg_content::MSG_SET_DIST_THRESH:
360
361 e404e6c0 galberding
362 309980f0 galberding
        break;
363
      case msg_content::MSG_GET_MAP_INFO:
364
        break;
365 e404e6c0 galberding
      default:
366 3c3c3bb9 galberding
        newState = ut_states::UT_IDLE;
367 10bf9cc0 galberding
        break;
368 d607fcef galberding
      }
369 5d138bca galberding
    }
370 10bf9cc0 galberding
    // newState = currentState;
371 d607fcef galberding
372 8dced1c9 galberding
    // Get sensor data
373 3c3c3bb9 galberding
    uint16_t WL = global.vcnl4020[constants::DiWheelDrive::PROX_WHEEL_LEFT].getProximityScaledWoOffset();
374
    uint16_t WR = global.vcnl4020[constants::DiWheelDrive::PROX_WHEEL_RIGHT].getProximityScaledWoOffset();
375 019224ff galberding
    for(int i=0; i<8;i++){
376
      rProx[i] = global.robot.getProximityRingValue(i);
377
    }
378 b24df8ad galberding
379
    // Continously update devication values
380
    meanDeviation(rProx[0] & 0xFFF0, rProx[7] & 0xFFF0);
381 181f2892 galberding
    // int FL = global.vcnl4020[constants::DiWheelDrive::PROX_FRONT_LEFT].getProximityScaledWoOffset();
382
    // int FR = global.vcnl4020[constants::DiWheelDrive::PROX_FRONT_RIGHT].getProximityScaledWoOffset();
383 10bf9cc0 galberding
    switch(currentState){
384 3c3c3bb9 galberding
      case ut_states::UT_INACTIVE:
385 10bf9cc0 galberding
        // Dummy state to deactivate every interaction
386
      break;
387
      // ---------------------------------------
388 3c3c3bb9 galberding
      case ut_states::UT_CALIBRATION_CHECK:
389 10bf9cc0 galberding
        // global.robot.calibrate();
390
        if(global.linePID.BThresh >= global.linePID.WThresh){
391 3c3c3bb9 galberding
          newState = ut_states::UT_CALIBRATION_ERROR;
392 10bf9cc0 galberding
        }else{
393 3c3c3bb9 galberding
          newState = ut_states::UT_FOLLOW_LINE;
394 10bf9cc0 galberding
        }
395
      break;
396
      // ---------------------------------------
397 3c3c3bb9 galberding
      case ut_states::UT_CALIBRATION:
398 10bf9cc0 galberding
        /* Calibrate the global thresholds for black or white.
399
            This values will be used by the line follow object
400
        */
401
402
        proxCalib.buf = 0;
403
        if(proxCalib.calibrateBlack){
404
          chprintf((BaseSequentialStream*)&global.sercanmux1, "Black Calibration, Place AMiRo on black Surface!\n");
405
          global.robot.calibrate();
406
        }
407
        for(int i=0; i <= proxCalib.meanWindow; i++){
408 8dced1c9 galberding
          proxCalib.buf += global.vcnl4020[constants::DiWheelDrive::PROX_FRONT_LEFT].getProximityScaledWoOffset()
409
                          + global.vcnl4020[constants::DiWheelDrive::PROX_FRONT_RIGHT].getProximityScaledWoOffset();
410 10bf9cc0 galberding
          this->sleep(CAN::UPDATE_PERIOD);
411
        }
412
        proxCalib.buf = proxCalib.buf / (2*proxCalib.meanWindow);
413 8dced1c9 galberding
414 10bf9cc0 galberding
        if(proxCalib.calibrateBlack){
415
          global.linePID.BThresh = proxCalib.buf;
416
        }else  {
417
          global.linePID.WThresh  = proxCalib.buf;
418
        }
419
          chprintf((BaseSequentialStream*)&global.sercanmux1, "Black: %d, White: %d!\n", global.linePID.BThresh, global.linePID.WThresh);
420
421 3c3c3bb9 galberding
        newState = ut_states::UT_IDLE;
422 10bf9cc0 galberding
      break;
423
      // ---------------------------------------
424 3c3c3bb9 galberding
      case ut_states::UT_IDLE:
425 27d4e1fa galberding
        global.motorcontrol.setMotorEnable(true);
426 181f2892 galberding
        setRpmSpeed(stop);
427
        if(/* checkPinVoltage() && */ checkPinEnabled()){
428
          global.robot.requestCharging(0);
429
        }
430 10bf9cc0 galberding
        // pCtrl.pFactor = 0;
431
        pCtrl.staticCont = 0;
432 fbcb25cc galberding
        utCount.whiteCount = 0;
433 10bf9cc0 galberding
        utCount.ringProxCount = 0;
434 27d4e1fa galberding
        utCount.errorCount = 0;
435 3c3c3bb9 galberding
        newState = ut_states::UT_INACTIVE;
436 10bf9cc0 galberding
      break;
437 181f2892 galberding
      // ---------------------------------------
438 3c3c3bb9 galberding
      case ut_states::UT_FOLLOW_LINE:
439 181f2892 galberding
      // Set correct forward speed to every strategy
440
        if (global.forwardSpeed != global.rpmForward[0]){
441
          global.forwardSpeed = global.rpmForward[0];
442
        }
443 8dced1c9 galberding
444 181f2892 galberding
        if(lf.getStrategy() != lStrategy){
445 9c46b728 galberding
          lf.setStrategy(lStrategy);
446
        }
447 5d138bca galberding
448 181f2892 galberding
        if(lf.followLine(rpmSpeed)){
449 fbcb25cc galberding
          utCount.whiteCount++;
450 10bf9cc0 galberding
          if(utCount.whiteCount >= WHITE_DETETION_TIMEOUT){
451
            setRpmSpeed(stop);
452
            utCount.whiteCount = 0;
453 3c3c3bb9 galberding
            newState = ut_states::UT_WHITE_DETECTION_ERROR;
454 9c46b728 galberding
          }
455 181f2892 galberding
        }else{
456 fbcb25cc galberding
          utCount.whiteCount = 0;
457 9c46b728 galberding
        }
458 e2002d0e galberding
459 10bf9cc0 galberding
        preventCollision(rpmSpeed, rProx);
460
        // proxSectorSpeedCorrection(rpmSpeed, rProx);
461 61544eee galberding
462 10bf9cc0 galberding
        if(utCount.ringProxCount > RING_PROX_DETECTION_TIMEOUT){
463
          utCount.ringProxCount = 0;
464 8dced1c9 galberding
465 d4c6efa9 galberding
466
          checkForMotion();
467
          // Check if only front sensors are active
468
          if (checkFrontalObject()) {
469
            // global.distcontrol.setTargetPosition(0, 2792526, ROTATION_DURATION);
470
            // // BaseThread::sleep(8000);
471
            // checkForMotion();
472
            this->utCount.whiteCount = 0;
473 3c3c3bb9 galberding
            newState = ut_states::UT_TURN;
474 d4c6efa9 galberding
            // lf.promptStrategyChange(LineFollowStrategy::EDGE_LEFT);
475
          } else {
476 3c3c3bb9 galberding
            newState = ut_states::UT_PROXY_DETECTION_ERROR;
477 d4c6efa9 galberding
          }
478 61544eee galberding
        }
479
480 c9fa414d galberding
        if (lf.getStrategy() == LineFollowStrategy::FUZZY){
481
          setRpmSpeedFuzzy(rpmSpeed);
482
        }else{
483
484
          setRpmSpeed(rpmSpeed);
485
        }
486 8dced1c9 galberding
487 10bf9cc0 galberding
      break;
488 181f2892 galberding
      // ---------------------------------------
489 3c3c3bb9 galberding
    case ut_states::UT_TURN:{
490 d4c6efa9 galberding
        // Check the line strategy in order to continue driving on the right side
491
      int factor = SPEED_CONVERSION_FACTOR;
492
      int frontL = global.vcnl4020[constants::DiWheelDrive::PROX_FRONT_LEFT].getProximityScaledWoOffset();
493
      int frontR = global.vcnl4020[constants::DiWheelDrive::PROX_FRONT_RIGHT].getProximityScaledWoOffset();
494 8dced1c9 galberding
      int blackSensor = 0;
495 d4c6efa9 galberding
      if (lf.getStrategy() == LineFollowStrategy::EDGE_RIGHT) {
496
        factor = -factor;
497 8dced1c9 galberding
        blackSensor = frontL;
498
      }else{
499
        blackSensor = frontR;
500 d4c6efa9 galberding
      }
501 8dced1c9 galberding
502 d4c6efa9 galberding
      rpmSpeed[0] = factor * CHARGING_SPEED;
503
      rpmSpeed[1] = -factor * CHARGING_SPEED;
504
      setRpmSpeed(rpmSpeed);
505 8dced1c9 galberding
506
      if ((blackSensor >= global.linePID.WThresh )){
507 d4c6efa9 galberding
        utCount.whiteCount = 1;
508 8dced1c9 galberding
      }else {
509
        if((utCount.whiteCount == 1) && (blackSensor <= global.linePID.BThresh)){
510 d4c6efa9 galberding
          utCount.whiteCount = 0;
511 3c3c3bb9 galberding
          newState = ut_states::UT_FOLLOW_LINE;
512 d4c6efa9 galberding
          setRpmSpeed(stop);
513 fbcb25cc galberding
        }
514 d4c6efa9 galberding
      }
515 10bf9cc0 galberding
      break;
516 d4c6efa9 galberding
    }
517 fbcb25cc galberding
      // ---------------------------------------
518 3c3c3bb9 galberding
    case ut_states::UT_DETECT_STATION:
519 8dced1c9 galberding
520 61544eee galberding
        if (global.forwardSpeed != DETECTION_SPEED){
521
          global.forwardSpeed = DETECTION_SPEED;
522
        }
523 181f2892 galberding
        if(lf.getStrategy() != LineFollowStrategy::EDGE_RIGHT){
524
          lf.setStrategy(LineFollowStrategy::EDGE_RIGHT);
525
        }
526 8dced1c9 galberding
527 181f2892 galberding
        lf.followLine(rpmSpeed);
528
        setRpmSpeed(rpmSpeed);
529
        // // Detect marker before docking station
530 019224ff galberding
        // if ((WL+WR) < PROXY_WHEEL_THRESH){
531 8dced1c9 galberding
        // Use proxy ring
532 019224ff galberding
        if ((rProx[3]+rProx[4]) > RING_PROX_FRONT_THRESH){
533
534 d607fcef galberding
          setRpmSpeed(stop);
535 181f2892 galberding
          checkForMotion();
536 8dced1c9 galberding
          // 180° Rotation
537 181f2892 galberding
          global.distcontrol.setTargetPosition(0, ROTATION_180, ROTATION_DURATION);
538
          // BaseThread::sleep(8000);
539
          checkForMotion();
540 3c3c3bb9 galberding
          newState = ut_states::UT_CORRECT_POSITIONING;
541 9c46b728 galberding
        }
542 10bf9cc0 galberding
      break;
543 181f2892 galberding
      // ---------------------------------------
544 3c3c3bb9 galberding
    case ut_states::UT_CORRECT_POSITIONING:
545 019224ff galberding
        if (global.forwardSpeed != CHARGING_SPEED){
546
          global.forwardSpeed = CHARGING_SPEED;
547
        }
548 181f2892 galberding
        if(lf.getStrategy() != LineFollowStrategy::EDGE_LEFT){
549
          lf.promptStrategyChange(LineFollowStrategy::EDGE_LEFT);
550 9c46b728 galberding
        }
551 181f2892 galberding
        lf.followLine(rpmSpeed);
552
        setRpmSpeed(rpmSpeed);
553 9c46b728 galberding
554 10bf9cc0 galberding
        utCount.stateTime++;
555
        if (utCount.stateTime >= DOCKING_CORRECTION_TIMEOUT){
556
          utCount.stateTime = 0;
557 3c3c3bb9 galberding
          newState = ut_states::UT_REVERSE;
558 181f2892 galberding
          setRpmSpeed(stop);
559
          checkForMotion();
560
        }
561 10bf9cc0 galberding
      break;
562 181f2892 galberding
      // ---------------------------------------
563 3c3c3bb9 galberding
    case ut_states::UT_REVERSE:
564 181f2892 galberding
        if(lf.getStrategy() != LineFollowStrategy::REVERSE){
565
          lf.setStrategy(LineFollowStrategy::REVERSE);
566
        }
567
        lf.followLine(rpmSpeed);
568
        setRpmSpeed(rpmSpeed);
569 b24df8ad galberding
        // utCount.stateTime++;
570 58fe0e0b Thomas Schöpping
571 b24df8ad galberding
        // Docking is only successful if Deviation is in range and sensors are at their max values.
572 d4c6efa9 galberding
        if((rProx[0] >= PROX_MAX_VAL)
573
           && (rProx[7] >= PROX_MAX_VAL)
574
           && ((devCor.currentDeviation > -MAX_DEVIATION_FACTOR) && (devCor.currentDeviation < MAX_DEVIATION_FACTOR) )){
575 61544eee galberding
          // setRpmSpeed(stop);
576
          // checkForMotion();
577 10bf9cc0 galberding
          utCount.stateTime = 0;
578 3c3c3bb9 galberding
          newState = ut_states::UT_PUSH_BACK;
579 b24df8ad galberding
        }else if ((devCor.currentDeviation <= -MAX_DEVIATION_FACTOR) && ((rProx[0] > DEVIATION_DIST_THRESH) || (rProx[7] > DEVIATION_DIST_THRESH))){
580 8dced1c9 galberding
          // Case R
581 b24df8ad galberding
          utCount.stateTime = 0;
582
          setRpmSpeed(stop);
583
          devCor.RCase = true;
584
          lightAllLeds(Color::YELLOW);
585 3c3c3bb9 galberding
          newState = ut_states::UT_DEVIATION_CORRECTION;
586 b24df8ad galberding
        }else if ((devCor.currentDeviation >= MAX_DEVIATION_FACTOR) && ((rProx[0] > DEVIATION_DIST_THRESH) || (rProx[7] > DEVIATION_DIST_THRESH))){
587 8dced1c9 galberding
          // Case L
588 b24df8ad galberding
          utCount.stateTime = 0;
589
          setRpmSpeed(stop);
590
          devCor.RCase = false;
591
          lightAllLeds(Color::WHITE);
592 3c3c3bb9 galberding
          newState = ut_states::UT_DEVIATION_CORRECTION;
593 10bf9cc0 galberding
        }else if (utCount.stateTime >= REVERSE_DOCKING_TIMEOUT){
594
          setRpmSpeed(stop);
595
          utCount.stateTime = 0;
596
          utCount.errorCount++;
597
          if (utCount.errorCount >= DOCKING_ERROR_THRESH){
598 3c3c3bb9 galberding
            newState = ut_states::UT_DOCKING_ERROR;
599 10bf9cc0 galberding
          }else{
600 3c3c3bb9 galberding
            newState = ut_states::UT_CORRECT_POSITIONING;
601 10bf9cc0 galberding
          }
602 27d4e1fa galberding
        }
603 10bf9cc0 galberding
604 84b4c632 galberding
        // if((devCor.currentDeviation <= -10)){
605
        //   rpmSpeed[0] -= 2000000;
606
        // }else if(devCor.currentDeviation >= 10){
607
        //   rpmSpeed[1] -= 2000000;
608
        // }
609
        // setRpmSpeed(rpmSpeed);
610 10bf9cc0 galberding
      break;
611 27d4e1fa galberding
      // ---------------------------------------
612 3c3c3bb9 galberding
    case ut_states::UT_DEVIATION_CORRECTION:
613 b24df8ad galberding
        // if(lf.getStrategy() != LineFollowStrategy::REVERSE){
614
        //   lf.setStrategy(LineFollowStrategy::REVERSE);
615
        // }
616
        // lf.followLine(rpmSpeed);
617
        // setRpmSpeed(rpmSpeed);
618
        if(utCount.stateTime < DEVIATION_CORRECTION_DURATION / 2 ){
619
          if(devCor.RCase){
620
            rpmSpeed[0] = 0;
621
            rpmSpeed[1] = DEVIATION_CORRECTION_SPEED;
622
          }else {
623
            rpmSpeed[0] = DEVIATION_CORRECTION_SPEED;
624
            rpmSpeed[1] = 0;
625
          }
626
          setRpmSpeed(rpmSpeed);
627 84b4c632 galberding
        }else if (((utCount.stateTime >= DEVIATION_CORRECTION_DURATION / 2) && (utCount.stateTime < DEVIATION_CORRECTION_DURATION +10)) ){
628 b24df8ad galberding
          if(devCor.RCase){
629
            rpmSpeed[0] = DEVIATION_CORRECTION_SPEED;
630
            rpmSpeed[1] = 0;
631
          }else {
632
            rpmSpeed[0] = 0;
633
            rpmSpeed[1] = DEVIATION_CORRECTION_SPEED;
634
          }
635
          setRpmSpeed(rpmSpeed);
636 84b4c632 galberding
          if(((devCor.currentDeviation >= -5) && (devCor.currentDeviation <= 5))){
637
            utCount.stateTime = 0;
638 3c3c3bb9 galberding
            newState = ut_states::UT_REVERSE;
639 84b4c632 galberding
            setRpmSpeed(stop);
640
          }
641 b24df8ad galberding
        }else{
642
          utCount.stateTime = 0;
643 3c3c3bb9 galberding
          newState = ut_states::UT_REVERSE;
644 b24df8ad galberding
          setRpmSpeed(stop);
645
        }
646
647
        utCount.stateTime++;
648
649
650
        // if (utCount.stateTime > PUSH_BACK_TIMEOUT){
651
        //   utCount.stateTime = 0;
652 3c3c3bb9 galberding
        //   newState = ut_states::UT_CHECK_POSITIONING;
653 b24df8ad galberding
        // }
654
      break;
655
      // ---------------------------------------
656 3c3c3bb9 galberding
    case ut_states::UT_PUSH_BACK:
657 27d4e1fa galberding
        if(lf.getStrategy() != LineFollowStrategy::REVERSE){
658
          lf.setStrategy(LineFollowStrategy::REVERSE);
659
        }
660
        lf.followLine(rpmSpeed);
661
        setRpmSpeed(rpmSpeed);
662
663 10bf9cc0 galberding
        utCount.stateTime++;
664
        if (utCount.stateTime > PUSH_BACK_TIMEOUT){
665
          utCount.stateTime = 0;
666 3c3c3bb9 galberding
          newState = ut_states::UT_CHECK_POSITIONING;
667 181f2892 galberding
        }
668 10bf9cc0 galberding
      break;
669 181f2892 galberding
      // ---------------------------------------
670 3c3c3bb9 galberding
    case ut_states::UT_CHECK_POSITIONING:
671 61544eee galberding
        setRpmSpeed(stop);
672
        checkForMotion();
673 27d4e1fa galberding
        if(checkDockingSuccess()){
674 3c3c3bb9 galberding
          newState = ut_states::UT_CHECK_VOLTAGE;
675 27d4e1fa galberding
        }else{
676
          utCount.errorCount++;
677 3c3c3bb9 galberding
          newState = ut_states::UT_CORRECT_POSITIONING;
678 10bf9cc0 galberding
          if (utCount.errorCount >= DOCKING_ERROR_THRESH){
679 3c3c3bb9 galberding
              newState = ut_states::UT_DOCKING_ERROR;
680 27d4e1fa galberding
            }
681
        }
682 10bf9cc0 galberding
      break;
683 181f2892 galberding
      // ---------------------------------------
684 3c3c3bb9 galberding
    case ut_states::UT_CHECK_VOLTAGE:
685 ba75ee1d galberding
        if(!checkPinEnabled()){
686
          global.robot.requestCharging(1);
687
        } else {
688
          if(checkPinVoltage()){
689 8dced1c9 galberding
            // Pins are under voltage -> correctly docked
690
691 3c3c3bb9 galberding
            newState = ut_states::UT_CHARGING;
692 ba75ee1d galberding
          }else{
693 27d4e1fa galberding
            utCount.errorCount++;
694 ba75ee1d galberding
            // No voltage on pins -> falsely docked
695
            // deactivate pins
696 27d4e1fa galberding
            global.motorcontrol.setMotorEnable(true);
697 ba75ee1d galberding
            global.robot.requestCharging(0);
698 27d4e1fa galberding
            // TODO: Soft release when docking falsely
699 61544eee galberding
            if((rProx[0] >= PROX_MAX_VAL) && (rProx[7] >= PROX_MAX_VAL)){
700 3c3c3bb9 galberding
              newState = ut_states::UT_RELEASE_TO_CORRECT;
701 61544eee galberding
            } else {
702 3c3c3bb9 galberding
              newState = ut_states::UT_RELEASE_TO_CORRECT; //ut_states::UT_CORRECT_POSITIONING;
703 27d4e1fa galberding
            }
704
705
            if (utCount.errorCount > DOCKING_ERROR_THRESH){
706 3c3c3bb9 galberding
              newState = ut_states::UT_DOCKING_ERROR;
707 61544eee galberding
            }
708 ba75ee1d galberding
          }
709
        }
710 10bf9cc0 galberding
      break;
711 019224ff galberding
      // ---------------------------------------
712 3c3c3bb9 galberding
    case ut_states::UT_RELEASE_TO_CORRECT:
713 8dced1c9 galberding
714 019224ff galberding
        global.distcontrol.setTargetPosition(0, ROTATION_20, ROTATION_DURATION);
715
        checkForMotion();
716
        // move 1cm forward
717
        global.distcontrol.setTargetPosition(5000, 0, ROTATION_DURATION);
718
        checkForMotion();
719
        // rotate back
720
        global.distcontrol.setTargetPosition(0, -2*ROTATION_20, ROTATION_DURATION);
721
        checkForMotion();
722
723 10bf9cc0 galberding
        global.distcontrol.setTargetPosition(1500, 0, ROTATION_DURATION);
724 019224ff galberding
        checkForMotion();
725 3c3c3bb9 galberding
        newState = ut_states::UT_CORRECT_POSITIONING;
726 10bf9cc0 galberding
      break;
727 27d4e1fa galberding
      // ---------------------------------------
728 3c3c3bb9 galberding
    case ut_states::UT_CHARGING:
729 27d4e1fa galberding
        global.motorcontrol.setMotorEnable(false);
730 10bf9cc0 galberding
        utCount.errorCount = 0;
731 181f2892 galberding
        // Formulate Request to enable charging
732
        if(/* checkPinVoltage() && */ !checkPinEnabled()){
733
          global.robot.requestCharging(1);
734
        }
735
        if(checkPinEnabled()){
736
          showChargingState();
737
        }
738 10bf9cc0 galberding
      break;
739 181f2892 galberding
      // ---------------------------------------
740 3c3c3bb9 galberding
    case ut_states::UT_RELEASE:
741 e5606def galberding
742 61544eee galberding
      if (global.forwardSpeed != DETECTION_SPEED){
743
          global.rpmForward[0] = DETECTION_SPEED;
744
        }
745 181f2892 galberding
        if(/* checkPinVoltage() && */ checkPinEnabled()){
746
          global.robot.requestCharging(0);
747
        }else{
748 27d4e1fa galberding
          global.motorcontrol.setMotorEnable(true);
749 8dced1c9 galberding
          // TODO: Use controlled
750 181f2892 galberding
          //Rotate -20° to free from magnet
751
          global.distcontrol.setTargetPosition(0, ROTATION_20, ROTATION_DURATION);
752 61544eee galberding
          checkForMotion();
753
          // move 1cm forward
754
          global.distcontrol.setTargetPosition(5000, 0, ROTATION_DURATION);
755
          checkForMotion();
756
          // rotate back
757 10bf9cc0 galberding
          // global.distcontrol.setTargetPosition(0, -ROTATION_20, ROTATION_DURATION);
758
          // checkForMotion();
759 019224ff galberding
760 61544eee galberding
          // global.distcontrol.setTargetPosition(5000, 0, ROTATION_DURATION);
761
          // checkForMotion();
762 181f2892 galberding
          lStrategy = LineFollowStrategy::EDGE_RIGHT;
763 3c3c3bb9 galberding
          newState = ut_states::UT_FOLLOW_LINE;
764 61544eee galberding
            // whiteBuf = -100;
765
          // lf.followLine(rpmSpeed);
766
          // setRpmSpeed(rpmSpeed);
767 181f2892 galberding
        }
768 61544eee galberding
        // lightAllLeds(Color::BLACK);
769 10bf9cc0 galberding
      break;
770
      // ---------------------------------------
771 3c3c3bb9 galberding
    case ut_states::UT_DOCKING_ERROR:
772
      newState = ut_states::UT_RELEASE;
773 10bf9cc0 galberding
      break;
774
      // ---------------------------------------
775 3c3c3bb9 galberding
    case ut_states::UT_REVERSE_TIMEOUT_ERROR:
776
      newState = ut_states::UT_IDLE;
777 10bf9cc0 galberding
      break;
778
      // ---------------------------------------
779 3c3c3bb9 galberding
    case ut_states::UT_CALIBRATION_ERROR:
780
      newState = ut_states::UT_IDLE;
781 10bf9cc0 galberding
      break;
782
      // ---------------------------------------
783 3c3c3bb9 galberding
    case ut_states::UT_WHITE_DETECTION_ERROR:
784
      newState = ut_states::UT_IDLE;
785 10bf9cc0 galberding
      break;
786
      // ---------------------------------------
787 3c3c3bb9 galberding
    case ut_states::UT_PROXY_DETECTION_ERROR:
788
      newState = ut_states::UT_IDLE;
789 10bf9cc0 galberding
      break;
790
      // ---------------------------------------
791 3c3c3bb9 galberding
    case ut_states::UT_NO_CHARGING_POWER_ERROR:
792
      newState = ut_states::UT_IDLE;
793 10bf9cc0 galberding
      break;
794
      // ---------------------------------------
795 3c3c3bb9 galberding
    case ut_states::UT_UNKNOWN_STATE_ERROR:
796
        newState = ut_states::UT_IDLE;
797 10bf9cc0 galberding
      break;
798
      // ---------------------------------------
799 3c3c3bb9 galberding
    case ut_states::UT_TEST_MAP_AUTO_STATE:
800
      chprintf((BaseSequentialStream *)&global.sercanmux1,
801
               "Start autotracking: \n");
802
803
      chprintf((BaseSequentialStream *)&global.sercanmux1,
804
               "NodeCount: %d\n", map.getNodeCount());
805
      for (int i=0; i<map.getNodeCount(); i++) {
806
        chprintf((BaseSequentialStream *)&global.sercanmux1,
807
                 "ID: %d, l: %d, r: %d \n", map.getNodeList()[i].id,
808
                 map.getNodeList()[i].left, map.getNodeList()[i].right);
809
      }
810 4d54a507 galberding
      // Start test suit for trackUpdate
811
      map.reset();
812
      global.tcase = 0;
813
      newState = UT_TEST_MAP_STATE;
814 3c3c3bb9 galberding
      break;
815 4d54a507 galberding
      // --------------------------------------------------
816 3c3c3bb9 galberding
    case ut_states::UT_TEST_MAP_STATE:{
817 e5606def galberding
      // Test suit for amiro map
818 e404e6c0 galberding
819
820 bdac5bec galberding
821 e404e6c0 galberding
      // AmiroMap map = AmiroMap(&global);
822
823 e5606def galberding
      // --------------------------------------------------
824 e404e6c0 galberding
825 4d54a507 galberding
      global.tcase++;
826 bdac5bec galberding
      // Set basic valid map configuration
827
      setAttributes(global.testmap, 0, 1, 2, 1);
828
      setAttributes(global.testmap, 1, 2, 2, 0);
829
      setAttributes(global.testmap, 2, 1, 0, 0);
830
      setAttributes(global.testmap, 3, 0, 0, 0xff);
831
      chprintf((BaseSequentialStream *)&global.sercanmux1, "Init Case: %d, res: %d\n",global.tcase, map.initialize());
832 e404e6c0 galberding
      global.testres[global.tcase] = map.get_state()->valid;
833
834 bdac5bec galberding
      global.tcase++; // 1
835
      // Test map fail if first node is flagged with end
836 e404e6c0 galberding
      setAttributes(global.testmap, 0, 1, 2, 0xff);
837
      map.initialize();
838
      global.testres[global.tcase] = !map.get_state()->valid;
839
840
      global.tcase++; // 2
841 bdac5bec galberding
      // Test if node 2 is set as start node
842 e404e6c0 galberding
      setAttributes(global.testmap, 0, 1, 2, 0);
843
      setAttributes(global.testmap, 2, 1, 0, 1);
844
      map.initialize();
845
      global.testres[global.tcase] = map.get_state()->current == 2;
846
847
      global.tcase++; // 3
848 bdac5bec galberding
      // Test if non reachable nodes will trigger invalid map
849 e404e6c0 galberding
      setAttributes(global.testmap, 3, 0, 0, 0);
850
      setAttributes(global.testmap, 4, 0, 0, 0xff);
851
      map.initialize();
852
      global.testres[global.tcase] = !map.get_state()->valid;
853
854 bdac5bec galberding
      global.tcase++; // 4
855
      // Test Reinitialization
856
      setAttributes(global.testmap, 0, 1, 2, 1);
857
      setAttributes(global.testmap, 1, 2, 2, 0);
858
      setAttributes(global.testmap, 2, 1, 0, 0);
859
      setAttributes(global.testmap, 3, 0, 0, 0xff);
860
      map.initialize();
861
      global.testres[global.tcase] = map.get_state()->valid;
862
863
      global.odometry.resetPosition();
864
      uint8_t ret = 0;
865
      global.tcase++; // 5
866
      // Test update under normal linefollowing without fixpoint
867
      ret = map.update(20000, 20000, LineFollowStrategy::EDGE_RIGHT);
868
      chprintf((BaseSequentialStream *)&global.sercanmux1,
869
               "Update test %d: Ret %d, cur %d, nex %d\n", global.tcase, ret,
870
               map.get_state()->current, map.get_state()->next);
871
      // No case should be true because neither was a node visited nor
872
      // was a fixpoint detected.
873
      global.testres[global.tcase] = (ret == 0x4);
874
875
876
      global.odometry.setPosition(1.0, 0.0, 0.0);
877 d02c536e galberding
      chprintf((BaseSequentialStream *)&global.sercanmux1, "Current Point: %d\n", global.odometry.getPosition().x);
878 bdac5bec galberding
      global.tcase++; // 6
879
      // Fixpoint on left side
880
      ret = map.update(0, 20000, LineFollowStrategy::EDGE_RIGHT);
881
      chprintf((BaseSequentialStream *)&global.sercanmux1,
882
               "Update test %d: Ret %d, cur %d, nex %d\n", global.tcase, ret,
883
               map.get_state()->current, map.get_state()->next);
884
      // No case should be true because neither was a node visited nor
885
      // was a fixpoint detected.
886
      // global.odometry
887 64cba697 galberding
      global.testres[global.tcase] = (ret == 0x2)
888
        && (map.get_state()->strategy == 0x02)
889 bdac5bec galberding
        && (map.get_state()->dist == 0)
890
        && (map.get_state()->current == 2);
891
892
893
      global.odometry.setPosition(1.5, 0.0, 0.0);
894 d02c536e galberding
      chprintf((BaseSequentialStream *)&global.sercanmux1,
895
               "Current Point: %d\n", global.odometry.getPosition().x);
896 bdac5bec galberding
      global.tcase++; // 7
897
      // Fixpoint on left side, no update should appear because fixpoint already
898
      // marked
899
      ret = map.update(0, 20000, LineFollowStrategy::EDGE_RIGHT);
900
      chprintf((BaseSequentialStream *)&global.sercanmux1,
901
               "Update test %d: Ret %d, cur %d, nex %d\n", global.tcase, ret,
902
               map.get_state()->current, map.get_state()->next);
903
      // No case should be true because neither was a node visited nor
904
      // was a fixpoint detected.
905
      global.testres[global.tcase] = (ret == 0x00)
906 64cba697 galberding
        && (map.get_state()->strategy == 0x02);
907 bdac5bec galberding
        // && (map.get_state()->dist == 0);
908
909 d02c536e galberding
      global.odometry.setPosition(1.2, 0.0, 0.0);
910
      global.tcase++; // 8
911
      // Fixpoint on left side, no update should appear because fixpoint already
912
      // marked
913
      ret = map.update(20000, 20000, LineFollowStrategy::EDGE_RIGHT);
914
      chprintf((BaseSequentialStream *)&global.sercanmux1,
915
               "Update test %d: Ret %d, cur %d, nex %d, dist %d, len %d\n", global.tcase, ret,
916
               map.get_state()->current, map.get_state()->next, map.get_state()->dist, map.get_state()->eLength);
917
      // No case should be true because neither was a node visited nor
918
      // was a fixpoint detected.
919
      global.testres[global.tcase] =
920 64cba697 galberding
          (ret == 0x04) && (map.get_state()->strategy == 0x02);
921 bdac5bec galberding
922 d02c536e galberding
      global.odometry.setPosition(.5, 0.0, 0.0);
923
      chprintf((BaseSequentialStream *)&global.sercanmux1,
924
               "Current Point: %d\n", global.odometry.getPosition().x);
925
      global.tcase++; // 9
926
      // Fixpoint on left side, no update should appear because fixpoint already
927
      // marked
928
      ret = map.update(0, 20000, LineFollowStrategy::EDGE_RIGHT);
929
      chprintf((BaseSequentialStream *)&global.sercanmux1,
930
               "Update test %d: Ret %d, cur %d, nex %d, dist %d, len %d\n",
931
               global.tcase, ret, map.get_state()->current,
932
               map.get_state()->next, map.get_state()->dist,
933
               map.get_state()->eLength);
934
      // No case should be true because neither was a node visited nor
935
      // was a fixpoint detected.
936
      global.testres[global.tcase] =
937 64cba697 galberding
        (ret == 2) &&
938
        (map.get_state()->strategy == 2) &&
939
        // (map.get_state()->dist == 0) &&
940 d02c536e galberding
        (map.get_state()->eLength == 50);
941 bdac5bec galberding
942 d02c536e galberding
      global.odometry.setPosition(.75, 0.0, 0.0);
943
      chprintf((BaseSequentialStream *)&global.sercanmux1,
944
               "Current Point: %d\n", global.odometry.getPosition().x);
945
      global.tcase++; // 10
946
      // Fixpoint on left side, no update should appear because fixpoint already
947
      // marked
948
      ret = map.update(20000, 20000, LineFollowStrategy::EDGE_RIGHT);
949
      chprintf((BaseSequentialStream *)&global.sercanmux1,
950
               "Update test %d: Ret %d, cur %d, nex %d, dist %d, len %d\n",
951
               global.tcase, ret, map.get_state()->current,
952
               map.get_state()->next, map.get_state()->dist,
953
               map.get_state()->eLength);
954
      // No case should be true because neither was a node visited nor
955
      // was a fixpoint detected.
956
      global.testres[global.tcase] =
957 64cba697 galberding
          (ret == 4) && (map.get_state()->strategy == 2) &&
958
          // (map.get_state()->dist == 50)
959
         (map.get_state()->eLength == 50);
960 bdac5bec galberding
961 e404e6c0 galberding
      int failed = 0;
962
      int passed = 0;
963
      for (int i = 0; i <= global.tcase; i++) {
964
        if (global.testres[i]) {
965
          passed++;
966
          chprintf((BaseSequentialStream *)&global.sercanmux1,
967
                   "Test %d Passed!\n", i);
968
        } else {
969
          failed++;
970
          chprintf((BaseSequentialStream *)&global.sercanmux1,
971
                   "Test %d Failed\n", i);
972
        }
973 27d4e1fa galberding
      }
974 e404e6c0 galberding
      chprintf((BaseSequentialStream *)&global.sercanmux1,
975
               "Total: %d, Passed: %d, Failed: %d\n", global.tcase + 1, passed,
976
               failed);
977
978 3c3c3bb9 galberding
      newState = ut_states::UT_IDLE;
979 e404e6c0 galberding
      break;
980
    }
981
      // --------------------------------------------------
982
    default:
983 3c3c3bb9 galberding
      newState = ut_states::UT_UNKNOWN_STATE_ERROR;
984 e404e6c0 galberding
      break;
985
    }
986
987 e5606def galberding
    // In case a new state is set:
988
    // 1. Record the state transition
989 3c3c3bb9 galberding
    if (AMIRO_MAP_AUTO_TRACKING) {
990
      // map.trackUpdate(WL, WR, lStrategy, currentState);
991
    }
992
993 e404e6c0 galberding
    if (currentState != newState){
994 e5606def galberding
995
      global.stateTransitionCounter++;
996
      // Clear all state transitions to prevent overflow
997
      if (global.stateTransitionCounter >= 255) {
998
        global.stateTransitionCounter = 0;
999
        for (int i = 0; i < 24; i++) {
1000
          global.stateTracker[i] = 0;
1001
        }
1002
}
1003
      // Transmit the new state over can
1004 e404e6c0 galberding
      chprintf((BaseSequentialStream*)&global.sercanmux1, "Transmit state %d\n", newState);
1005
      global.robot.transmitState(newState);
1006 e5606def galberding
1007
      // Increase state count for specific state
1008
      // TODO: Improve with dictionary or other than switch case
1009 3c3c3bb9 galberding
      if (newState == ut_states::UT_IDLE)
1010
        {global.stateTracker[ut_states::UT_IDLE] += 1;}
1011
      else if (newState == ut_states::UT_FOLLOW_LINE)
1012
        {global.stateTracker[ut_states::UT_FOLLOW_LINE] += 1;}
1013
      else if (newState == ut_states::UT_DETECT_STATION)
1014
        {global.stateTracker[ut_states::UT_DETECT_STATION] += 1;}
1015
      else if (newState == ut_states::UT_REVERSE)
1016
        {global.stateTracker[ut_states::UT_REVERSE] += 1;}
1017
      else if (newState == ut_states::UT_PUSH_BACK)
1018
        {global.stateTracker[ut_states::UT_PUSH_BACK] += 1;}
1019
      else if (newState == ut_states::UT_CHECK_POSITIONING)
1020
        {global.stateTracker[ut_states::UT_CHECK_POSITIONING] += 1;}
1021
      else if (newState == ut_states::UT_CHECK_VOLTAGE)
1022
        {global.stateTracker[ut_states::UT_CHECK_VOLTAGE] += 1;}
1023
      else if (newState == ut_states::UT_CHARGING)
1024
        {global.stateTracker[ut_states::UT_CHARGING] += 1;}
1025
      else if (newState == ut_states::UT_RELEASE)
1026
        {global.stateTracker[ut_states::UT_RELEASE] += 1;}
1027
      else if (newState == ut_states::UT_RELEASE_TO_CORRECT)
1028
        {global.stateTracker[ut_states::UT_RELEASE_TO_CORRECT] += 1;}
1029
      else if (newState == ut_states::UT_CORRECT_POSITIONING)
1030
        {global.stateTracker[ut_states::UT_CORRECT_POSITIONING] += 1;}
1031
      else if (newState == ut_states::UT_TURN)
1032
        {global.stateTracker[ut_states::UT_TURN] += 1;}
1033
      else if (newState == ut_states::UT_INACTIVE)
1034
        {global.stateTracker[ut_states::UT_INACTIVE] += 1;}
1035
      else if (newState == ut_states::UT_CALIBRATION)
1036
        {global.stateTracker[ut_states::UT_CALIBRATION] += 1;}
1037
      else if (newState == ut_states::UT_CALIBRATION_CHECK)
1038
        {global.stateTracker[ut_states::UT_CALIBRATION_CHECK] += 1;}
1039
      else if (newState == ut_states::UT_DEVIATION_CORRECTION)
1040
        {global.stateTracker[ut_states::UT_DEVIATION_CORRECTION] += 1;}
1041
      else if (newState == ut_states::UT_DOCKING_ERROR)
1042
        {global.stateTracker[16+(-ut_states::UT_DOCKING_ERROR)] += 1;}
1043
      else if (newState == ut_states::UT_REVERSE_TIMEOUT_ERROR)
1044
        {global.stateTracker[16+(-ut_states::UT_REVERSE_TIMEOUT_ERROR)] += 1;}
1045
      else if (newState == ut_states::UT_CALIBRATION_ERROR)
1046
        {global.stateTracker[16+(-ut_states::UT_CALIBRATION_ERROR)] += 1;}
1047
      else if (newState == ut_states::UT_WHITE_DETECTION_ERROR)
1048
        {global.stateTracker[16+(-ut_states::UT_WHITE_DETECTION_ERROR)] += 1;}
1049
      else if (newState == ut_states::UT_PROXY_DETECTION_ERROR)
1050
        {global.stateTracker[16+(-ut_states::UT_PROXY_DETECTION_ERROR)] += 1;}
1051
      else if (newState == ut_states::UT_NO_CHARGING_POWER_ERROR)
1052
        {global.stateTracker[16+(-ut_states::UT_NO_CHARGING_POWER_ERROR)] += 1;}
1053
      else if (newState == ut_states::UT_UNKNOWN_STATE_ERROR)
1054
        {global.stateTracker[16+(-ut_states::UT_UNKNOWN_STATE_ERROR)] += 1;}
1055 e404e6c0 galberding
    }
1056 e5606def galberding
1057
    // Keep track of last state and set the new state for next iteration
1058 e404e6c0 galberding
    prevState = currentState;
1059
    currentState = newState;
1060
1061 5d138bca galberding
    this->sleep(CAN::UPDATE_PERIOD);
1062
  }
1063 58fe0e0b Thomas Schöpping
1064
  return RDY_OK;
1065
}