Statistics
| Branch: | Tag: | Revision:

amiro-os / devices / DiWheelDrive / userthread.cpp @ 8dced1c9

History | View | Annotate | Download (27.6 KB)

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