Statistics
| Branch: | Tag: | Revision:

amiro-os / devices / DiWheelDrive / userthread.cpp @ 019224ff

History | View | Annotate | Download (12.314 KB)

1
#include "userthread.hpp"
2
#include "global.hpp"
3
#include "linefollow.hpp" 
4

    
5
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
bool running = false;
12

    
13

    
14
/**
15
 * Set speed.
16
 * 
17
 * @param rpmSpeed speed for left and right wheel in rounds/min
18
 */
19
void UserThread::setRpmSpeed(const int (&rpmSpeed)[2]) {
20
  global.motorcontrol.setTargetRPM(rpmSpeed[constants::DiWheelDrive::LEFT_WHEEL] * 1000000, rpmSpeed[constants::DiWheelDrive::RIGHT_WHEEL] * 1000000);
21
}
22

    
23
void UserThread::lightOneLed(Color color, int idx){
24
  global.robot.setLightColor(idx, Color(color));
25
}
26

    
27
void UserThread::lightAllLeds(Color color){
28
  int led = 0;
29
  for(led=0; led<8; led++){
30
        lightOneLed(color, led);
31
      }
32
}
33

    
34
void UserThread::showChargingState(){
35
  uint8_t numLeds = global.robot.getPowerStatus().state_of_charge / 12;
36
  Color color = Color::GREEN;
37
  if (numLeds <= 2){
38
    color = Color::RED;
39
  }else if(numLeds <= 6){
40
    color = Color::YELLOW;
41
  }
42
  for (int i=0; i<numLeds; i++){
43
    lightOneLed(color, i);
44
    this->sleep(300);
45
  }
46
  this->sleep(1000);
47
  lightAllLeds(Color::BLACK);
48
}
49

    
50
/**
51
 * Blocks as long as the position changes.
52
 */
53
void UserThread::checkForMotion(){
54
  int motion = 1;
55
  int led = 0;
56
  types::position oldPos = global.odometry.getPosition();
57
  while(motion){
58
    this->sleep(500);
59
    types::position tmp = global.odometry.getPosition();
60
    motion = abs(oldPos.x - tmp.x)+ abs(oldPos.y - tmp.y)+abs(oldPos.z - tmp.z);
61
    oldPos = tmp;
62
      global.robot.setLightColor((led + 1) % 8, Color(Color::YELLOW));
63
      global.robot.setLightColor(led % 8, Color(Color::BLACK));
64
      led++;
65
  }
66
}
67

    
68
bool UserThread::checkPinVoltage(){
69
  return global.ltc4412.isPluggedIn(); 
70
}
71

    
72
bool UserThread::checkPinEnabled(){
73
  return global.ltc4412.isEnabled();
74
}
75

    
76
int UserThread::checkDockingSuccess(){
77
  // setRpmSpeed(stop);
78
  checkForMotion();
79
  int success = 0;
80
  global.odometry.resetPosition();
81
  types::position start = global.startPos = global.odometry.getPosition();
82
  global.motorcontrol.toggleMotorEnable();
83
  this->sleep(1000);
84
  types::position stop_ = global.endPos = global.odometry.getPosition();
85
  
86
  // Amiro moved, docking was not successful
87
  if ((start.x + stop_.x) || (start.y + stop_.y)){
88
    lightAllLeds(Color::RED);
89
    // Enable Motor again if docking was not successful
90
    global.motorcontrol.toggleMotorEnable();
91
    success = 0;
92
  }else{
93
    lightAllLeds(Color::GREEN);
94
    success = 1;
95
  }
96
  
97
  this->sleep(500);
98
  lightAllLeds(Color::BLACK);
99
  return success;
100
}
101

    
102
uint16_t UserThread::getProxyRingSum(){
103
  uint16_t prox_sum = 0;
104
  for(int i=0; i<8;i++){
105
    prox_sum += global.robot.getProximityRingValue(i);;
106
  }
107
  return prox_sum;
108
}
109

    
110

    
111
UserThread::UserThread() :
112
  chibios_rt::BaseStaticThread<USER_THREAD_STACK_SIZE>()
113
{
114
}
115

    
116
UserThread::~UserThread()
117
{
118
}
119

    
120
msg_t
121
UserThread::main()
122
{
123
  /*
124
   * SETUP
125
   */
126
  // User thread state:
127
states utState = states::IDLE;
128
states newState;
129

    
130
   int whiteBuf = 0;
131
   int proxyBuf = 0;
132
   int correctionStep = 0;
133
   uint16_t rProx[8]; // buffer for ring proxy values
134
  int rpmSpeed[2] = {0};
135
  int stop[2] = {0};
136
  LineFollowStrategy lStrategy = LineFollowStrategy::FUZZY;
137
  for (uint8_t led = 0; led < 8; ++led) {
138
    global.robot.setLightColor(led, Color(Color::BLACK));
139
  }
140
  running = false;
141
  LineFollow lf(&global);
142
  /*
143
   * LOOP
144
   */
145
  while (!this->shouldTerminate())
146
  {
147
    /*
148
    * read accelerometer z-value
149
    */
150
    accel_z = global.lis331dlh.getAccelerationForce(LIS331DLH::AXIS_Z);
151
        
152
    if (accel_z < -900 /*-0.9g*/) { 
153
      // Start line following when AMiRo is rotated
154
      if(utState == states::IDLE){
155
        utState = states::FOLLOW_LINE;
156
      }else{
157
        utState = states::IDLE;
158
      }
159
      lightAllLeds(Color::GREEN);
160
      this->sleep(1000);
161
      lightAllLeds(Color::BLACK);
162

    
163
    // If message was received handle it here:
164
    } else if(global.msgReceived){
165
      global.msgReceived = false;
166
      // running = true;
167
      switch(global.lfStrategy){
168
        case msg_content::START:
169
          utState = states::FOLLOW_LINE;
170
          break;
171
        case msg_content::STOP:
172
          utState = states::IDLE;
173
          break;
174
        case msg_content::EDGE_RIGHT:
175
          // utState = states::FOLLOW_LINE;
176
          lStrategy = LineFollowStrategy::EDGE_RIGHT;
177
          break;
178
        case  msg_content::EDGE_LEFT:
179
          // utState = states::FOLLOW_LINE;
180
          lStrategy = LineFollowStrategy::EDGE_LEFT;
181
          break;
182
        case msg_content::FUZZY:
183
          // utState = states::FOLLOW_LINE;
184
          lStrategy = LineFollowStrategy::FUZZY;
185
          break;
186
        case msg_content::DOCK:
187
          utState = states::DETECT_STATION;
188
          break;
189
        case msg_content::UNDOCK:
190
          utState = states::RELEASE;
191
          break;
192
        case msg_content::CHARGE:
193
          utState = states::CHARGING;
194
          break;
195
        default:
196
          utState = states::IDLE;
197
          break;
198
      }
199
    }
200
    newState = utState;
201

    
202
    // Get sensor data 
203
    uint16_t WL = global.vcnl4020[constants::DiWheelDrive::PROX_WHEEL_LEFT].getProximityScaledWoOffset();
204
    uint16_t WR = global.vcnl4020[constants::DiWheelDrive::PROX_WHEEL_RIGHT].getProximityScaledWoOffset();
205
    for(int i=0; i<8;i++){
206
      rProx[i] = global.robot.getProximityRingValue(i);
207
    }
208
    // int FL = global.vcnl4020[constants::DiWheelDrive::PROX_FRONT_LEFT].getProximityScaledWoOffset();
209
    // int FR = global.vcnl4020[constants::DiWheelDrive::PROX_FRONT_RIGHT].getProximityScaledWoOffset();
210
    switch(utState){
211
      case states::IDLE:
212
        if (!global.motorcontrol.getMotorEnable()){
213
            global.motorcontrol.toggleMotorEnable();
214
        }
215
        setRpmSpeed(stop);
216
        if(/* checkPinVoltage() && */ checkPinEnabled()){
217
          global.robot.requestCharging(0);
218
        }
219
        
220
        break;
221
      // ---------------------------------------
222
      case states::FOLLOW_LINE:
223
      // Set correct forward speed to every strategy
224
        if (global.forwardSpeed != global.rpmForward[0]){
225
          global.forwardSpeed = global.rpmForward[0];
226
        }
227
        
228
        if(lf.getStrategy() != lStrategy){
229
          lf.setStrategy(lStrategy);
230
        }
231

    
232
        //TODO: Check if white is detected and stop threshold is reached
233
        if(lf.followLine(rpmSpeed)){
234
          
235
          if(whiteBuf >= WHITE_COUNT_THRESH){
236
            setRpmSpeed(stop);
237
            newState = states::IDLE;
238
          }else{
239
            whiteBuf++;
240
          }
241
        }else{
242
          whiteBuf = 0;
243
          setRpmSpeed(rpmSpeed);
244
        }
245

    
246
        if(getProxyRingSum() > PROXY_RING_THRESH){
247
          setRpmSpeed(stop);
248
          proxyBuf++;
249
          if(proxyBuf > WHITE_COUNT_THRESH){
250
            newState = states::IDLE;
251
          }
252
        }else{
253
            proxyBuf = 0;
254
          }
255
        // lf.followLine(rpmSpeed);
256
        // setRpmSpeed(rpmSpeed);
257
        
258
        break;
259
      // ---------------------------------------
260
      case states::DETECT_STATION:
261
        // if (global.forwardSpeed != CHARGING_SPEED){
262
        //   global.forwardSpeed = CHARGING_SPEED;
263
        // }
264
        if(lf.getStrategy() != LineFollowStrategy::EDGE_RIGHT){
265
          lf.setStrategy(LineFollowStrategy::EDGE_RIGHT);
266
        }
267

    
268
        lf.followLine(rpmSpeed);
269
        setRpmSpeed(rpmSpeed);
270
        // // Detect marker before docking station
271
        // if ((WL+WR) < PROXY_WHEEL_THRESH){
272
        // Use proxy ring 
273
        if ((rProx[3]+rProx[4]) > RING_PROX_FRONT_THRESH){
274

    
275
          setRpmSpeed(stop);
276
          checkForMotion();
277
          // 180° Rotation 
278
          global.distcontrol.setTargetPosition(0, ROTATION_180, ROTATION_DURATION);
279
          // BaseThread::sleep(8000);
280
          checkForMotion();
281
          newState = states::CORRECT_POSITIONING;
282
        }
283
        break;
284
      // ---------------------------------------
285
      case states::CORRECT_POSITIONING:
286
        if (global.forwardSpeed != CHARGING_SPEED){
287
          global.forwardSpeed = CHARGING_SPEED;
288
        }
289
        if(lf.getStrategy() != LineFollowStrategy::EDGE_LEFT){
290
          lf.promptStrategyChange(LineFollowStrategy::EDGE_LEFT);
291
        }
292
        lf.followLine(rpmSpeed);
293
        setRpmSpeed(rpmSpeed);
294

    
295
        correctionStep++;
296
        if (correctionStep >= MAX_CORRECTION_STEPS){
297
          correctionStep = 0;
298
          newState = states::REVERSE;
299
          setRpmSpeed(stop);
300
          checkForMotion();
301
        }
302
        break;
303
      // ---------------------------------------
304
      case states::REVERSE:
305
        if(lf.getStrategy() != LineFollowStrategy::REVERSE){
306
          lf.setStrategy(LineFollowStrategy::REVERSE);
307
        }
308
        lf.followLine(rpmSpeed);
309
        setRpmSpeed(rpmSpeed);
310

    
311
        // if ((WL+WR) < PROXY_WHEEL_THRESH){
312
        // Is of those sensors at it max val means that the AMiRo cant drive back
313
        // so check if correctly positioned
314
        //definitely wrong positioned -> correct position directly without rotation
315
        if ((rProx[0] >= PROX_MAX_VAL && rProx[7] < PROX_MAX_VAL) || (rProx[0] < PROX_MAX_VAL && rProx[7] >= PROX_MAX_VAL)){
316
          setRpmSpeed(stop);
317
          checkForMotion();
318
          newState = states::CORRECT_POSITIONING;
319
        }
320
        // Both sensors are at a wall -> potential loading station dock and on magnet -> need to rotate
321
        if((rProx[0] >= PROX_MAX_VAL) || (rProx[7] >= PROX_MAX_VAL)){
322
          setRpmSpeed(stop);
323
          checkForMotion();
324
          newState = states::CHECK_POSITIONING;
325
        }
326
        break;
327
      // ---------------------------------------
328
      case states::CHECK_POSITIONING:
329
        if(checkDockingSuccess()){
330
          newState = states::CHECK_VOLTAGE;
331
        }else{
332
          newState = states::CORRECT_POSITIONING;
333
        }
334
        break;
335
      // ---------------------------------------
336
      case states::CHECK_VOLTAGE:
337
        if(!checkPinEnabled()){
338
          global.robot.requestCharging(1);
339
        } else {
340
          if(checkPinVoltage()){
341
            // Pins are under voltage -> correctly docked 
342
            newState = states::CHARGING;
343
          }else{
344
            // No voltage on pins -> falsely docked
345
            // deactivate pins
346
            global.robot.requestCharging(0);
347
            newState = states::RELEASE_TO_CORRECT;
348
          }
349
        }
350
        break;
351
      // ---------------------------------------
352
      case states::RELEASE_TO_CORRECT:
353
        global.distcontrol.setTargetPosition(0, ROTATION_20, ROTATION_DURATION);
354
        checkForMotion();
355
        // move 1cm forward
356
        global.distcontrol.setTargetPosition(5000, 0, ROTATION_DURATION);
357
        checkForMotion();
358
        // rotate back
359
        global.distcontrol.setTargetPosition(0, -2*ROTATION_20, ROTATION_DURATION);
360
        checkForMotion();
361

    
362
        global.distcontrol.setTargetPosition(7000, 0, ROTATION_DURATION);
363
        checkForMotion();
364
        newState = states::CORRECT_POSITIONING;
365
        break;
366
      // ---------------------------------------
367
      case states::CHARGING:
368
        if (global.motorcontrol.getMotorEnable()){
369
          global.motorcontrol.toggleMotorEnable();
370
        }
371
        // Formulate Request to enable charging
372
        if(/* checkPinVoltage() && */ !checkPinEnabled()){
373
          global.robot.requestCharging(1);
374
        }
375
        if(checkPinEnabled()){
376
          showChargingState();
377
        }
378
        break;
379
      
380
      // ---------------------------------------
381
      case states::RELEASE:
382
        if(/* checkPinVoltage() && */ checkPinEnabled()){
383
          global.robot.requestCharging(0);
384
        }
385

    
386
        if(checkPinEnabled()){
387
          showChargingState();
388
        }else{
389
          if (!global.motorcontrol.getMotorEnable()){
390
            global.motorcontrol.toggleMotorEnable();
391
          }
392
          //Rotate -20° to free from magnet
393
          global.distcontrol.setTargetPosition(0, ROTATION_20, ROTATION_DURATION);
394
        checkForMotion();
395
        // move 1cm forward
396
        global.distcontrol.setTargetPosition(5000, 0, ROTATION_DURATION);
397
        checkForMotion();
398
        // rotate back
399
        global.distcontrol.setTargetPosition(0, -ROTATION_20, ROTATION_DURATION);
400
        checkForMotion();
401

    
402
        global.distcontrol.setTargetPosition(5000, 0, ROTATION_DURATION);
403
        checkForMotion();
404
          lStrategy = LineFollowStrategy::EDGE_RIGHT;
405
          newState = states::FOLLOW_LINE;
406
          whiteBuf = -100;
407
        }
408
        lightAllLeds(Color::BLACK);
409
        break;
410
      
411
      default:
412
        break;
413
      }
414
      utState = newState;
415
    this->sleep(CAN::UPDATE_PERIOD);
416
  }
417

    
418
  return RDY_OK;
419
}