Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (32.231 KB)

1 58fe0e0b Thomas Schöpping
#include "global.hpp"
2 10bf9cc0 galberding
#include <cmath>
3 8dced1c9 galberding
#include "linefollow.hpp"
4 d4c6efa9 galberding
#include "userthread.hpp"
5 e404e6c0 galberding
#include "amiro_map.hpp"
6
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 8dced1c9 galberding
 *
19 181f2892 galberding
 * @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 8dced1c9 galberding
79 10bf9cc0 galberding
  }
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 8dced1c9 galberding
98 10bf9cc0 galberding
  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 8dced1c9 galberding
126 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]);
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 d4c6efa9 galberding
      rpmSpeed[0] = rpmSpeed[0] / 3;
142
      rpmSpeed[1] = rpmSpeed[1] / 3;
143 10bf9cc0 galberding
  }
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 8dced1c9 galberding
153 10bf9cc0 galberding
}
154
155
156 9c46b728 galberding
/**
157
 * Blocks as long as the position changes.
158
 */
159 181f2892 galberding
void UserThread::checkForMotion(){
160 8dced1c9 galberding
  bool motion = true;
161 9c46b728 galberding
  int led = 0;
162
  types::position oldPos = global.odometry.getPosition();
163
  while(motion){
164 8dced1c9 galberding
    this->sleep(200);
165 9c46b728 galberding
    types::position tmp = global.odometry.getPosition();
166 8dced1c9 galberding
    motion = oldPos.x != tmp.x; //abs(oldPos.x - tmp.x)+ abs(oldPos.y - tmp.y)+abs(oldPos.z - tmp.z);
167 9c46b728 galberding
    oldPos = tmp;
168 8dced1c9 galberding
    global.robot.setLightColor((led + 1) % 8, Color(Color::YELLOW));
169
    global.robot.setLightColor(led % 8, Color(Color::BLACK));
170
    led++;
171 9c46b728 galberding
  }
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 8dced1c9 galberding
  return global.ltc4412.isPluggedIn();
195 181f2892 galberding
}
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 8dced1c9 galberding
211 9c46b728 galberding
  // Amiro moved, docking was not successful
212 10bf9cc0 galberding
  // if ((start.x + stop_.x)  || (start.y + stop_.y)){
213 84b4c632 galberding
  if (abs(start.x - stop_.x) > 200 /* || (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 8dced1c9 galberding
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 8dced1c9 galberding
  int32_t res = 0;
239 b24df8ad galberding
  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 e404e6c0 galberding
void setAttributes(uint8_t (&map)[MAX_NODES][NODE_ATTRIBUTES],
251
                          uint8_t id, uint8_t l, uint8_t r, uint8_t att) {
252
  map[id][0] = l;
253
  map[id][1] = r;
254
  map[id][2] = att;
255
}
256 e2002d0e galberding
257 58fe0e0b Thomas Schöpping
UserThread::UserThread() :
258
  chibios_rt::BaseStaticThread<USER_THREAD_STACK_SIZE>()
259
{
260
}
261
262
UserThread::~UserThread()
263
{
264
}
265
266
msg_t
267
UserThread::main()
268
{
269 5d138bca galberding
  /*
270
   * SETUP
271
   */
272 181f2892 galberding
  // User thread state:
273
274 5d138bca galberding
  for (uint8_t led = 0; led < 8; ++led) {
275
    global.robot.setLightColor(led, Color(Color::BLACK));
276
  }
277
  running = false;
278 10bf9cc0 galberding
  LineFollowStrategy lStrategy = LineFollowStrategy::EDGE_RIGHT;
279 5d138bca galberding
  LineFollow lf(&global);
280 e404e6c0 galberding
  AmiroMap map(&global);
281 5d138bca galberding
  /*
282
   * LOOP
283
   */
284
  while (!this->shouldTerminate())
285
  {
286 181f2892 galberding
    /*
287
    * read accelerometer z-value
288
    */
289
    accel_z = global.lis331dlh.getAccelerationForce(LIS331DLH::AXIS_Z);
290 8dced1c9 galberding
291
    if (accel_z < -900 /*-0.9g*/) {
292 181f2892 galberding
      // Start line following when AMiRo is rotated
293 10bf9cc0 galberding
      if(currentState == states::INACTIVE){
294 fbcb25cc galberding
        newState = states::FOLLOW_LINE;
295 181f2892 galberding
      }else{
296 fbcb25cc galberding
        newState = states::IDLE;
297 181f2892 galberding
      }
298
      lightAllLeds(Color::GREEN);
299
      this->sleep(1000);
300
      lightAllLeds(Color::BLACK);
301 c76baf23 Georg Alberding
302 d607fcef galberding
    // If message was received handle it here:
303
    } else if(global.msgReceived){
304
      global.msgReceived = false;
305 181f2892 galberding
      // running = true;
306 d607fcef galberding
      switch(global.lfStrategy){
307 e404e6c0 galberding
      case msg_content::MSG_START:
308
        newState = states::CALIBRATION_CHECK;
309 10bf9cc0 galberding
        break;
310 e404e6c0 galberding
      case msg_content::MSG_STOP:
311
        newState = states::IDLE;
312 10bf9cc0 galberding
        break;
313 e404e6c0 galberding
      case msg_content::MSG_EDGE_RIGHT:
314
        // newState = states::FOLLOW_LINE;
315
        lStrategy = LineFollowStrategy::EDGE_RIGHT;
316 10bf9cc0 galberding
        break;
317 e404e6c0 galberding
      case  msg_content::MSG_EDGE_LEFT:
318
        // newState = states::FOLLOW_LINE;
319
        lStrategy = LineFollowStrategy::EDGE_LEFT;
320 10bf9cc0 galberding
        break;
321 e404e6c0 galberding
      case msg_content::MSG_FUZZY:
322
        // newState = states::FOLLOW_LINE;
323
        lStrategy = LineFollowStrategy::FUZZY;
324 10bf9cc0 galberding
        break;
325 e404e6c0 galberding
      case msg_content::MSG_DOCK:
326
        newState = states::DETECT_STATION;
327 10bf9cc0 galberding
        break;
328 e404e6c0 galberding
      case msg_content::MSG_UNDOCK:
329
        newState = states::RELEASE;
330
        break;
331
      case msg_content::MSG_CHARGE:
332
        newState = states::CHARGING;
333 10bf9cc0 galberding
        break;
334 e404e6c0 galberding
      case msg_content::MSG_RESET_ODOMETRY:
335
        global.odometry.resetPosition();
336 10bf9cc0 galberding
        break;
337 e404e6c0 galberding
      case msg_content::MSG_CALIBRATE_BLACK:
338
        proxCalib.calibrateBlack = true;
339
        // global.odometry.resetPosition();
340
        newState = states::CALIBRATION;
341 10bf9cc0 galberding
        break;
342 e404e6c0 galberding
      case msg_content::MSG_CALIBRATE_WHITE:
343
        proxCalib.calibrateBlack = false;
344
        newState = states::CALIBRATION;
345 10bf9cc0 galberding
        break;
346 e404e6c0 galberding
      case msg_content::MSG_TEST_MAP_STATE:
347
        newState = states::TEST_MAP_STATE;
348 10bf9cc0 galberding
        break;
349 e404e6c0 galberding
350
      default:
351
        newState = states::IDLE;
352 10bf9cc0 galberding
        break;
353 d607fcef galberding
      }
354 5d138bca galberding
    }
355 10bf9cc0 galberding
    // newState = currentState;
356 d607fcef galberding
357 8dced1c9 galberding
    // Get sensor data
358 fbcb25cc galberding
    // uint16_t WL = global.vcnl4020[constants::DiWheelDrive::PROX_WHEEL_LEFT].getProximityScaledWoOffset();
359
    // uint16_t WR = global.vcnl4020[constants::DiWheelDrive::PROX_WHEEL_RIGHT].getProximityScaledWoOffset();
360 019224ff galberding
    for(int i=0; i<8;i++){
361
      rProx[i] = global.robot.getProximityRingValue(i);
362
    }
363 b24df8ad galberding
364
    // Continously update devication values
365
    meanDeviation(rProx[0] & 0xFFF0, rProx[7] & 0xFFF0);
366 181f2892 galberding
    // int FL = global.vcnl4020[constants::DiWheelDrive::PROX_FRONT_LEFT].getProximityScaledWoOffset();
367
    // int FR = global.vcnl4020[constants::DiWheelDrive::PROX_FRONT_RIGHT].getProximityScaledWoOffset();
368 10bf9cc0 galberding
    switch(currentState){
369
      case states::INACTIVE:
370
        // Dummy state to deactivate every interaction
371
      break;
372
      // ---------------------------------------
373
      case states::CALIBRATION_CHECK:
374
        // global.robot.calibrate();
375
        if(global.linePID.BThresh >= global.linePID.WThresh){
376
          newState = states::CALIBRATION_ERROR;
377
        }else{
378
          newState = states::FOLLOW_LINE;
379
        }
380
      break;
381
      // ---------------------------------------
382
      case states::CALIBRATION:
383
        /* Calibrate the global thresholds for black or white.
384
            This values will be used by the line follow object
385
        */
386
387
        proxCalib.buf = 0;
388
        if(proxCalib.calibrateBlack){
389
          chprintf((BaseSequentialStream*)&global.sercanmux1, "Black Calibration, Place AMiRo on black Surface!\n");
390
          global.robot.calibrate();
391
        }
392
        for(int i=0; i <= proxCalib.meanWindow; i++){
393 8dced1c9 galberding
          proxCalib.buf += global.vcnl4020[constants::DiWheelDrive::PROX_FRONT_LEFT].getProximityScaledWoOffset()
394
                          + global.vcnl4020[constants::DiWheelDrive::PROX_FRONT_RIGHT].getProximityScaledWoOffset();
395 10bf9cc0 galberding
          this->sleep(CAN::UPDATE_PERIOD);
396
        }
397
        proxCalib.buf = proxCalib.buf / (2*proxCalib.meanWindow);
398 8dced1c9 galberding
399 10bf9cc0 galberding
        if(proxCalib.calibrateBlack){
400
          global.linePID.BThresh = proxCalib.buf;
401
        }else  {
402
          global.linePID.WThresh  = proxCalib.buf;
403
        }
404
          chprintf((BaseSequentialStream*)&global.sercanmux1, "Black: %d, White: %d!\n", global.linePID.BThresh, global.linePID.WThresh);
405
406
        newState = states::IDLE;
407
      break;
408
      // ---------------------------------------
409 181f2892 galberding
      case states::IDLE:
410 27d4e1fa galberding
        global.motorcontrol.setMotorEnable(true);
411 181f2892 galberding
        setRpmSpeed(stop);
412
        if(/* checkPinVoltage() && */ checkPinEnabled()){
413
          global.robot.requestCharging(0);
414
        }
415 10bf9cc0 galberding
        // pCtrl.pFactor = 0;
416
        pCtrl.staticCont = 0;
417 fbcb25cc galberding
        utCount.whiteCount = 0;
418 10bf9cc0 galberding
        utCount.ringProxCount = 0;
419