Statistics
| Branch: | Tag: | Revision:

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

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

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

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

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

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

    
264
        lf.followLine(rpmSpeed);
265
        setRpmSpeed(rpmSpeed);
266
        // // Detect marker before docking station
267
        if ((WL+WR) < PROXY_WHEEL_THRESH){
268
          setRpmSpeed(stop);
269
          checkForMotion();
270
          // 180° Rotation 
271
          global.distcontrol.setTargetPosition(0, ROTATION_180, ROTATION_DURATION);
272
          // BaseThread::sleep(8000);
273
          checkForMotion();
274
          newState = states::CORRECT_POSITIONING;
275
        }
276
        break;
277
      // ---------------------------------------
278
      case states::CORRECT_POSITIONING:
279
        if(lf.getStrategy() != LineFollowStrategy::EDGE_LEFT){
280
          lf.promptStrategyChange(LineFollowStrategy::EDGE_LEFT);
281
        }
282
        lf.followLine(rpmSpeed);
283
        setRpmSpeed(rpmSpeed);
284

    
285
        correctionStep++;
286
        if (correctionStep >= MAX_CORRECTION_STEPS){
287
          correctionStep = 0;
288
          newState = states::REVERSE;
289
          setRpmSpeed(stop);
290
          checkForMotion();
291
        }
292
        break;
293
      // ---------------------------------------
294
      case states::REVERSE:
295
        if(lf.getStrategy() != LineFollowStrategy::REVERSE){
296
          lf.setStrategy(LineFollowStrategy::REVERSE);
297
        }
298
        lf.followLine(rpmSpeed);
299
        setRpmSpeed(rpmSpeed);
300

    
301
        if ((WL+WR) < PROXY_WHEEL_THRESH){
302
          setRpmSpeed(stop);
303
          checkForMotion();
304
          newState = states::CHECK_POSITIONING;
305
        }
306
        break;
307
      // ---------------------------------------
308
      case states::CHECK_POSITIONING:
309
        if(checkDockingSuccess()){
310
          newState = states::CHECK_VOLTAGE;
311
        }else{
312
          newState = states::CORRECT_POSITIONING;
313
        }
314
        break;
315
      // ---------------------------------------
316
      case states::CHECK_VOLTAGE:
317
        if(!checkPinEnabled()){
318
          global.robot.requestCharging(1);
319
        } else {
320
          if(checkPinVoltage()){
321
            // Pins are under voltage -> correctly docked 
322
            newState = states::CHARGING;
323
          }else{
324
            // No voltage on pins -> falsely docked
325
            // deactivate pins
326
            global.robot.requestCharging(0);
327
            newState = states::CORRECT_POSITIONING;
328
          }
329
        }
330
      // ---------------------------------------
331
      case states::CHARGING:
332
        if (global.motorcontrol.getMotorEnable()){
333
          global.motorcontrol.toggleMotorEnable();
334
        }
335
        // Formulate Request to enable charging
336
        if(/* checkPinVoltage() && */ !checkPinEnabled()){
337
          global.robot.requestCharging(1);
338
        }
339
        if(checkPinEnabled()){
340
          showChargingState();
341
        }
342
        break;
343
      
344
      // ---------------------------------------
345
      case states::RELEASE:
346
        if(/* checkPinVoltage() && */ checkPinEnabled()){
347
          global.robot.requestCharging(0);
348
        }
349

    
350
        if(checkPinEnabled()){
351
          showChargingState();
352
        }else{
353
          if (!global.motorcontrol.getMotorEnable()){
354
            global.motorcontrol.toggleMotorEnable();
355
          }
356
          //Rotate -20° to free from magnet
357
          global.distcontrol.setTargetPosition(0, ROTATION_20, ROTATION_DURATION);
358
          checkForMotion();
359
          lStrategy = LineFollowStrategy::EDGE_RIGHT;
360
          newState = states::FOLLOW_LINE;
361
        }
362
        lightAllLeds(Color::BLACK);
363
        break;
364
      
365
      default:
366
        break;
367
      }
368
      utState = newState;
369
    this->sleep(CAN::UPDATE_PERIOD);
370
  }
371

    
372
  return RDY_OK;
373
}