Revision d314ad6f

View differences:

devices/DiWheelDrive/linefollow.cpp
1 1
#include "global.hpp"
2
#include "linefollow2.hpp" 
2
#include "linefollow.hpp" 
3 3
#include <cmath>
4 4

  
5 5

  
devices/DiWheelDrive/linefollow.hpp
10 10
namespace amiro {
11 11
  
12 12
  enum LineFollowStrategy{
13
  EDGE_LEFT,
14
  TRANSITION_L_R,
15
  TRANSITION_R_L,
16
  EDGE_RIGHT,
13
  EDGE_LEFT,      // driving on the left edge of a black line
14
  TRANSITION_L_R, // Transition from left to right edge
15
  TRANSITION_R_L, // transition from right to left edge
16
  EDGE_RIGHT,     // driving on the right edge of a black line
17 17
  REVERSE,
18
  MIDDLE,
18
  MIDDLE,         // not working, use FUZZY instead
19 19
  FUZZY,
20 20
  NONE
21 21
  };
......
30 30
{
31 31
public:
32 32

  
33
  // TODO: Documentation
34 33
  int biggestDiff = 0;
35 34
  Global *global;
36 35
  LineFollow(Global *global);
37 36
  LineFollow(Global *global, LineFollowStrategy strategy);
37
  /**
38
   * Entry method which should be called to follow a line.
39
   * 
40
   * @param rpmSpeed speed that will be determained
41
   * @return white flag, 1 if white is detected  
42
   */
38 43
  int followLine(int (&rpmSpeed)[2]);
44

  
45
  /**
46
   * Setter for LineFollowStrategy which triggers transition behavior.
47
   * 
48
   * To prevent random turns while changeing the strategy a transition state is set.
49
   * In case the strategy needs to be switched immediately use promptStrategyChange().
50
   * 
51
   * @param strategy 
52
   */
39 53
  void setStrategy(LineFollowStrategy strategy);
40 54
  void promptStrategyChange(LineFollowStrategy strategy);
41 55
  LineFollowStrategy getStrategy();
......
63 77
  const int greyStartRising = blackStartFalling; // Where grey starts rising
64 78
  const int greyOff = whiteOn; // Where grey is completely off again
65 79

  
66
  private:
67
    int delta();
68
    int getError();
69
    int transitionError(int FL, int FR, int targetL, int targetR);
70
    int getPidCorrectionSpeed();
71
    void lineFollowing(int (&proximity)[4], int (&rpmFuzzyCtrl)[2]);
72
    // void defuzz(colorMember (&member)[4], int (&rpmFuzzyCtrl)[2]);
73
    Color memberToLed(colorMember member);
74
    void defuzzyfication(colorMember (&member)[4], int (&rpmFuzzyCtrl)[2]);
75
    colorMember getMember(float (&fuzzyValue)[3]);
76
    void fuzzyfication(int sensorValue, float (&fuzziedValue)[3]);
77
    void copyRpmSpeed(const int (&source)[2], int (&target)[2]);
78

  
79
    char whiteFlag = 0;
80
    LineFollowStrategy strategy = LineFollowStrategy::EDGE_RIGHT;
81
    float K_p = 0.002;
82
    float K_i = 0;
83
    float K_d = 0;
84
    int accumHist = 0;
85
    float oldError = 0;
86
    int trans = 0;
87
    int vcnl4020AmbientLight[4] = {0};
88
    int vcnl4020Proximity[4] = {0};
80
private:
81
  /**
82
   * Calculate the error from front sensors.
83
   */
84
  int getError();
85

  
86
  /**
87
   * Error calculation while changing from one EDGE_* strategy to another.
88
   * This prevents the AMiRo from random turns while switching strategies.
89
   * 
90
   * @param FL value of left front sensor
91
   * @param FR value of right front sensor
92
   * @param targetL left threshold 
93
   * @param targetR right threshold
94
   */
95
  int transitionError(int FL, int FR, int targetL, int targetR);
96

  
97
  /**
98
   * Use the error according to the strategy to calculate the correction speed.
99
   * Currently only the P part of the PID controller is used to calculate the 
100
   * correction speed.
101
   */
102
  int getPidCorrectionSpeed();
103

  
104
  // Fuzzy line following methods--------------
105
  void lineFollowing(int (&proximity)[4], int (&rpmFuzzyCtrl)[2]);
106
  Color memberToLed(colorMember member);
107
  void defuzzyfication(colorMember (&member)[4], int (&rpmFuzzyCtrl)[2]);
108
  colorMember getMember(float (&fuzzyValue)[3]);
109
  void fuzzyfication(int sensorValue, float (&fuzziedValue)[3]);
110
  void copyRpmSpeed(const int (&source)[2], int (&target)[2]);
111
  int vcnl4020AmbientLight[4] = {0};
112
  int vcnl4020Proximity[4] = {0};
113
  // -----------------------------------------
114
  LineFollowStrategy strategy = LineFollowStrategy::EDGE_RIGHT;
115
  char whiteFlag = 0;
116
  int trans = 0;
117

  
118
  // PID controller components ---------------
119
  float K_p = 0.002;
120
  float K_i = 0;
121
  float K_d = 0;
122
  int accumHist = 0;
123
  float oldError = 0;
124
  // ----------------------------------------
89 125
};
90 126

  
91 127

  
devices/DiWheelDrive/linefollow2.cpp
1
#include "global.hpp"
2
#include "linefollow2.hpp" 
3
#include <cmath>
4

  
5

  
6

  
7
LineFollow::LineFollow(Global *global){
8
    this->global = global;
9
}
10
LineFollow::LineFollow(Global *global, LineFollowStrategy strategy){
11
    this->global = global;
12
    this-> strategy = strategy;
13
}
14

  
15
/**
16
 * Calculate the error from front proxi sensors and fixed threshold values for those sensors.
17
 */
18
int LineFollow::getError(){
19
    // Get actual sensor data of both front sensors
20
    int FL = global->vcnl4020[constants::DiWheelDrive::PROX_FRONT_LEFT].getProximityScaledWoOffset();
21
    int FR = global->vcnl4020[constants::DiWheelDrive::PROX_FRONT_RIGHT].getProximityScaledWoOffset();
22
    int targetL = global->threshProxyL;
23
    int targetR = global->threshProxyR;
24
    int error = 0;
25
    switch (this->strategy)
26
    {
27
    case LineFollowStrategy::EDGE_RIGHT: case LineFollowStrategy::DOCKING:
28
        error = -(FL -targetL + FR - targetR);
29
        break;
30
    case LineFollowStrategy::EDGE_LEFT:
31
        error = (FL -targetL + FR - targetR);
32
        break;
33
    case LineFollowStrategy::MIDDLE:
34
        // Assume that the smallest value means driving in the middle
35
        targetL = targetR = !(targetL<targetR)?targetR:targetL;
36
        error = (FL -targetL + FR - targetR);
37
        break;
38
    
39
    default:
40
        break;
41
    }
42
    // Debugging stuff ------
43
    if (global->enableRecord){
44
        global->senseRec[global->sensSamples].error = error;
45
        global->senseRec[global->sensSamples].FL = global->vcnl4020[constants::DiWheelDrive::PROX_FRONT_LEFT].getProximityScaledWoOffset();
46
        global->senseRec[global->sensSamples].FR = global->vcnl4020[constants::DiWheelDrive::PROX_FRONT_RIGHT].getProximityScaledWoOffset();
47
        global->sensSamples++;
48
        }
49
    // ----------------------
50
    // Register white values
51
    if (FL+FR > global->threshWhite){
52
        whiteFlag = 1;
53
    }else{
54
        whiteFlag = 0;
55
    }
56
    return error;
57
}
58

  
59
int LineFollow::followLine(int (&rpmSpeed)[2]){
60
    int correctionSpeed = 0;
61
    switch (this->strategy)
62
    {
63
    case LineFollowStrategy::FUZZY:
64
      for (int i = 0; i < 4; i++) {
65
          vcnl4020AmbientLight[i] = global->vcnl4020[i].getAmbientLight();
66
          vcnl4020Proximity[i] = global->vcnl4020[i].getProximityScaledWoOffset();
67
      }
68
      lineFollowing(vcnl4020Proximity, rpmSpeed);
69
      break;
70

  
71
    case LineFollowStrategy::DOCKING:
72
      correctionSpeed = -getPidCorrectionSpeed();
73
      rpmSpeed[constants::DiWheelDrive::LEFT_WHEEL] = -global->forwardSpeed;
74

  
75
      rpmSpeed[constants::DiWheelDrive::RIGHT_WHEEL] = -global->forwardSpeed;
76
      
77
      break;
78

  
79
    default:
80
      correctionSpeed = getPidCorrectionSpeed();
81
      // chprintf((BaseSequentialStream*) &SD1, "Correction: %d, thresh: %d\n",correctionSpeed,  global->threshWhite);
82

  
83
      rpmSpeed[constants::DiWheelDrive::LEFT_WHEEL] =   global->forwardSpeed + correctionSpeed;
84

  
85
      rpmSpeed[constants::DiWheelDrive::RIGHT_WHEEL] = global->forwardSpeed - correctionSpeed;
86
      break;
87
    }
88
    return whiteFlag;
89
}
90

  
91

  
92
/**
93
 * Pid controller which returns a corrections speed.
94
 */
95
int LineFollow::getPidCorrectionSpeed(){
96
    int error = getError();
97
    int sloap = error - oldError;
98
    int correctionSpeed = (int) (Kp*error + Ki*accumHist + Kd*sloap);
99
    oldError = error;
100
    // accumHist += (int) (0.01 * error);
101
    if (abs(error) > global->maxDist.error){
102
        global->maxDist.error = error;
103
    }
104
    return correctionSpeed;
105
}
106

  
107

  
108
void LineFollow::setStrategy(LineFollowStrategy strategy){
109
    this->strategy = strategy;
110
}
111

  
112
LineFollowStrategy LineFollow::getStrategy(){
113
      return this->strategy;
114
}
115
void LineFollow::setGains(float Kp, float Ki, float Kd){
116
    this->Kp = Kp;
117
    this->Ki = Ki;
118
    this->Kd = Kd;
119
}
120

  
121

  
122

  
123

  
124

  
125
// Lagacy code, fuzzy following-----------------------------------------
126
// Line following by a fuzzy controler
127
void LineFollow::lineFollowing(int (&proximity)[4], int (&rpmFuzzyCtrl)[2]) {
128
  // FUZZYFICATION
129
  // First we need to get the fuzzy value for our 3 values {BLACK, GREY, WHITE}
130
  float leftWheelFuzzyMemberValues[3], leftFrontFuzzyMemberValues[3], rightFrontFuzzyMemberValues[3], rightWheelFuzzyMemberValues[3];
131
  fuzzyfication(proximity[constants::DiWheelDrive::PROX_WHEEL_LEFT], leftWheelFuzzyMemberValues);
132
  fuzzyfication(proximity[constants::DiWheelDrive::PROX_FRONT_LEFT], leftFrontFuzzyMemberValues);
133
  fuzzyfication(proximity[constants::DiWheelDrive::PROX_FRONT_RIGHT], rightFrontFuzzyMemberValues);
134
  fuzzyfication(proximity[constants::DiWheelDrive::PROX_WHEEL_RIGHT], rightWheelFuzzyMemberValues);
135

  
136
  // INFERENCE RULE DEFINITION
137
  // Get the member for each sensor
138
  colorMember member[4];
139
  member[constants::DiWheelDrive::PROX_WHEEL_LEFT] = getMember(leftWheelFuzzyMemberValues);
140
  member[constants::DiWheelDrive::PROX_FRONT_LEFT] = getMember(leftFrontFuzzyMemberValues);
141
  member[constants::DiWheelDrive::PROX_FRONT_RIGHT] = getMember(rightFrontFuzzyMemberValues);
142
  member[constants::DiWheelDrive::PROX_WHEEL_RIGHT] = getMember(rightWheelFuzzyMemberValues);
143

  
144
  // visualize sensors via LEDs
145
  global->robot.setLightColor(constants::LightRing::LED_WNW, memberToLed(member[constants::DiWheelDrive::PROX_WHEEL_LEFT]));
146
  global->robot.setLightColor(constants::LightRing::LED_NNW, memberToLed(member[constants::DiWheelDrive::PROX_FRONT_LEFT]));
147
  global->robot.setLightColor(constants::LightRing::LED_NNE, memberToLed(member[constants::DiWheelDrive::PROX_FRONT_RIGHT]));
148
  global->robot.setLightColor(constants::LightRing::LED_ENE, memberToLed(member[constants::DiWheelDrive::PROX_WHEEL_RIGHT]));
149

  
150
  // chprintf((BaseSequentialStream*) &SD1, "Left: BLACK: %f, GREY: %f, WHITE: %f\r\n", leftWheelFuzzyMemberValues[BLACK], leftWheelFuzzyMemberValues[GREY], leftWheelFuzzyMemberValues[WHITE]);
151
  // chprintf((BaseSequentialStream*) &SD1, "Right: BLACK: %f, GREY: %f, WHITE: %f\r\n", rightFuzzyMemberValues[BLACK], rightFuzzyMemberValues[GREY], rightFuzzyMemberValues[WHITE]);
152

  
153
  // DEFUZZYFICATION
154
  defuzzyfication(member, rpmFuzzyCtrl);
155
  // defuzz(member, rpmFuzzyCtrl);
156
}
157

  
158

  
159
Color LineFollow::memberToLed(colorMember member) {
160
  switch (member) {
161
    case BLACK:
162
      return Color(Color::GREEN);
163
    case GREY:
164
      return Color(Color::YELLOW);
165
    case WHITE:
166
      return Color(Color::RED);
167
    default:
168
      return Color(Color::WHITE);
169
  }
170
}
171

  
172
void LineFollow::defuzzyfication(colorMember (&member)[4], int (&rpmFuzzyCtrl)[2]) {
173
    whiteFlag = 0;
174
  // all sensors are equal
175
  if (member[constants::DiWheelDrive::PROX_WHEEL_LEFT] == member[constants::DiWheelDrive::PROX_FRONT_LEFT] &&
176
      member[constants::DiWheelDrive::PROX_FRONT_LEFT] == member[constants::DiWheelDrive::PROX_FRONT_RIGHT] &&
177
      member[constants::DiWheelDrive::PROX_FRONT_RIGHT] == member[constants::DiWheelDrive::PROX_WHEEL_RIGHT]) {
178
    // something is wrong -> stop
179
    copyRpmSpeed(rpmHalt, rpmFuzzyCtrl);
180
  // both front sensor detect a line
181
  } else if (member[constants::DiWheelDrive::PROX_FRONT_LEFT] == BLACK &&
182
      member[constants::DiWheelDrive::PROX_FRONT_RIGHT] == BLACK) {
183
    // straight
184
    copyRpmSpeed(global->rpmForward, rpmFuzzyCtrl);
185
  // exact one front sensor detects a line
186
  } else if (member[constants::DiWheelDrive::PROX_FRONT_LEFT] == BLACK ||
187
             member[constants::DiWheelDrive::PROX_FRONT_RIGHT] == BLACK) {
188
    // soft correction
189
    if (member[constants::DiWheelDrive::PROX_FRONT_LEFT] == GREY) {
190
      // soft right
191
      copyRpmSpeed(global->rpmSoftRight, rpmFuzzyCtrl);
192
    } else if (member[constants::DiWheelDrive::PROX_FRONT_LEFT] == WHITE) {
193
      // hard right
194
      copyRpmSpeed(global->rpmHardRight, rpmFuzzyCtrl);
195
    } else if (member[constants::DiWheelDrive::PROX_FRONT_RIGHT] == GREY) {
196
      // soft left
197
      copyRpmSpeed(global->rpmSoftLeft, rpmFuzzyCtrl);
198
    } else if (member[constants::DiWheelDrive::PROX_FRONT_RIGHT] == WHITE) {
199
      // hard left
200
      copyRpmSpeed(global->rpmHardLeft, rpmFuzzyCtrl);
201
    }
202
  // both wheel sensors detect a line
203
  } else if (member[constants::DiWheelDrive::PROX_WHEEL_LEFT] == BLACK &&
204
             member[constants::DiWheelDrive::PROX_WHEEL_RIGHT] == BLACK) {
205
    // something is wrong -> stop
206
    copyRpmSpeed(rpmHalt, rpmFuzzyCtrl);
207
  // exactly one wheel sensor detects a line
208
  } else if (member[constants::DiWheelDrive::PROX_WHEEL_LEFT] == BLACK ||
209
             member[constants::DiWheelDrive::PROX_WHEEL_RIGHT] == BLACK) {
210
    if (member[constants::DiWheelDrive::PROX_WHEEL_LEFT] == BLACK) {
211
      // turn left
212
      copyRpmSpeed(rpmTurnLeft, rpmFuzzyCtrl);
213
    } else if (member[constants::DiWheelDrive::PROX_WHEEL_RIGHT] == BLACK) {
214
      // turn right
215
      copyRpmSpeed(rpmTurnRight, rpmFuzzyCtrl);
216
    }
217
  // both front sensors may detect a line
218
  } else if (member[constants::DiWheelDrive::PROX_FRONT_LEFT] == GREY &&
219
             member[constants::DiWheelDrive::PROX_FRONT_RIGHT] == GREY) {
220
    if (member[constants::DiWheelDrive::PROX_WHEEL_LEFT] == GREY) {
221
      // turn left
222
      copyRpmSpeed(rpmTurnLeft, rpmFuzzyCtrl);
223
    } else if (member[constants::DiWheelDrive::PROX_WHEEL_RIGHT] == GREY) {
224
      // turn right
225
      copyRpmSpeed(rpmTurnRight, rpmFuzzyCtrl);
226
    }
227
  // exactly one front sensor may detect a line
228
  } else if (member[constants::DiWheelDrive::PROX_FRONT_LEFT] == GREY ||
229
             member[constants::DiWheelDrive::PROX_FRONT_RIGHT] == GREY) {
230
    if (member[constants::DiWheelDrive::PROX_FRONT_LEFT] == GREY) {
231
      // turn left
232
      copyRpmSpeed(rpmTurnLeft, rpmFuzzyCtrl);
233
    } else if (member[constants::DiWheelDrive::PROX_FRONT_RIGHT] == GREY) {
234
      // turn right
235
      copyRpmSpeed(rpmTurnRight, rpmFuzzyCtrl);
236
    }
237
  // both wheel sensors may detect a line
238
  } else if (member[constants::DiWheelDrive::PROX_WHEEL_LEFT] == GREY &&
239
             member[constants::DiWheelDrive::PROX_WHEEL_RIGHT] == GREY) {
240
    // something is wrong -> stop
241
    copyRpmSpeed(rpmHalt, rpmFuzzyCtrl);
242
  // exactly one wheel sensor may detect a line
243
  } else if (member[constants::DiWheelDrive::PROX_WHEEL_LEFT] == GREY ||
244
             member[constants::DiWheelDrive::PROX_WHEEL_RIGHT] == GREY) {
245
    if (member[constants::DiWheelDrive::PROX_WHEEL_LEFT] == GREY) {
246
      // turn left
247
      copyRpmSpeed(rpmTurnLeft, rpmFuzzyCtrl);
248
    } else if (member[constants::DiWheelDrive::PROX_WHEEL_RIGHT] == GREY) {
249
      // turn right
250
      copyRpmSpeed(rpmTurnRight, rpmFuzzyCtrl);
251
    }
252
  // no sensor detects anything 
253
  } else {
254
    // line is lost -> stop
255
    whiteFlag = 1;
256
    copyRpmSpeed(rpmHalt, rpmFuzzyCtrl);
257
  }
258
    chprintf((BaseSequentialStream*) &SD1, "Fuzzy Speed: Left: %d, Right: %d\n", rpmFuzzyCtrl[0], rpmFuzzyCtrl[1]);
259
  return;
260
}
261

  
262
colorMember LineFollow::getMember(float (&fuzzyValue)[3]) {
263
  colorMember member;
264

  
265
  if (fuzzyValue[BLACK] > fuzzyValue[GREY])
266
    if (fuzzyValue[BLACK] > fuzzyValue[WHITE])
267
      member = BLACK;
268
    else
269
      member = WHITE;
270
  else
271
    if (fuzzyValue[GREY] > fuzzyValue[WHITE])
272
      member = GREY;
273
    else
274
      member = WHITE;
275

  
276
  return member;
277
}
278

  
279
// Fuzzyfication of the sensor values
280
void LineFollow::fuzzyfication(int sensorValue, float (&fuzziedValue)[3]) {
281
  if (sensorValue < blackStartFalling ) {
282
    // Only black value
283
    fuzziedValue[BLACK] = 1.0f;
284
    fuzziedValue[GREY] = 0.0f;
285
    fuzziedValue[WHITE] = 0.0f;
286
  } else if (sensorValue > whiteOn ) {
287
    // Only white value
288
    fuzziedValue[BLACK] = 0.0f;
289
    fuzziedValue[GREY] = 0.0f;
290
    fuzziedValue[WHITE] = 1.0f;
291
  } else if ( sensorValue < greyMax) {
292
    // Some greyisch value between black and grey
293

  
294
    // Black is going down
295
    if ( sensorValue > blackOff) {
296
      fuzziedValue[BLACK] = 0.0f;
297
    } else {
298
      fuzziedValue[BLACK] = static_cast<float>(sensorValue-blackOff) / (blackStartFalling-blackOff);
299
    }
300

  
301
    // Grey is going up
302
    if ( sensorValue < greyStartRising) {
303
      fuzziedValue[GREY] = 0.0f;
304
    } else {
305
      fuzziedValue[GREY] = static_cast<float>(sensorValue-greyStartRising) / (greyMax-greyStartRising);
306
    }
307

  
308
    // White is absent
309
    fuzziedValue[WHITE] = 0.0f;
310

  
311
  } else if ( sensorValue >= greyMax) {
312
    // Some greyisch value between grey white
313

  
314
    // Black is absent
315
    fuzziedValue[BLACK] = 0.0f;
316

  
317
    // Grey is going down
318
    if ( sensorValue < greyOff) {
319
      fuzziedValue[GREY] = static_cast<float>(sensorValue-greyOff) / (greyMax-greyOff);
320
    } else {
321
      fuzziedValue[GREY] = 0.0f;
322
    }
323

  
324
    // White is going up
325
    if ( sensorValue < whiteStartRising) {
326
      fuzziedValue[WHITE] = 0.0f;
327
    } else {
328
      fuzziedValue[WHITE] = static_cast<float>(sensorValue-whiteStartRising) / (whiteOn-whiteStartRising);
329
    }
330
  }
331
}
332

  
333
void LineFollow::copyRpmSpeed(const int (&source)[2], int (&target)[2]) {
334
  target[constants::DiWheelDrive::LEFT_WHEEL] = source[constants::DiWheelDrive::LEFT_WHEEL];
335
  target[constants::DiWheelDrive::RIGHT_WHEEL] = source[constants::DiWheelDrive::RIGHT_WHEEL];
336
  // chprintf((BaseSequentialStream*) &SD1, "Speed left: %d, Speed right: %d\r\n", target[0], target[1]);
337
}
devices/DiWheelDrive/linefollow2.hpp
1
#ifndef AMIRO_LINEFOLLOWING_H
2
#define AMIRO_LINEFOLLOWING_H
3

  
4
#include <ch.hpp>
5
#include "global.hpp"
6
#include <amiroosconf.h>
7

  
8
namespace amiro {
9
  
10
  enum class LineFollowStrategy{
11
  EDGE_LEFT,
12
  EDGE_RIGHT,
13
  DOCKING,
14
  MIDDLE,
15
  FUZZY,
16
  NONE
17
  };
18

  
19
enum colorMember : uint8_t {
20
	BLACK=0,
21
	GREY=1,
22
	WHITE=2
23
};
24

  
25
class LineFollow
26
{
27
public:
28

  
29
  
30
  int biggestDiff = 0;
31
  Global *global;
32
  LineFollow(Global *global);
33
  LineFollow(Global *global, LineFollowStrategy strategy);
34
  // void calibrateZiegler(float KCrit, int rpmSpeed[2]);
35
  int followLine(int (&rpmSpeed)[2]);
36
  // int followLeftEdge(int rpmSpeed[2]);
37
  // int followRightEdge(int rpmSpeed[2]);
38
  // int followMiddle(int rpmSpeed[2]);
39
  void setStrategy(LineFollowStrategy strategy);
40
  LineFollowStrategy getStrategy();
41
  void setGains(float Kp, float Ki, float Kd);
42

  
43

  
44
  const int rpmTurnLeft[2] = {-10, 10};
45
  const int rpmTurnRight[2] = {rpmTurnLeft[1],rpmTurnLeft[0]};
46
  const int rpmHalt[2] = {0, 0};
47
  // Definition of the fuzzyfication function
48
  //  | Membership
49
  // 1|_B__   G    __W__
50
  //  |    \  /\  /
51
  //  |     \/  \/
52
  //  |_____/\__/\______ Sensor values
53
  // SEE MATLAB SCRIPT "fuzzyRule.m" for adjusting the values
54
  // All values are "raw sensor values"
55
  /* Use these values for white ground surface (e.g. paper) */
56

  
57
  const int blackStartFalling = 0x1000; // Where the black curve starts falling
58
  const int blackOff = 0x1800; // Where no more black is detected
59
  const int whiteStartRising = 0x2800; // Where the white curve starts rising
60
  const int whiteOn = 0x6000; // Where the white curve has reached the maximum value
61
  const int greyMax = (whiteOn + blackStartFalling) / 2; // Where grey has its maximum
62
  const int greyStartRising = blackStartFalling; // Where grey starts rising
63
  const int greyOff = whiteOn; // Where grey is completely off again
64

  
65
  private:
66
    int delta();
67
    int getError();
68
    int getPidCorrectionSpeed();
69
    void lineFollowing(int (&proximity)[4], int (&rpmFuzzyCtrl)[2]);
70
    // void defuzz(colorMember (&member)[4], int (&rpmFuzzyCtrl)[2]);
71
    Color memberToLed(colorMember member);
72
    void defuzzyfication(colorMember (&member)[4], int (&rpmFuzzyCtrl)[2]);
73
    colorMember getMember(float (&fuzzyValue)[3]);
74
    void fuzzyfication(int sensorValue, float (&fuzziedValue)[3]);
75
    void copyRpmSpeed(const int (&source)[2], int (&target)[2]);
76

  
77
    char whiteFlag = 0;
78
    LineFollowStrategy strategy = LineFollowStrategy::EDGE_RIGHT;
79
    float Kp = 0.002;
80
    float Ki = 0;
81
    float Kd = 0;
82
    int accumHist = 0;
83
    float oldError = 0;
84
    int vcnl4020AmbientLight[4] = {0};
85
    int vcnl4020Proximity[4] = {0};
86
};
87

  
88

  
89

  
90
} // end of namespace amiro
91

  
92
#endif // AMIRO_LINEFOLLOWING_H

Also available in: Unified diff