Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (23.786 KB)

1 10bf9cc0 galberding
// #include "userthread.hpp"
2 58fe0e0b Thomas Schöpping
#include "global.hpp"
3 10bf9cc0 galberding
#include <cmath>
4 05d54823 galberding
#include "linefollow.hpp" 
5 10bf9cc0 galberding
// #include <cmath>
6
// #include "global.hpp"
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
 * 
19
 * @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
    
79
  }
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
  
98
  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
    
126
  // 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
      rpmSpeed[0] = rpmSpeed[0] / 4;
142
      rpmSpeed[1] = rpmSpeed[1] / 4;
143
  }
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
  
153
}
154
155
156 9c46b728 galberding
/**
157
 * Blocks as long as the position changes.
158
 */
159 181f2892 galberding
void UserThread::checkForMotion(){
160 9c46b728 galberding
  int motion = 1;
161
  int led = 0;
162
  types::position oldPos = global.odometry.getPosition();
163
  while(motion){
164 181f2892 galberding
    this->sleep(500);
165 9c46b728 galberding
    types::position tmp = global.odometry.getPosition();
166
    motion = abs(oldPos.x - tmp.x)+ abs(oldPos.y - tmp.y)+abs(oldPos.z - tmp.z);
167
    oldPos = tmp;
168
      global.robot.setLightColor((led + 1) % 8, Color(Color::YELLOW));
169
      global.robot.setLightColor(led % 8, Color(Color::BLACK));
170
      led++;
171
  }
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
  return global.ltc4412.isPluggedIn(); 
195
}
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
  
211 9c46b728 galberding
  // Amiro moved, docking was not successful
212 10bf9cc0 galberding
  // if ((start.x + stop_.x)  || (start.y + stop_.y)){
213
  if (abs(start.x - stop_.x) > 0 /* || (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
  
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
  int32_t res = 0; 
239
  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 e2002d0e galberding
251 58fe0e0b Thomas Schöpping
UserThread::UserThread() :
252
  chibios_rt::BaseStaticThread<USER_THREAD_STACK_SIZE>()
253
{
254
}
255
256
UserThread::~UserThread()
257
{
258
}
259
260
msg_t
261
UserThread::main()
262
{
263 5d138bca galberding
  /*
264
   * SETUP
265
   */
266 181f2892 galberding
  // User thread state:
267
268 5d138bca galberding
  for (uint8_t led = 0; led < 8; ++led) {
269
    global.robot.setLightColor(led, Color(Color::BLACK));
270
  }
271
  running = false;
272 10bf9cc0 galberding
  LineFollowStrategy lStrategy = LineFollowStrategy::EDGE_RIGHT;
273 5d138bca galberding
  LineFollow lf(&global);
274
  /*
275
   * LOOP
276
   */
277
  while (!this->shouldTerminate())
278
  {
279 181f2892 galberding
    /*
280
    * read accelerometer z-value
281
    */
282
    accel_z = global.lis331dlh.getAccelerationForce(LIS331DLH::AXIS_Z);
283
        
284
    if (accel_z < -900 /*-0.9g*/) { 
285
      // Start line following when AMiRo is rotated
286 10bf9cc0 galberding
      if(currentState == states::INACTIVE){
287 fbcb25cc galberding
        newState = states::FOLLOW_LINE;
288 181f2892 galberding
      }else{
289 fbcb25cc galberding
        newState = states::IDLE;
290 181f2892 galberding
      }
291
      lightAllLeds(Color::GREEN);
292
      this->sleep(1000);
293
      lightAllLeds(Color::BLACK);
294 c76baf23 Georg Alberding
295 d607fcef galberding
    // If message was received handle it here:
296
    } else if(global.msgReceived){
297
      global.msgReceived = false;
298 181f2892 galberding
      // running = true;
299 d607fcef galberding
      switch(global.lfStrategy){
300 10bf9cc0 galberding
        case msg_content::MSG_START:
301
          newState = states::CALIBRATION_CHECK;
302
        break;
303
        case msg_content::MSG_STOP:
304 fbcb25cc galberding
          newState = states::IDLE;
305 10bf9cc0 galberding
        break;
306
        case msg_content::MSG_EDGE_RIGHT:
307 fbcb25cc galberding
          // newState = states::FOLLOW_LINE;
308 d607fcef galberding
          lStrategy = LineFollowStrategy::EDGE_RIGHT;
309 10bf9cc0 galberding
        break;
310
        case  msg_content::MSG_EDGE_LEFT:
311 fbcb25cc galberding
          // newState = states::FOLLOW_LINE;
312 d607fcef galberding
          lStrategy = LineFollowStrategy::EDGE_LEFT;
313 10bf9cc0 galberding
        break;
314
        case msg_content::MSG_FUZZY:
315 fbcb25cc galberding
          // newState = states::FOLLOW_LINE;
316 d607fcef galberding
          lStrategy = LineFollowStrategy::FUZZY;
317 10bf9cc0 galberding
        break;
318
        case msg_content::MSG_DOCK:
319 fbcb25cc galberding
          newState = states::DETECT_STATION;
320 10bf9cc0 galberding
        break;
321
        case msg_content::MSG_UNDOCK:
322 fbcb25cc galberding
          newState = states::RELEASE;
323 10bf9cc0 galberding
        break;
324
        case msg_content::MSG_CHARGE:
325 fbcb25cc galberding
          newState = states::CHARGING;
326 10bf9cc0 galberding
        break;
327
        case msg_content::MSG_RESET_ODOMETRY:
328
          global.odometry.resetPosition();
329
        break;
330
        case msg_content::MSG_CALIBRATE_BLACK:
331
          proxCalib.calibrateBlack = true;
332
          // global.odometry.resetPosition();
333
          newState = states::CALIBRATION;
334
        break;
335
        case msg_content::MSG_CALIBRATE_WHITE:
336
          proxCalib.calibrateBlack = false;
337
          newState = states::CALIBRATION;
338
        break;
339 d607fcef galberding
        default:
340 fbcb25cc galberding
          newState = states::IDLE;
341 10bf9cc0 galberding
        break;
342 d607fcef galberding
      }
343 5d138bca galberding
    }
344 10bf9cc0 galberding
    // newState = currentState;
345 d607fcef galberding
346 181f2892 galberding
    // Get sensor data 
347 fbcb25cc galberding
    // uint16_t WL = global.vcnl4020[constants::DiWheelDrive::PROX_WHEEL_LEFT].getProximityScaledWoOffset();
348
    // uint16_t WR = global.vcnl4020[constants::DiWheelDrive::PROX_WHEEL_RIGHT].getProximityScaledWoOffset();
349 019224ff galberding
    for(int i=0; i<8;i++){
350
      rProx[i] = global.robot.getProximityRingValue(i);
351
    }
352 b24df8ad galberding
353
    // Continously update devication values
354
    meanDeviation(rProx[0] & 0xFFF0, rProx[7] & 0xFFF0);
355 181f2892 galberding
    // int FL = global.vcnl4020[constants::DiWheelDrive::PROX_FRONT_LEFT].getProximityScaledWoOffset();
356
    // int FR = global.vcnl4020[constants::DiWheelDrive::PROX_FRONT_RIGHT].getProximityScaledWoOffset();
357 10bf9cc0 galberding
    switch(currentState){
358
      case states::INACTIVE:
359
        // Dummy state to deactivate every interaction
360
      break;
361
      // ---------------------------------------
362
      case states::CALIBRATION_CHECK:
363
        // global.robot.calibrate();
364
        if(global.linePID.BThresh >= global.linePID.WThresh){
365
          newState = states::CALIBRATION_ERROR;
366
        }else{
367
          newState = states::FOLLOW_LINE;
368
        }
369
      break;
370
      // ---------------------------------------
371
      case states::CALIBRATION:
372
        /* Calibrate the global thresholds for black or white.
373
            This values will be used by the line follow object
374
        */
375
376
        proxCalib.buf = 0;
377
        if(proxCalib.calibrateBlack){
378
          chprintf((BaseSequentialStream*)&global.sercanmux1, "Black Calibration, Place AMiRo on black Surface!\n");
379
          global.robot.calibrate();
380
        }
381
        for(int i=0; i <= proxCalib.meanWindow; i++){
382
          proxCalib.buf += global.vcnl4020[constants::DiWheelDrive::PROX_FRONT_LEFT].getProximityScaledWoOffset() 
383
                          + global.vcnl4020[constants::DiWheelDrive::PROX_FRONT_RIGHT].getProximityScaledWoOffset(); 
384
          this->sleep(CAN::UPDATE_PERIOD);
385
        }
386
        proxCalib.buf = proxCalib.buf / (2*proxCalib.meanWindow);
387
        
388
        if(proxCalib.calibrateBlack){
389
          global.linePID.BThresh = proxCalib.buf;
390
        }else  {
391
          global.linePID.WThresh  = proxCalib.buf;
392
        }
393
          chprintf((BaseSequentialStream*)&global.sercanmux1, "Black: %d, White: %d!\n", global.linePID.BThresh, global.linePID.WThresh);
394
395
        newState = states::IDLE;
396
      break;
397
      // ---------------------------------------
398 181f2892 galberding
      case states::IDLE:
399 27d4e1fa galberding
        global.motorcontrol.setMotorEnable(true);
400 181f2892 galberding
        setRpmSpeed(stop);
401
        if(/* checkPinVoltage() && */ checkPinEnabled()){
402
          global.robot.requestCharging(0);
403
        }
404 10bf9cc0 galberding
        // pCtrl.pFactor = 0;
405
        pCtrl.staticCont = 0;
406 fbcb25cc galberding
        utCount.whiteCount = 0;
407 10bf9cc0 galberding
        utCount.ringProxCount = 0;
408 27d4e1fa galberding
        utCount.errorCount = 0;
409 10bf9cc0 galberding
        newState = states::INACTIVE;
410
      break;
411 181f2892 galberding
      // ---------------------------------------
412
      case states::FOLLOW_LINE:
413
      // Set correct forward speed to every strategy
414
        if (global.forwardSpeed != global.rpmForward[0]){
415
          global.forwardSpeed = global.rpmForward[0];
416
        }
417
        
418
        if(lf.getStrategy() != lStrategy){
419 9c46b728 galberding
          lf.setStrategy(lStrategy);
420
        }
421 5d138bca galberding
422 181f2892 galberding
        if(lf.followLine(rpmSpeed)){
423 fbcb25cc galberding
          utCount.whiteCount++;
424 10bf9cc0 galberding
          if(utCount.whiteCount >= WHITE_DETETION_TIMEOUT){
425
            setRpmSpeed(stop);
426
            utCount.whiteCount = 0;
427
            newState = states::WHITE_DETECTION_ERROR;
428 9c46b728 galberding
          }
429 181f2892 galberding
        }else{
430 fbcb25cc galberding
          utCount.whiteCount = 0;
431 9c46b728 galberding
        }
432 e2002d0e galberding
433 10bf9cc0 galberding
        preventCollision(rpmSpeed, rProx);
434
        // proxSectorSpeedCorrection(rpmSpeed, rProx);
435 61544eee galberding
436 10bf9cc0 galberding
        if(utCount.ringProxCount > RING_PROX_DETECTION_TIMEOUT){
437
          utCount.ringProxCount = 0;
438
          newState = states::TURN;
439 61544eee galberding
        }
440
441 c9fa414d galberding
        if (lf.getStrategy() == LineFollowStrategy::FUZZY){
442
          setRpmSpeedFuzzy(rpmSpeed);
443
        }else{
444
445
          setRpmSpeed(rpmSpeed);
446
        }
447 181f2892 galberding
        
448 10bf9cc0 galberding
      break;
449 181f2892 galberding
      // ---------------------------------------
450 fbcb25cc galberding
      case states::TURN:
451
        checkForMotion();
452
        // Check if only front sensors are active 
453
        if(checkFrontalObject()){
454 10bf9cc0 galberding
          global.distcontrol.setTargetPosition(0, 2792526, ROTATION_DURATION);
455 fbcb25cc galberding
          // BaseThread::sleep(8000);
456
          checkForMotion();
457
          newState = states::FOLLOW_LINE;
458 10bf9cc0 galberding
          // lf.promptStrategyChange(LineFollowStrategy::EDGE_LEFT);
459 fbcb25cc galberding
        }else{
460 10bf9cc0 galberding
          newState = states::PROXY_DETECTION_ERROR;
461 fbcb25cc galberding
        }
462 10bf9cc0 galberding
      break;
463 fbcb25cc galberding
      // ---------------------------------------
464 181f2892 galberding
      case states::DETECT_STATION:
465 61544eee galberding
        if (global.forwardSpeed != DETECTION_SPEED){
466
          global.forwardSpeed = DETECTION_SPEED;
467
        }
468 181f2892 galberding
        if(lf.getStrategy() != LineFollowStrategy::EDGE_RIGHT){
469
          lf.setStrategy(LineFollowStrategy::EDGE_RIGHT);
470
        }
471
472
        lf.followLine(rpmSpeed);
473
        setRpmSpeed(rpmSpeed);
474
        // // Detect marker before docking station
475 019224ff galberding
        // if ((WL+WR) < PROXY_WHEEL_THRESH){
476
        // Use proxy ring 
477
        if ((rProx[3]+rProx[4]) > RING_PROX_FRONT_THRESH){
478
479 d607fcef galberding
          setRpmSpeed(stop);
480 181f2892 galberding
          checkForMotion();
481
          // 180° Rotation 
482
          global.distcontrol.setTargetPosition(0, ROTATION_180, ROTATION_DURATION);
483
          // BaseThread::sleep(8000);
484
          checkForMotion();
485
          newState = states::CORRECT_POSITIONING;
486 9c46b728 galberding
        }
487 10bf9cc0 galberding
      break;
488 181f2892 galberding
      // ---------------------------------------
489
      case states::CORRECT_POSITIONING:
490 019224ff galberding
        if (global.forwardSpeed != CHARGING_SPEED){
491
          global.forwardSpeed = CHARGING_SPEED;
492
        }
493 181f2892 galberding
        if(lf.getStrategy() != LineFollowStrategy::EDGE_LEFT){
494
          lf.promptStrategyChange(LineFollowStrategy::EDGE_LEFT);
495 9c46b728 galberding
        }
496 181f2892 galberding
        lf.followLine(rpmSpeed);
497
        setRpmSpeed(rpmSpeed);
498 9c46b728 galberding
499 10bf9cc0 galberding
        utCount.stateTime++;
500
        if (utCount.stateTime >= DOCKING_CORRECTION_TIMEOUT){
501
          utCount.stateTime = 0;
502 181f2892 galberding
          newState = states::REVERSE;
503
          setRpmSpeed(stop);
504
          checkForMotion();
505
        }
506 10bf9cc0 galberding
      break;
507 181f2892 galberding
      // ---------------------------------------
508
      case states::REVERSE:
509
        if(lf.getStrategy() != LineFollowStrategy::REVERSE){
510
          lf.setStrategy(LineFollowStrategy::REVERSE);
511
        }
512
        lf.followLine(rpmSpeed);
513
        setRpmSpeed(rpmSpeed);
514 b24df8ad galberding
        // utCount.stateTime++;
515 58fe0e0b Thomas Schöpping
516 b24df8ad galberding
        // Docking is only successful if Deviation is in range and sensors are at their max values.
517
        if((rProx[0] >= PROX_MAX_VAL) && (rProx[7] >= PROX_MAX_VAL) && ((devCor.currentDeviation > -MAX_DEVIATION_FACTOR) &&  (devCor.currentDeviation < MAX_DEVIATION_FACTOR) )){
518 61544eee galberding
          // setRpmSpeed(stop);
519
          // checkForMotion();
520 10bf9cc0 galberding
          utCount.stateTime = 0;
521 27d4e1fa galberding
          newState = states::PUSH_BACK;
522 b24df8ad galberding
        }else if ((devCor.currentDeviation <= -MAX_DEVIATION_FACTOR) && ((rProx[0] > DEVIATION_DIST_THRESH) || (rProx[7] > DEVIATION_DIST_THRESH))){
523
          // Case R 
524
          utCount.stateTime = 0;
525
          setRpmSpeed(stop);
526
          devCor.RCase = true;
527
          lightAllLeds(Color::YELLOW);
528
          newState = states::DEVIATION_CORRECTION;
529
        }else if ((devCor.currentDeviation >= MAX_DEVIATION_FACTOR) && ((rProx[0] > DEVIATION_DIST_THRESH) || (rProx[7] > DEVIATION_DIST_THRESH))){
530
          // Case L 
531
          utCount.stateTime = 0;
532
          setRpmSpeed(stop);
533
          devCor.RCase = false;
534
          lightAllLeds(Color::WHITE);
535
          newState = states::DEVIATION_CORRECTION;
536 10bf9cc0 galberding
        }else if (utCount.stateTime >= REVERSE_DOCKING_TIMEOUT){
537
          setRpmSpeed(stop);
538
          utCount.stateTime = 0;
539
          utCount.errorCount++;
540
          if (utCount.errorCount >= DOCKING_ERROR_THRESH){
541
            newState = states::DOCKING_ERROR;
542
          }else{
543
            newState = states::CORRECT_POSITIONING;
544
          }
545 27d4e1fa galberding
        }
546 10bf9cc0 galberding
547
      break;
548 27d4e1fa galberding
      // ---------------------------------------
549 b24df8ad galberding
      case states::DEVIATION_CORRECTION:
550
        // if(lf.getStrategy() != LineFollowStrategy::REVERSE){
551
        //   lf.setStrategy(LineFollowStrategy::REVERSE);
552
        // }
553
        // lf.followLine(rpmSpeed);
554
        // setRpmSpeed(rpmSpeed);
555
        if(utCount.stateTime < DEVIATION_CORRECTION_DURATION / 2 ){
556
          if(devCor.RCase){
557
            rpmSpeed[0] = 0;
558
            rpmSpeed[1] = DEVIATION_CORRECTION_SPEED;
559
          }else {
560
            rpmSpeed[0] = DEVIATION_CORRECTION_SPEED;
561
            rpmSpeed[1] = 0;
562
          }
563
          setRpmSpeed(rpmSpeed);
564
        }else if ((utCount.stateTime >= DEVIATION_CORRECTION_DURATION / 2) && (utCount.stateTime < DEVIATION_CORRECTION_DURATION)){
565
          if(devCor.RCase){
566
            rpmSpeed[0] = DEVIATION_CORRECTION_SPEED;
567
            rpmSpeed[1] = 0;
568
          }else {
569
            rpmSpeed[0] = 0;
570
            rpmSpeed[1] = DEVIATION_CORRECTION_SPEED;
571
          }
572
          setRpmSpeed(rpmSpeed);
573
        }else if (utCount.stateTime >= DEVIATION_CORRECTION_DURATION + 10) {  
574
          // Wait to clear the mean window buffer
575
          setRpmSpeed(stop);
576
        }else{
577
          utCount.stateTime = 0;
578
          newState = states::REVERSE;
579
          setRpmSpeed(stop);
580
        }
581
582
        utCount.stateTime++;
583
584
585
        // if (utCount.stateTime > PUSH_BACK_TIMEOUT){
586
        //   utCount.stateTime = 0;
587
        //   newState = states::CHECK_POSITIONING;
588
        // }
589
      break;
590
      // ---------------------------------------
591 27d4e1fa galberding
      case states::PUSH_BACK:
592
        if(lf.getStrategy() != LineFollowStrategy::REVERSE){
593
          lf.setStrategy(LineFollowStrategy::REVERSE);
594
        }
595
        lf.followLine(rpmSpeed);
596
        setRpmSpeed(rpmSpeed);
597
598 10bf9cc0 galberding
        utCount.stateTime++;
599
        if (utCount.stateTime > PUSH_BACK_TIMEOUT){
600
          utCount.stateTime = 0;
601 181f2892 galberding
          newState = states::CHECK_POSITIONING;
602
        }
603 10bf9cc0 galberding
      break;
604 181f2892 galberding
      // ---------------------------------------
605
      case states::CHECK_POSITIONING:
606 61544eee galberding
        setRpmSpeed(stop);
607
        checkForMotion();
608 27d4e1fa galberding
        if(checkDockingSuccess()){
609
          newState = states::CHECK_VOLTAGE;
610
        }else{
611
          utCount.errorCount++;
612
          newState = states::CORRECT_POSITIONING;
613 10bf9cc0 galberding
          if (utCount.errorCount >= DOCKING_ERROR_THRESH){
614
              newState = states::DOCKING_ERROR;
615 27d4e1fa galberding
            }
616
        }
617 10bf9cc0 galberding
      break;
618 181f2892 galberding
      // ---------------------------------------
619 ba75ee1d galberding
      case states::CHECK_VOLTAGE:
620
        if(!checkPinEnabled()){
621
          global.robot.requestCharging(1);
622
        } else {
623
          if(checkPinVoltage()){
624
            // Pins are under voltage -> correctly docked 
625 10bf9cc0 galberding
            
626 ba75ee1d galberding
            newState = states::CHARGING;
627
          }else{
628 27d4e1fa galberding
            utCount.errorCount++;
629 ba75ee1d galberding
            // No voltage on pins -> falsely docked
630
            // deactivate pins
631 27d4e1fa galberding
            global.motorcontrol.setMotorEnable(true);
632 ba75ee1d galberding
            global.robot.requestCharging(0);
633 27d4e1fa galberding
            // TODO: Soft release when docking falsely
634 61544eee galberding
            if((rProx[0] >= PROX_MAX_VAL) && (rProx[7] >= PROX_MAX_VAL)){
635
              newState = states::RELEASE_TO_CORRECT;
636
            } else {
637 27d4e1fa galberding
              newState = states::RELEASE_TO_CORRECT; //states::CORRECT_POSITIONING; 
638
            }
639
640
            if (utCount.errorCount > DOCKING_ERROR_THRESH){
641 10bf9cc0 galberding
              newState = states::DOCKING_ERROR;
642 61544eee galberding
            }
643 ba75ee1d galberding
          }
644
        }
645 10bf9cc0 galberding
      break;
646 019224ff galberding
      // ---------------------------------------
647
      case states::RELEASE_TO_CORRECT:
648 27d4e1fa galberding
649 019224ff galberding
        global.distcontrol.setTargetPosition(0, ROTATION_20, ROTATION_DURATION);
650
        checkForMotion();
651
        // move 1cm forward
652
        global.distcontrol.setTargetPosition(5000, 0, ROTATION_DURATION);
653
        checkForMotion();
654
        // rotate back
655
        global.distcontrol.setTargetPosition(0, -2*ROTATION_20, ROTATION_DURATION);
656
        checkForMotion();
657
658 10bf9cc0 galberding
        global.distcontrol.setTargetPosition(1500, 0, ROTATION_DURATION);
659 019224ff galberding
        checkForMotion();
660
        newState = states::CORRECT_POSITIONING;
661 10bf9cc0 galberding
      break;
662 27d4e1fa galberding
      // ---------------------------------------
663 181f2892 galberding
      case states::CHARGING:
664 27d4e1fa galberding
        global.motorcontrol.setMotorEnable(false);
665 10bf9cc0 galberding
        utCount.errorCount = 0;
666 181f2892 galberding
        // Formulate Request to enable charging
667
        if(/* checkPinVoltage() && */ !checkPinEnabled()){
668
          global.robot.requestCharging(1);
669
        }
670
        if(checkPinEnabled()){
671
          showChargingState();
672
        }
673 10bf9cc0 galberding
      break;
674 181f2892 galberding
      // ---------------------------------------
675
      case states::RELEASE:
676 61544eee galberding
      if (global.forwardSpeed != DETECTION_SPEED){
677
          global.rpmForward[0] = DETECTION_SPEED;
678
        }
679 181f2892 galberding
        if(/* checkPinVoltage() && */ checkPinEnabled()){
680
          global.robot.requestCharging(0);
681
        }else{
682 27d4e1fa galberding
          global.motorcontrol.setMotorEnable(true);
683
684 181f2892 galberding
          //Rotate -20° to free from magnet
685
          global.distcontrol.setTargetPosition(0, ROTATION_20, ROTATION_DURATION);
686 61544eee galberding
          checkForMotion();
687
          // move 1cm forward
688
          global.distcontrol.setTargetPosition(5000, 0, ROTATION_DURATION);
689
          checkForMotion();
690
          // rotate back
691 10bf9cc0 galberding
          // global.distcontrol.setTargetPosition(0, -ROTATION_20, ROTATION_DURATION);
692
          // checkForMotion();
693 019224ff galberding
694 61544eee galberding
          // global.distcontrol.setTargetPosition(5000, 0, ROTATION_DURATION);
695
          // checkForMotion();
696 181f2892 galberding
          lStrategy = LineFollowStrategy::EDGE_RIGHT;
697
          newState = states::FOLLOW_LINE;
698 61544eee galberding
            // whiteBuf = -100;
699
          // lf.followLine(rpmSpeed);
700
          // setRpmSpeed(rpmSpeed);
701 181f2892 galberding
        }
702 61544eee galberding
        // lightAllLeds(Color::BLACK);
703 10bf9cc0 galberding
      break;
704
      // ---------------------------------------
705
      case states::DOCKING_ERROR:
706
        newState = states::RELEASE;
707
      break;
708
      // ---------------------------------------
709
      case states::REVERSE_TIMEOUT_ERROR:
710
        newState = states::IDLE;
711
      break;
712
      // ---------------------------------------
713
      case states::CALIBRATION_ERROR:
714
        newState = states::IDLE;
715
      break;
716
      // ---------------------------------------
717
      case states::WHITE_DETECTION_ERROR:
718
        newState = states::IDLE;
719
      break;
720
      // ---------------------------------------
721
      case states::PROXY_DETECTION_ERROR:
722
        newState = states::IDLE;
723
      break;
724
      // ---------------------------------------
725
      case states::NO_CHARGING_POWER_ERROR:
726
        newState = states::IDLE;
727
      break;
728
      // ---------------------------------------
729
      case states::UNKNOWN_STATE_ERROR:
730
        newState = states::IDLE;
731
      break;
732
      // ---------------------------------------
733 181f2892 galberding
      default:
734 10bf9cc0 galberding
        newState = states::UNKNOWN_STATE_ERROR;
735
      break;
736 181f2892 galberding
      }
737 10bf9cc0 galberding
      if (currentState != newState){
738 fbcb25cc galberding
        chprintf((BaseSequentialStream*)&global.sercanmux1, "Transmit state %d\n", newState);
739 27d4e1fa galberding
        global.robot.transmitState(newState);
740
      }
741 10bf9cc0 galberding
      prevState = currentState;
742
      currentState = newState;
743
      if (utCount.stateCount > CAN_TRANSMIT_STATE_THRESH){
744
          utCount.stateCount = 0;
745
        // chprintf((BaseSequentialStream*)&global.sercanmux1, "Transmit state %d\n", newState);
746
        global.robot.transmitState(currentState);
747
        // global.robot.setOdometry(global.odometry.getPosition());
748
        
749
      }else{
750
        utCount.stateCount++;
751
      }
752 5d138bca galberding
    this->sleep(CAN::UPDATE_PERIOD);
753
  }
754 58fe0e0b Thomas Schöpping
755
  return RDY_OK;
756
}