Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (7.311 KB)

1
#include "userthread.hpp"
2

    
3
#include "global.hpp"
4

    
5
#include "linefollow2.hpp" 
6

    
7
using namespace amiro;
8

    
9
extern Global global;
10

    
11
enum class states{
12
  FOLLOW_LINE,
13
  OCCUPY,
14
  RELEASE,
15
  CHARGING
16
};
17

    
18
enum msg_content{
19
  STOP, 
20
  START,
21
  EDGE_LEFT,
22
  EDGE_RIGHT,
23
  FUZZY,
24
  DOCKING
25
};
26

    
27
// User thread state:
28
states utState = states::FOLLOW_LINE;
29

    
30
// a buffer for the z-value of the accelerometer
31
int16_t accel_z;
32
bool running = false;
33

    
34
int vcnl4020AmbientLight[4] = {0};
35
int vcnl4020Proximity[4] = {0};
36

    
37

    
38
// Set the speed by the array
39
void setRpmSpeed(const int (&rpmSpeed)[2]) {
40
  global.motorcontrol.setTargetRPM(rpmSpeed[constants::DiWheelDrive::LEFT_WHEEL] * 1000000, rpmSpeed[constants::DiWheelDrive::RIGHT_WHEEL] * 1000000);
41
}
42

    
43
void lightOneLed(Color color, int idx){
44
  global.robot.setLightColor(idx, Color(color));
45
}
46

    
47
void lightAllLeds(Color color){
48
  int led = 0;
49
  for(led=0; led<8; led++){
50
        lightOneLed(color, led);
51
      }
52
}
53

    
54
/**
55
 * Get the wanted strategy from the global object.
56
 */
57
LineFollowStrategy determineStrategy(){
58
  switch(global.lfStrategy){
59
    case 0:
60
      return LineFollowStrategy::EDGE_RIGHT;
61
      break;
62
    case 1:
63
      return LineFollowStrategy::EDGE_LEFT;
64
      break;
65
    case 2:
66
      return LineFollowStrategy::FUZZY;
67
      break;
68
    case 3:
69
      return LineFollowStrategy::DOCKING;
70
    default:
71
      break;
72
  }
73
  return LineFollowStrategy::NONE;
74
}
75

    
76
/**
77
 * Blocks as long as the position changes.
78
 */
79
void checkForMotion(UserThread *ut){
80
  int motion = 1;
81
  int led = 0;
82
  types::position oldPos = global.odometry.getPosition();
83
  while(motion){
84
    ut->sleep(500);
85
    types::position tmp = global.odometry.getPosition();
86
    motion = abs(oldPos.x - tmp.x)+ abs(oldPos.y - tmp.y)+abs(oldPos.z - tmp.z);
87
    oldPos = tmp;
88
      global.robot.setLightColor((led + 1) % 8, Color(Color::YELLOW));
89
      global.robot.setLightColor(led % 8, Color(Color::BLACK));
90
      led++;
91
  }
92
}
93

    
94

    
95
/**
96
 * Turns MotorControl off and checks if position remains stable.
97
 */
98
int checkDockingSuccess(UserThread *ut){
99
  // global.motorcontrol.setTargetRPM(0,0);
100
  checkForMotion(ut);
101
  int led = 0;
102
  int success = 0;
103
  global.odometry.resetPosition();
104
  types::position start = global.startPos = global.odometry.getPosition();
105
  global.motorcontrol.toggleMotorEnable();
106
  ut->sleep(1000);
107
  types::position stop = global.endPos = global.odometry.getPosition();
108
  global.motorcontrol.toggleMotorEnable();
109
  // Amiro moved, docking was not successful
110
  if ((start.x + stop.x) || (start.y + stop.y)){
111
    for(led=0; led<8; led++){
112
      global.robot.setLightColor(led, Color(Color::RED));
113
    }
114
    success = 0;
115
  }else{
116
    for(led=0; led<8; led++){
117
      global.robot.setLightColor(led, Color(Color::GREEN));
118
    }
119
    success = 1;
120
  }
121
  
122
  ut->sleep(500);
123
  for(led=0; led<8; led++){
124
          global.robot.setLightColor(led, Color(Color::BLACK));
125
  }
126
  return success;
127
}
128

    
129
void correctPosition(UserThread *ut, LineFollow &lf, int steps){
130
  int checkWhite = 0;
131
  int rpmSpeed[2] ={0};
132
  lf.setStrategy(LineFollowStrategy::EDGE_LEFT);
133
  for (int correction=0; correction<steps; correction++){
134
    checkWhite = lf.followLine(rpmSpeed);
135
    setRpmSpeed(rpmSpeed);
136
    ut->sleep(CAN::UPDATE_PERIOD);
137
  }
138
}
139

    
140

    
141
UserThread::UserThread() :
142
  chibios_rt::BaseStaticThread<USER_THREAD_STACK_SIZE>()
143
{
144
}
145

    
146
UserThread::~UserThread()
147
{
148
}
149

    
150
msg_t
151
UserThread::main()
152
{
153
  /*
154
   * SETUP
155
   */
156
  int rpmSpeed[2] = {0};
157
  int stop[2] = {0};
158
  int proxyWheelThresh = 18000;
159
  LineFollowStrategy lStrategy;
160
  for (uint8_t led = 0; led < 8; ++led) {
161
    global.robot.setLightColor(led, Color(Color::BLACK));
162
  }
163
  running = false;
164
  LineFollow lf(&global);
165
  /*
166
   * LOOP
167
   */
168
  while (!this->shouldTerminate())
169
  {
170
        /*
171
         * read accelerometer z-value
172
         */
173
        accel_z = global.lis331dlh.getAccelerationForce(LIS331DLH::AXIS_Z);
174

    
175
        /*
176
         * evaluate the accelerometer
177
         */
178

    
179
  //Features over can: (Line Following)
180
  //SetKP
181
  //SetKI
182
  //SetKd ?
183
  //SetSleepTime
184
  //SeForwardSpeed? or SetMaxSpeed
185
  //DriveOnLeftLine
186
  //DriveOnRightLine
187
  
188
  //if accel_z<-900
189
    //send can event (one time)
190
    // Line following is started if amiro roteted
191
    if (accel_z < -900 /*-0.9g*/) { //new: (can.allowLineFollowOnTurn && accel_z < 900) || can.startLineFollow optional feature
192
        // set the front LEDs to blue for one second
193
        lightAllLeds(Color::GREEN);
194
        this->sleep(1000);
195
        lightAllLeds(Color::BLACK);
196
        running = !running;
197
    // If message was received handle it here:
198
    } else if(global.msgReceived){
199

    
200
      global.msgReceived = false;
201
      running = true;
202
      switch(global.lfStrategy){
203
        case msg_content::START:
204
          break;
205
        case msg_content::STOP:
206
          running = false;
207
          break;
208
        case msg_content::EDGE_RIGHT:
209
          lStrategy = LineFollowStrategy::EDGE_RIGHT;
210
          break;
211
        case  msg_content::EDGE_LEFT:
212
          lStrategy = LineFollowStrategy::EDGE_LEFT;
213
          break;
214
        case msg_content::FUZZY:
215
          lStrategy = LineFollowStrategy::FUZZY;
216
          break;
217
        case msg_content::DOCKING:
218
          utState = states::OCCUPY;
219
          lStrategy = LineFollowStrategy::EDGE_RIGHT;
220
          break;
221
        default:
222
          break;
223
      }
224
    
225
    }
226

    
227
    if(running){
228
      switch(utState){
229
        case states::FOLLOW_LINE:{
230
          // LineFollowStrategy lStrategy = determineStrategy();
231
          if(lStrategy == LineFollowStrategy::DOCKING){
232
            utState = states::OCCUPY;
233
            break;
234
          }
235
          lf.setStrategy(lStrategy);
236
          lf.followLine(rpmSpeed);
237
          setRpmSpeed(rpmSpeed);
238
          break;
239
        }
240
        case states::OCCUPY:{
241
          // Get Wheel proxy sensors
242
          int WL = global.vcnl4020[constants::DiWheelDrive::PROX_WHEEL_LEFT].getProximityScaledWoOffset();
243
          int WR = global.vcnl4020[constants::DiWheelDrive::PROX_WHEEL_LEFT].getProximityScaledWoOffset();
244
          // Check for black
245
          if ((WL+WR) < proxyWheelThresh){ /*TODO: Only check for one sensor */
246
            global.motorcontrol.setTargetRPM(0,0);
247

    
248
            // Stop when in docking state and take further actions
249
            if(lf.getStrategy() == LineFollowStrategy::DOCKING){
250
              if(checkDockingSuccess(this)){
251
                utState = states::CHARGING;
252
                break;
253
              }else{
254
                correctPosition(this, lf, 250);
255
                lf.setStrategy(LineFollowStrategy::DOCKING);
256
                // break;
257
              }
258
            }else{
259
              checkForMotion(this);
260
              // 180° Rotation 
261
              global.distcontrol.setTargetPosition(0, 3141592, 10000);
262
              // BaseThread::sleep(8000);
263
              checkForMotion(this);
264
              correctPosition(this, lf, 250);
265
              // break;
266
              lf.setStrategy(LineFollowStrategy::DOCKING);
267
              
268
            }
269
          }
270

    
271
          // Set correct following
272
          // lf.setStrategy(LineFollowStrategy::EDGE_RIGHT);
273
          lf.followLine(rpmSpeed);
274
          setRpmSpeed(rpmSpeed);
275
          
276
          break;
277
        }
278
        case states::RELEASE:{
279
          break;
280
        }
281
        case states::CHARGING:{
282
          setRpmSpeed(stop);
283
          break;
284
        }
285
        default:{
286
          break;
287
        }
288
      }
289

    
290
    }else{
291
      // Stop
292
        setRpmSpeed(stop);
293
      }
294

    
295
    this->sleep(CAN::UPDATE_PERIOD);
296
  }
297

    
298
  return RDY_OK;
299
}