NXPCUP-libary
Library for car's control board on NXPCUP competition based on the Mbed framework.
ObstacleDetectorWithServo.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include <optional>
4 
5 #include "Image.h"
6 #include "Servo.h"
7 #include "mbed.h"
8 
9 namespace nxpcup {
10 
12 public:
13  struct Config {
14  PinName sensorPin;
19  bool isDeactivate = false;
21  // 5 degree step is 36 image size...
22  // 10 degree step is 18 image size...
23  static constexpr int IMAGE_SIZE = 30;
24  static constexpr int SERVO_MAX_RANGE_DEGREE = 180;
25  };
26 
27  enum class AvoidingObstacle {
28  no,
29  onRightSide,
30  onLeftSide
31  };
32 
33  using ImageType = uint16_t;
35 
42  : m_sensor(config.sensorPin)
43  , m_servo(config.servoConfig)
44  , m_config(config){};
45 
52  int servoAngle(int index)
53  {
54  int servoAngleRange = m_servo.getMaxAngle() - m_servo.getMinAngle();
55  auto angle = m_servo.getMinAngle() + servoAngleRange * index / m_image.size;
56  return angle;
57  }
58 
62  int servoPositionDegree() const
63  {
64  return m_servoPositionDegree;
65  }
66 
70  int sensorValue() const
71  {
72  return m_sensorValue;
73  }
74 
83  int error(float encoderDistance,
84  int borderDetectorError,
85  int leftBorder,
86  int rightBorder)
87  {
88  update();
89  check(encoderDistance);
90 
91  if (m_config.isDeactivate) {
92  return borderDetectorError;
93  }
94 
95  if (m_avoidingObstacle == AvoidingObstacle::no) {
96  return borderDetectorError;
97  }
98  if (m_avoidingObstacle == AvoidingObstacle::onLeftSide) {
99  return leftBorder - (64 - m_config.moveFromObstacle); // see just right line;
100  }
101  // obstacle on the right side
102  return rightBorder - (64 + m_config.moveFromObstacle);
103  ; // see just left line
104  }
105 
112  {
113  return m_avoidingObstacle;
114  }
115 
122  {
123  switch (m_avoidingObstacle) {
125  default:
126  return 0;
128  return -1;
130  return 1;
131  }
132  }
133 
140  {
141  return m_distanceThatTriggered;
142  }
143 
147  Config config() const
148  {
149  return m_config;
150  }
151 
158  {
159  m_config = config;
160  reset();
161  }
162 
166  void reset()
167  {
168  m_encoderDistanceStart = 0;
169  m_avoidingObstacle = AvoidingObstacle::no;
170  }
171 
172 private:
173  int update()
174  {
175  // filtration - average
176  m_sensorValue = 0;
177  for (int i = 0; i < 10; ++i) {
178  m_sensorValue += m_sensor.read_u16();
179  }
180  m_sensorValue /= 10;
181 
182  m_image[m_index] = m_sensorValue;
183 
184  if (m_direction == 1) {
185  m_index++;
186  if (m_index == (m_image.size - 1)) {
187  m_direction = -1;
188  }
189  } else if (m_direction == -1) {
190  m_index--;
191  if (m_index == 0) {
192  m_direction = 1;
193  }
194  }
195 
196  m_servoPositionDegree = servoAngle(m_index);
197  m_servo.setAngle(m_servoPositionDegree);
198 
199  return m_sensorValue;
200  }
201 
202  std::optional<int> checkObstacleAngle()
203  {
204  Image processed = m_image;
205  int maxElementIndex = std::max_element(processed.begin(), processed.end())
206  - processed.begin();
207 
208  int maxElementValue = processed[maxElementIndex];
209  if (maxElementValue < m_config.thresholdDistance) {
210  return {};
211  }
212  m_distanceThatTriggered = maxElementValue;
213  return { servoAngle(maxElementIndex) };
214  }
215 
216  void check(float encoderDistance)
217  {
218  if (m_avoidingObstacle == AvoidingObstacle::no) {
219  auto obstacle = checkObstacleAngle();
220 
221  if (!obstacle) {
222  return;
223  }
224  if (*obstacle < 90) {
225  m_avoidingObstacle = AvoidingObstacle::onLeftSide; // see just right line;
226  } else {
227  m_avoidingObstacle = AvoidingObstacle::onRightSide; // see just left line
228  }
229  m_encoderDistanceStart = encoderDistance;
230  } else {
231  if (m_encoderDistanceStart + m_config.encoderAvoidDistance < encoderDistance) {
232  m_avoidingObstacle = AvoidingObstacle::no;
233  }
234  }
235  }
236 
237  AnalogIn m_sensor;
238  Servo m_servo;
239  Config m_config;
240 
241  AvoidingObstacle m_avoidingObstacle = AvoidingObstacle::no;
242  float m_encoderDistanceStart = 0;
243  int m_sensorValue = 0;
244  int m_servoPositionDegree = 90;
245  int m_direction = 1; // -1 = left; 1 = right
246  int m_index = 0;
247  int m_distanceThatTriggered = 0;
248  ObstacleImage m_image;
249 };
250 
251 } // namespace nxpcup
int error(float encoderDistance, int borderDetectorError, int leftBorder, int rightBorder)
Definition: ObstacleDetectorWithServo.h:83
int servoPositionDegree() const
Definition: ObstacleDetectorWithServo.h:62
void setConfig(Config &config)
Definition: ObstacleDetectorWithServo.h:157
ObstacleDetectorWithServo(Config config)
Definition: ObstacleDetectorWithServo.h:41
int servoAngle(int index)
Definition: ObstacleDetectorWithServo.h:52
const T * begin() const
Definition: Image.h:22
int sensorValue() const
Definition: ObstacleDetectorWithServo.h:70
int avoidingObstacleInteger() const
Definition: ObstacleDetectorWithServo.h:121
uint16_t ImageType
Definition: ObstacleDetectorWithServo.h:33
Definition: BorderDetector.h:6
int moveFromObstacle
Definition: ObstacleDetectorWithServo.h:17
Definition: ObstacleDetectorWithServo.h:11
Definition: ObstacleDetectorWithServo.h:13
Definition: Servo.h:9
Definition: Servo.h:11
void reset()
Definition: ObstacleDetectorWithServo.h:166
PinName sensorPin
Definition: ObstacleDetectorWithServo.h:14
Servo::Config servoConfig
Definition: ObstacleDetectorWithServo.h:15
int thresholdDistance
Definition: ObstacleDetectorWithServo.h:16
const T * end() const
Definition: Image.h:24
AvoidingObstacle avoidingObstacle() const
Definition: ObstacleDetectorWithServo.h:111
int distanceThatTriggered() const
Definition: ObstacleDetectorWithServo.h:139
static constexpr int SERVO_MAX_RANGE_DEGREE
Definition: ObstacleDetectorWithServo.h:24
float encoderAvoidDistance
Definition: ObstacleDetectorWithServo.h:18
bool isDeactivate
Definition: ObstacleDetectorWithServo.h:19
Config config() const
Definition: ObstacleDetectorWithServo.h:147
AvoidingObstacle
Definition: ObstacleDetectorWithServo.h:27
static constexpr int IMAGE_SIZE
Definition: ObstacleDetectorWithServo.h:23