Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (15.776 KB)

1 58fe0e0b Thomas Schöpping
#include "userthread.hpp"
2
#include "global.hpp"
3 05d54823 galberding
#include "linefollow.hpp" 
4 c76baf23 Georg Alberding
5 58fe0e0b Thomas Schöpping
using namespace amiro;
6
7
extern Global global;
8
9
// a buffer for the z-value of the accelerometer
10
int16_t accel_z;
11 5d138bca galberding
bool running = false;
12 58fe0e0b Thomas Schöpping
13
14 181f2892 galberding
/**
15
 * Set speed.
16
 * 
17
 * @param rpmSpeed speed for left and right wheel in rounds/min
18
 */
19 c9fa414d galberding
void UserThread::setRpmSpeedFuzzy(const int (&rpmSpeed)[2]) {
20 5d138bca galberding
  global.motorcontrol.setTargetRPM(rpmSpeed[constants::DiWheelDrive::LEFT_WHEEL] * 1000000, rpmSpeed[constants::DiWheelDrive::RIGHT_WHEEL] * 1000000);
21 58fe0e0b Thomas Schöpping
}
22
23 c9fa414d galberding
void UserThread::setRpmSpeed(const int (&rpmSpeed)[2]) {
24
  global.motorcontrol.setTargetRPM(rpmSpeed[constants::DiWheelDrive::LEFT_WHEEL], rpmSpeed[constants::DiWheelDrive::RIGHT_WHEEL]);
25
}
26
27 181f2892 galberding
void UserThread::lightOneLed(Color color, int idx){
28 5d138bca galberding
  global.robot.setLightColor(idx, Color(color));
29
}
30 58fe0e0b Thomas Schöpping
31 181f2892 galberding
void UserThread::lightAllLeds(Color color){
32 5d138bca galberding
  int led = 0;
33
  for(led=0; led<8; led++){
34
        lightOneLed(color, led);
35
      }
36 58fe0e0b Thomas Schöpping
}
37
38 181f2892 galberding
void UserThread::showChargingState(){
39
  uint8_t numLeds = global.robot.getPowerStatus().state_of_charge / 12;
40
  Color color = Color::GREEN;
41
  if (numLeds <= 2){
42
    color = Color::RED;
43
  }else if(numLeds <= 6){
44
    color = Color::YELLOW;
45
  }
46
  for (int i=0; i<numLeds; i++){
47
    lightOneLed(color, i);
48
    this->sleep(300);
49 9c46b728 galberding
  }
50 181f2892 galberding
  this->sleep(1000);
51
  lightAllLeds(Color::BLACK);
52 9c46b728 galberding
}
53
54
/**
55
 * Blocks as long as the position changes.
56
 */
57 181f2892 galberding
void UserThread::checkForMotion(){
58 9c46b728 galberding
  int motion = 1;
59
  int led = 0;
60
  types::position oldPos = global.odometry.getPosition();
61
  while(motion){
62 181f2892 galberding
    this->sleep(500);
63 9c46b728 galberding
    types::position tmp = global.odometry.getPosition();
64
    motion = abs(oldPos.x - tmp.x)+ abs(oldPos.y - tmp.y)+abs(oldPos.z - tmp.z);
65
    oldPos = tmp;
66
      global.robot.setLightColor((led + 1) % 8, Color(Color::YELLOW));
67
      global.robot.setLightColor(led % 8, Color(Color::BLACK));
68
      led++;
69
  }
70
}
71
72 fbcb25cc galberding
bool UserThread::checkFrontalObject(){
73
  uint32_t thresh = 1000;
74
  uint32_t prox;
75
  for(int i=0; i<8; i++){
76
    prox = global.robot.getProximityRingValue(i);
77
    if((i == 3) || (i == 4)){
78
      if(prox < thresh){
79
        return false;
80
      }
81
    }else{
82
      if(prox > thresh){
83
        return false;
84
      }
85
    }
86
  }
87
  return true;
88
}
89
90 181f2892 galberding
bool UserThread::checkPinVoltage(){
91
  return global.ltc4412.isPluggedIn(); 
92
}
93 9c46b728 galberding
94 181f2892 galberding
bool UserThread::checkPinEnabled(){
95
  return global.ltc4412.isEnabled();
96
}
97
98
int UserThread::checkDockingSuccess(){
99
  // setRpmSpeed(stop);
100
  checkForMotion();
101 9c46b728 galberding
  int success = 0;
102
  global.odometry.resetPosition();
103
  types::position start = global.startPos = global.odometry.getPosition();
104 27d4e1fa galberding
  global.motorcontrol.setMotorEnable(false);
105
  this->sleep(1000);
106 181f2892 galberding
  types::position stop_ = global.endPos = global.odometry.getPosition();
107
  
108 9c46b728 galberding
  // Amiro moved, docking was not successful
109 181f2892 galberding
  if ((start.x + stop_.x) || (start.y + stop_.y)){
110
    lightAllLeds(Color::RED);
111
    // Enable Motor again if docking was not successful
112 27d4e1fa galberding
    global.motorcontrol.setMotorEnable(true);
113 9c46b728 galberding
    success = 0;
114
  }else{
115 181f2892 galberding
    lightAllLeds(Color::GREEN);
116 9c46b728 galberding
    success = 1;
117
  }
118
  
119 61544eee galberding
  // this->sleep(500);
120 181f2892 galberding
  lightAllLeds(Color::BLACK);
121 9c46b728 galberding
  return success;
122
}
123
124 c9fa414d galberding
int UserThread::getProxyRingSum(){
125
  int prox_sum = 0;
126 e2002d0e galberding
  for(int i=0; i<8;i++){
127
    prox_sum += global.robot.getProximityRingValue(i);;
128
  }
129
  return prox_sum;
130
}
131
132
133 58fe0e0b Thomas Schöpping
UserThread::UserThread() :
134
  chibios_rt::BaseStaticThread<USER_THREAD_STACK_SIZE>()
135
{
136
}
137
138
UserThread::~UserThread()
139
{
140
}
141
142
msg_t
143
UserThread::main()
144
{
145 5d138bca galberding
  /*
146
   * SETUP
147
   */
148 181f2892 galberding
  // User thread state:
149
150 fbcb25cc galberding
151
  //  int whiteBuf = 0;
152
  //  int proxyBuf = 0;
153 27d4e1fa galberding
  //  int reverseBuf = 0;
154 181f2892 galberding
   int correctionStep = 0;
155 27d4e1fa galberding
  //  int dist_count = 0;
156
  //  bool needDistance = false;
157 61544eee galberding
158 019224ff galberding
   uint16_t rProx[8]; // buffer for ring proxy values
159 9c46b728 galberding
  int rpmSpeed[2] = {0};
160
  int stop[2] = {0};
161 61544eee galberding
  int turn[2] = {5,-5};
162 c9fa414d galberding
  LineFollowStrategy lStrategy = LineFollowStrategy::EDGE_RIGHT;
163 5d138bca galberding
  for (uint8_t led = 0; led < 8; ++led) {
164
    global.robot.setLightColor(led, Color(Color::BLACK));
165
  }
166
  running = false;
167
  LineFollow lf(&global);
168
  /*
169
   * LOOP
170
   */
171
  while (!this->shouldTerminate())
172
  {
173 181f2892 galberding
    /*
174
    * read accelerometer z-value
175
    */
176
    accel_z = global.lis331dlh.getAccelerationForce(LIS331DLH::AXIS_Z);
177
        
178
    if (accel_z < -900 /*-0.9g*/) { 
179
      // Start line following when AMiRo is rotated
180
      if(utState == states::IDLE){
181 fbcb25cc galberding
        newState = states::FOLLOW_LINE;
182 181f2892 galberding
      }else{
183 fbcb25cc galberding
        newState = states::IDLE;
184 181f2892 galberding
      }
185
      lightAllLeds(Color::GREEN);
186
      this->sleep(1000);
187
      lightAllLeds(Color::BLACK);
188 c76baf23 Georg Alberding
189 d607fcef galberding
    // If message was received handle it here:
190
    } else if(global.msgReceived){
191
      global.msgReceived = false;
192 181f2892 galberding
      // running = true;
193 d607fcef galberding
      switch(global.lfStrategy){
194
        case msg_content::START:
195 fbcb25cc galberding
          newState = states::FOLLOW_LINE;
196 d607fcef galberding
          break;
197
        case msg_content::STOP:
198 fbcb25cc galberding
          newState = states::IDLE;
199 d607fcef galberding
          break;
200
        case msg_content::EDGE_RIGHT:
201 fbcb25cc galberding
          // newState = states::FOLLOW_LINE;
202 d607fcef galberding
          lStrategy = LineFollowStrategy::EDGE_RIGHT;
203
          break;
204
        case  msg_content::EDGE_LEFT:
205 fbcb25cc galberding
          // newState = states::FOLLOW_LINE;
206 d607fcef galberding
          lStrategy = LineFollowStrategy::EDGE_LEFT;
207
          break;
208
        case msg_content::FUZZY:
209 fbcb25cc galberding
          // newState = states::FOLLOW_LINE;
210 d607fcef galberding
          lStrategy = LineFollowStrategy::FUZZY;
211
          break;
212 181f2892 galberding
        case msg_content::DOCK:
213 fbcb25cc galberding
          newState = states::DETECT_STATION;
214 181f2892 galberding
          break;
215
        case msg_content::UNDOCK:
216 fbcb25cc galberding
          newState = states::RELEASE;
217 181f2892 galberding
          break;
218
        case msg_content::CHARGE:
219 fbcb25cc galberding
          newState = states::CHARGING;
220 d607fcef galberding
          break;
221
        default:
222 fbcb25cc galberding
          newState = states::IDLE;
223 d607fcef galberding
          break;
224
      }
225 5d138bca galberding
    }
226 fbcb25cc galberding
    // newState = utState;
227 d607fcef galberding
228 181f2892 galberding
    // Get sensor data 
229 fbcb25cc galberding
    // uint16_t WL = global.vcnl4020[constants::DiWheelDrive::PROX_WHEEL_LEFT].getProximityScaledWoOffset();
230
    // uint16_t WR = global.vcnl4020[constants::DiWheelDrive::PROX_WHEEL_RIGHT].getProximityScaledWoOffset();
231 019224ff galberding
    for(int i=0; i<8;i++){
232
      rProx[i] = global.robot.getProximityRingValue(i);
233
    }
234 181f2892 galberding
    // int FL = global.vcnl4020[constants::DiWheelDrive::PROX_FRONT_LEFT].getProximityScaledWoOffset();
235
    // int FR = global.vcnl4020[constants::DiWheelDrive::PROX_FRONT_RIGHT].getProximityScaledWoOffset();
236
    switch(utState){
237
      case states::IDLE:
238 27d4e1fa galberding
        global.motorcontrol.setMotorEnable(true);
239 181f2892 galberding
        setRpmSpeed(stop);
240
        if(/* checkPinVoltage() && */ checkPinEnabled()){
241
          global.robot.requestCharging(0);
242
        }
243 fbcb25cc galberding
        utCount.whiteCount = 0;
244
        utCount.proxyCount = 0;
245 27d4e1fa galberding
        utCount.errorCount = 0;
246 fbcb25cc galberding
        utCount.idleCount++;
247
        if (utCount.idleCount > 10){
248
          utCount.idleCount = 0;
249
        // chprintf((BaseSequentialStream*)&global.sercanmux1, "Transmit state %d\n", newState);
250
        global.robot.transmitState(utState);
251
      }
252 181f2892 galberding
        break;
253
      // ---------------------------------------
254
      case states::FOLLOW_LINE:
255
      // Set correct forward speed to every strategy
256
        if (global.forwardSpeed != global.rpmForward[0]){
257
          global.forwardSpeed = global.rpmForward[0];
258
        }
259
        
260
        if(lf.getStrategy() != lStrategy){
261 9c46b728 galberding
          lf.setStrategy(lStrategy);
262
        }
263 5d138bca galberding
264 181f2892 galberding
        if(lf.followLine(rpmSpeed)){
265 fbcb25cc galberding
          utCount.whiteCount++;
266
          if(utCount.whiteCount >= WHITE_COUNT_THRESH){
267 61544eee galberding
            rpmSpeed[0] = stop[0];
268
            rpmSpeed[1] = stop[1];
269 181f2892 galberding
            newState = states::IDLE;
270 9c46b728 galberding
          }
271 181f2892 galberding
        }else{
272 fbcb25cc galberding
          utCount.whiteCount = 0;
273 61544eee galberding
          // setRpmSpeed(rpmSpeed);
274 9c46b728 galberding
        }
275 e2002d0e galberding
276
        if(getProxyRingSum() > PROXY_RING_THRESH){
277 fbcb25cc galberding
          utCount.proxyCount++;
278
          if(utCount.proxyCount > WHITE_COUNT_THRESH){
279 61544eee galberding
            rpmSpeed[0] = stop[0];
280
            rpmSpeed[1] = stop[1];
281 fbcb25cc galberding
            // newState = states::IDLE;
282
            if (continue_on_obstacle){
283
              newState = states::TURN;
284
              utCount.proxyCount = 0;
285
            }else{
286
              newState = states::IDLE;
287
            }
288 e2002d0e galberding
          }
289
        }else{
290 fbcb25cc galberding
            utCount.proxyCount = 0;
291 61544eee galberding
        }
292
293
        if ((rProx[3] + rProx[4]) > RING_PROX_FRONT_THRESH){
294
          rpmSpeed[0] = stop[0];
295
          rpmSpeed[1] = stop[1];
296
        }
297
298 c9fa414d galberding
        if (lf.getStrategy() == LineFollowStrategy::FUZZY){
299
          setRpmSpeedFuzzy(rpmSpeed);
300
        }else{
301
302
          setRpmSpeed(rpmSpeed);
303
        }
304 181f2892 galberding
        
305
        break;
306
      // ---------------------------------------
307 fbcb25cc galberding
      case states::TURN:
308
        checkForMotion();
309
        // Check if only front sensors are active 
310
        if(checkFrontalObject()){
311
          global.distcontrol.setTargetPosition(0, ROTATION_180, ROTATION_DURATION);
312
          // BaseThread::sleep(8000);
313
          checkForMotion();
314
          newState = states::FOLLOW_LINE;
315
          lf.promptStrategyChange(LineFollowStrategy::EDGE_LEFT);
316
        }else{
317
          newState = states::IDLE;
318
        }
319
        break;
320
      // ---------------------------------------
321 181f2892 galberding
      case states::DETECT_STATION:
322 61544eee galberding
        if (global.forwardSpeed != DETECTION_SPEED){
323
          global.forwardSpeed = DETECTION_SPEED;
324
        }
325 181f2892 galberding
        if(lf.getStrategy() != LineFollowStrategy::EDGE_RIGHT){
326
          lf.setStrategy(LineFollowStrategy::EDGE_RIGHT);
327
        }
328
329
        lf.followLine(rpmSpeed);
330
        setRpmSpeed(rpmSpeed);
331
        // // Detect marker before docking station
332 019224ff galberding
        // if ((WL+WR) < PROXY_WHEEL_THRESH){
333
        // Use proxy ring 
334
        if ((rProx[3]+rProx[4]) > RING_PROX_FRONT_THRESH){
335
336 d607fcef galberding
          setRpmSpeed(stop);
337 181f2892 galberding
          checkForMotion();
338
          // 180° Rotation 
339
          global.distcontrol.setTargetPosition(0, ROTATION_180, ROTATION_DURATION);
340
          // BaseThread::sleep(8000);
341
          checkForMotion();
342
          newState = states::CORRECT_POSITIONING;
343 9c46b728 galberding
        }
344 181f2892 galberding
        break;
345
      // ---------------------------------------
346
      case states::CORRECT_POSITIONING:
347 019224ff galberding
        if (global.forwardSpeed != CHARGING_SPEED){
348
          global.forwardSpeed = CHARGING_SPEED;
349
        }
350 181f2892 galberding
        if(lf.getStrategy() != LineFollowStrategy::EDGE_LEFT){
351
          lf.promptStrategyChange(LineFollowStrategy::EDGE_LEFT);
352 9c46b728 galberding
        }
353 181f2892 galberding
        lf.followLine(rpmSpeed);
354
        setRpmSpeed(rpmSpeed);
355 9c46b728 galberding
356 fbcb25cc galberding
        utCount.stepCount++;
357
        if (utCount.stepCount >= MAX_CORRECTION_STEPS){
358
          utCount.stepCount = 0;
359 181f2892 galberding
          newState = states::REVERSE;
360
          setRpmSpeed(stop);
361
          checkForMotion();
362
        }
363
        break;
364
      // ---------------------------------------
365
      case states::REVERSE:
366
        if(lf.getStrategy() != LineFollowStrategy::REVERSE){
367
          lf.setStrategy(LineFollowStrategy::REVERSE);
368
        }
369
        lf.followLine(rpmSpeed);
370
        setRpmSpeed(rpmSpeed);
371 58fe0e0b Thomas Schöpping
372 019224ff galberding
        // if ((WL+WR) < PROXY_WHEEL_THRESH){
373
        // Is of those sensors at it max val means that the AMiRo cant drive back
374
        // so check if correctly positioned
375
        //definitely wrong positioned -> correct position directly without rotation
376
        // Both sensors are at a wall -> potential loading station dock and on magnet -> need to rotate
377 61544eee galberding
        // if((rProx[0] >= PROX_MAX_VAL) && (rProx[7] >= PROX_MAX_VAL)){
378
        //   setRpmSpeed(stop);
379
        //   checkForMotion();
380
        //   newState = states::CHECK_POSITIONING;
381
        // } else 
382 019224ff galberding
        if((rProx[0] >= PROX_MAX_VAL) || (rProx[7] >= PROX_MAX_VAL)){
383 61544eee galberding
          // setRpmSpeed(stop);
384
          // checkForMotion();
385 fbcb25cc galberding
          utCount.stepCount = 0;
386 27d4e1fa galberding
          newState = states::PUSH_BACK;
387
        }
388
        break;
389
      // ---------------------------------------
390
      case states::PUSH_BACK:
391
        if(lf.getStrategy() != LineFollowStrategy::REVERSE){
392
          lf.setStrategy(LineFollowStrategy::REVERSE);
393
        }
394
        lf.followLine(rpmSpeed);
395
        setRpmSpeed(rpmSpeed);
396
397 fbcb25cc galberding
        utCount.stepCount++;
398
        if (utCount.stepCount > PUSH_BACK_COUNT){
399 181f2892 galberding
          newState = states::CHECK_POSITIONING;
400
        }
401
        break;
402
      // ---------------------------------------
403
      case states::CHECK_POSITIONING:
404 61544eee galberding
        setRpmSpeed(stop);
405
        checkForMotion();
406
        // if((rProx[0] >= PROX_MAX_VAL) && (rProx[7] >= PROX_MAX_VAL)){
407 27d4e1fa galberding
        if(checkDockingSuccess()){
408
          newState = states::CHECK_VOLTAGE;
409
        }else{
410
          utCount.errorCount++;
411
          newState = states::CORRECT_POSITIONING;
412
          if (utCount.errorCount > DOCKING_ERROR_THRESH){
413
              newState = states::ERROR;
414
            }
415
        }
416 61544eee galberding
        // }
417
        // else{
418
        //   newState = CORRECT_POSITIONING;
419
        // }
420 181f2892 galberding
        break;
421
      // ---------------------------------------
422 ba75ee1d galberding
      case states::CHECK_VOLTAGE:
423
        if(!checkPinEnabled()){
424
          global.robot.requestCharging(1);
425
        } else {
426
          if(checkPinVoltage()){
427
            // Pins are under voltage -> correctly docked 
428 27d4e1fa galberding
            utCount.errorCount = 0;
429 ba75ee1d galberding
            newState = states::CHARGING;
430
          }else{
431 27d4e1fa galberding
            utCount.errorCount++;
432 ba75ee1d galberding
            // No voltage on pins -> falsely docked
433
            // deactivate pins
434 27d4e1fa galberding
            global.motorcontrol.setMotorEnable(true);
435 ba75ee1d galberding
            global.robot.requestCharging(0);
436 27d4e1fa galberding
            // TODO: Soft release when docking falsely
437 61544eee galberding
            if((rProx[0] >= PROX_MAX_VAL) && (rProx[7] >= PROX_MAX_VAL)){
438
              newState = states::RELEASE_TO_CORRECT;
439
            } else {
440 27d4e1fa galberding
              newState = states::RELEASE_TO_CORRECT; //states::CORRECT_POSITIONING; 
441
            }
442
443
            if (utCount.errorCount > DOCKING_ERROR_THRESH){
444
              newState = states::ERROR;
445 61544eee galberding
            }
446 ba75ee1d galberding
          }
447
        }
448 019224ff galberding
        break;
449
      // ---------------------------------------
450
      case states::RELEASE_TO_CORRECT:
451 27d4e1fa galberding
452 019224ff galberding
        global.distcontrol.setTargetPosition(0, ROTATION_20, ROTATION_DURATION);
453
        checkForMotion();
454
        // move 1cm forward
455
        global.distcontrol.setTargetPosition(5000, 0, ROTATION_DURATION);
456
        checkForMotion();
457
        // rotate back
458
        global.distcontrol.setTargetPosition(0, -2*ROTATION_20, ROTATION_DURATION);
459
        checkForMotion();
460
461
        global.distcontrol.setTargetPosition(7000, 0, ROTATION_DURATION);
462
        checkForMotion();
463
        newState = states::CORRECT_POSITIONING;
464
        break;
465 ba75ee1d galberding
      // ---------------------------------------
466 27d4e1fa galberding
      case states::ERROR:
467
        utCount.errorCount = 0;
468 fbcb25cc galberding
        // lStrategy = LineFollowStrategy::EDGE_RIGHT;
469
        newState = states::RELEASE;
470 27d4e1fa galberding
        break;
471
      // ---------------------------------------
472 181f2892 galberding
      case states::CHARGING:
473 27d4e1fa galberding
        global.motorcontrol.setMotorEnable(false);
474 181f2892 galberding
        // Formulate Request to enable charging
475
        if(/* checkPinVoltage() && */ !checkPinEnabled()){
476
          global.robot.requestCharging(1);
477
        }
478
        if(checkPinEnabled()){
479
          showChargingState();
480
        }
481
        break;
482
      
483
      // ---------------------------------------
484
      case states::RELEASE:
485 61544eee galberding
      if (global.forwardSpeed != DETECTION_SPEED){
486
          global.rpmForward[0] = DETECTION_SPEED;
487
        }
488 181f2892 galberding
        if(/* checkPinVoltage() && */ checkPinEnabled()){
489
          global.robot.requestCharging(0);
490
        }else{
491 27d4e1fa galberding
          global.motorcontrol.setMotorEnable(true);
492
493 181f2892 galberding
          //Rotate -20° to free from magnet
494
          global.distcontrol.setTargetPosition(0, ROTATION_20, ROTATION_DURATION);
495 61544eee galberding
          checkForMotion();
496
          // move 1cm forward
497
          global.distcontrol.setTargetPosition(5000, 0, ROTATION_DURATION);
498
          checkForMotion();
499
          // rotate back
500
          global.distcontrol.setTargetPosition(0, -ROTATION_20, ROTATION_DURATION);
501
          checkForMotion();
502 019224ff galberding
503 61544eee galberding
          // global.distcontrol.setTargetPosition(5000, 0, ROTATION_DURATION);
504
          // checkForMotion();
505 181f2892 galberding
          lStrategy = LineFollowStrategy::EDGE_RIGHT;
506
          newState = states::FOLLOW_LINE;
507 61544eee galberding
            // whiteBuf = -100;
508
          // lf.followLine(rpmSpeed);
509
          // setRpmSpeed(rpmSpeed);
510 181f2892 galberding
        }
511 61544eee galberding
        // lightAllLeds(Color::BLACK);
512 181f2892 galberding
        break;
513
      
514
      default:
515
        break;
516
      }
517 27d4e1fa galberding
      if (utState != newState){
518 fbcb25cc galberding
        chprintf((BaseSequentialStream*)&global.sercanmux1, "Transmit state %d\n", newState);
519 27d4e1fa galberding
        global.robot.transmitState(newState);
520
      }
521 181f2892 galberding
      utState = newState;
522 5d138bca galberding
    this->sleep(CAN::UPDATE_PERIOD);
523
  }
524 58fe0e0b Thomas Schöpping
525
  return RDY_OK;
526
}