footbot_distance_scanner_rotzonly_sensor.cpp
Go to the documentation of this file.
1 
8 #include <argos3/core/simulator/entity/composable_entity.h>
9 #include <argos3/core/simulator/entity/controllable_entity.h>
10 #include <argos3/core/simulator/simulator.h>
11 #include <argos3/core/simulator/space/space.h>
12 
13 namespace argos {
14 
15  /****************************************/
16  /****************************************/
17 
18  static const Real FOOTBOT_RADIUS = 0.085036758f;
19 
20  static const Real SHORT_RANGE_MIN_DISTANCE = 0.0f;
21  static const Real SHORT_RANGE_RAY_START = FOOTBOT_RADIUS;
22  static const Real SHORT_RANGE_RAY_END = FOOTBOT_RADIUS + 0.26f;
23 
24  static const Real LONG_RANGE_MIN_DISTANCE = 0.12f;
25  static const Real LONG_RANGE_RAY_START = FOOTBOT_RADIUS;
26  static const Real LONG_RANGE_RAY_END = FOOTBOT_RADIUS + 1.42f;
27 
28  static const Real SENSOR_ELEVATION = 0.123199866f;
29 
30  /****************************************/
31  /****************************************/
32 
34  m_pcRNG(nullptr),
35  m_bAddNoise(false),
36  m_cSpace(CSimulator::GetInstance().GetSpace()),
37  m_bShowRays(false) {}
38 
39  /****************************************/
40  /****************************************/
41 
43  try {
45  /* Show rays? */
46  GetNodeAttributeOrDefault(t_tree, "show_rays", m_bShowRays, m_bShowRays);
47  /* Noise range */
48  GetNodeAttributeOrDefault(t_tree, "noise_range", m_cNoiseRange, m_cNoiseRange);
49  if(m_cNoiseRange.GetSpan() > 0.0f) {
50  m_bAddNoise = true;
51  m_pcRNG = CRandom::CreateRNG("argos");
52  }
53 
54  /* sensor is enabled by default */
55  Enable();
56  }
57  catch(CARGoSException& ex) {
58  THROW_ARGOSEXCEPTION_NESTED("Initialization error in foot-bot distance scanner rot_z_only sensor.", ex);
59  }
60  }
61 
62  /****************************************/
63  /****************************************/
64 
66  m_pcEmbodiedEntity = &(c_entity.GetComponent<CEmbodiedEntity>("body"));
67  m_pcControllableEntity = &(c_entity.GetComponent<CControllableEntity>("controller"));
68  m_pcDistScanEntity = &(c_entity.GetComponent<CFootBotDistanceScannerEquippedEntity>("distance_scanner"));
69  m_pcDistScanEntity->Enable();
70  }
71 
72  /****************************************/
73  /****************************************/
74 
76  /* sensor is disabled--nothing to do */
77  if (IsDisabled()) {
78  return;
79  }
80  /* Clear the maps */
81  m_tReadingsMap.clear();
82  m_tShortReadingsMap.clear();
83  m_tLongReadingsMap.clear();
84  /* Perform calculations only if the sensor is on */
85  if(m_pcDistScanEntity->GetMode() != CFootBotDistanceScannerEquippedEntity::MODE_OFF) {
86  /* Update the readings wrt to device mode */
88  /* Sensor blocked in a position */
89  /* Recalculate the rays */
90  CalculateRaysNotRotating();
91  /* Save the rotation for next time */
92  m_cLastDistScanRotation = m_pcDistScanEntity->GetRotation();
93  /* Update the values */
94  UpdateNotRotating();
95  }
96  else {
97  /* Rotating sensor */
98  /* Recalculate the rays */
99  CalculateRaysRotating();
100  /* Update the values */
101  UpdateRotating();
102  /* Save the rotation for next time */
103  m_cLastDistScanRotation = m_pcDistScanEntity->GetRotation();
104  }
105  }
106  }
107 
108  /****************************************/
109  /****************************************/
110 
112  /* Clear the maps */
113  m_tReadingsMap.clear();
114  m_tShortReadingsMap.clear();
115  m_tLongReadingsMap.clear();
116  /* Zero the last rotation */
117  m_cLastDistScanRotation = CRadians::ZERO;
118  }
119 
120  /****************************************/
121  /****************************************/
122 
123  void CFootBotDistanceScannerRotZOnlySensor::UpdateNotRotating() {
124  /* Short range [0] */
125  CRadians cAngle = m_cLastDistScanRotation;
126  cAngle.SignedNormalize();
127  Real fReading = CalculateReadingForRay(m_cShortRangeRays0[0], SHORT_RANGE_MIN_DISTANCE);
128  m_tShortReadingsMap[cAngle] = fReading;
129  m_tReadingsMap[cAngle] = fReading;
130  /* Long range [1] */
131  cAngle += CRadians::PI_OVER_TWO;
132  cAngle.SignedNormalize();
133  fReading = CalculateReadingForRay(m_cLongRangeRays1[0], LONG_RANGE_MIN_DISTANCE);
134  m_tLongReadingsMap[cAngle] = fReading;
135  m_tReadingsMap[cAngle] = fReading;
136  /* Short range [2] */
137  cAngle += CRadians::PI_OVER_TWO;
138  cAngle.SignedNormalize();
139  fReading = CalculateReadingForRay(m_cShortRangeRays2[0], SHORT_RANGE_MIN_DISTANCE);
140  m_tShortReadingsMap[cAngle] = fReading;
141  m_tReadingsMap[cAngle] = fReading;
142  /* Long range [3] */
143  cAngle += CRadians::PI_OVER_TWO;
144  cAngle.SignedNormalize();
145  fReading = CalculateReadingForRay(m_cLongRangeRays3[0], LONG_RANGE_MIN_DISTANCE);
146  m_tLongReadingsMap[cAngle] = fReading;
147  m_tReadingsMap[cAngle] = fReading;
148  }
149 
150  /****************************************/
151  /****************************************/
152 
153 #define ADD_READING(RAYS,MAP,INDEX,MINDIST) \
154  cAngle += cInterSensorSpan; \
155  cAngle.SignedNormalize(); \
156  fReading = CalculateReadingForRay(RAYS[INDEX],MINDIST); \
157  MAP[cAngle] = fReading; \
158  m_tReadingsMap[cAngle] = fReading;
159 
160 #define ADD_READINGS(RAYS,MAP,MINDIST) \
161  ADD_READING(RAYS,MAP,1,MINDIST) \
162  ADD_READING(RAYS,MAP,2,MINDIST) \
163  ADD_READING(RAYS,MAP,3,MINDIST) \
164  ADD_READING(RAYS,MAP,4,MINDIST) \
165  ADD_READING(RAYS,MAP,5,MINDIST)
166 
167  void CFootBotDistanceScannerRotZOnlySensor::UpdateRotating() {
168  CRadians cInterSensorSpan = (m_pcDistScanEntity->GetRotation() - m_cLastDistScanRotation).UnsignedNormalize() / 6.0f;
169  CRadians cStartAngle = m_cLastDistScanRotation;
170  /* Short range [0] */
171  CRadians cAngle = cStartAngle;
172  cAngle.SignedNormalize();
173  Real fReading = CalculateReadingForRay(m_cShortRangeRays0[0], SHORT_RANGE_MIN_DISTANCE);
174  m_tShortReadingsMap[cAngle] = fReading;
175  m_tReadingsMap[cAngle] = fReading;
176  ADD_READINGS(m_cShortRangeRays0, m_tShortReadingsMap, SHORT_RANGE_MIN_DISTANCE);
177  /* Short range [2] */
178  cAngle = cStartAngle + CRadians::PI;
179  cAngle.SignedNormalize();
180  fReading = CalculateReadingForRay(m_cShortRangeRays2[0], SHORT_RANGE_MIN_DISTANCE);
181  m_tShortReadingsMap[cAngle] = fReading;
182  m_tReadingsMap[cAngle] = fReading;
183  ADD_READINGS(m_cShortRangeRays2, m_tShortReadingsMap, SHORT_RANGE_MIN_DISTANCE);
184  /* Long range [1] */
185  cAngle = cStartAngle + CRadians::PI_OVER_TWO;
186  cAngle.SignedNormalize();
187  fReading = CalculateReadingForRay(m_cLongRangeRays1[0], LONG_RANGE_MIN_DISTANCE);
188  m_tLongReadingsMap[cAngle] = fReading;
189  m_tReadingsMap[cAngle] = fReading;
190  ADD_READINGS(m_cLongRangeRays1, m_tLongReadingsMap, LONG_RANGE_MIN_DISTANCE);
191  /* Long range [3] */
192  cAngle = cStartAngle + CRadians::PI_OVER_TWO + CRadians::PI;
193  cAngle.SignedNormalize();
194  fReading = CalculateReadingForRay(m_cLongRangeRays3[0], LONG_RANGE_MIN_DISTANCE);
195  m_tLongReadingsMap[cAngle] = fReading;
196  m_tReadingsMap[cAngle] = fReading;
197  ADD_READINGS(m_cLongRangeRays3, m_tLongReadingsMap, LONG_RANGE_MIN_DISTANCE);
198  }
199 
200  /****************************************/
201  /****************************************/
202 
203  Real CFootBotDistanceScannerRotZOnlySensor::CalculateReadingForRay(const CRay3& c_ray,
204  Real f_min_distance) {
205  /* Get the closest intersection */
206  SEmbodiedEntityIntersectionItem sIntersection;
208  c_ray,
209  *m_pcEmbodiedEntity)) {
210  if(m_bShowRays) m_pcControllableEntity->AddIntersectionPoint(c_ray, sIntersection.TOnRay);
211  /* There is an intersection! */
212  Real fDistance = c_ray.GetDistance(sIntersection.TOnRay);
213  if(fDistance > f_min_distance) {
214  /* The distance is returned in meters, but the reading must be in cm */
215  if(m_bShowRays) m_pcControllableEntity->AddCheckedRay(true, c_ray);
216  return fDistance * 100.0f;
217  }
218  else {
219  /* The detected intersection was too close */
220  if(m_bShowRays) m_pcControllableEntity->AddCheckedRay(true, c_ray);
221  return -1.0f;
222  }
223  }
224  else {
225  /* No intersection */
226  if(m_bShowRays) m_pcControllableEntity->AddCheckedRay(false, c_ray);
227  return -2.0f;
228  }
229  }
230 
231  /****************************************/
232  /****************************************/
233 
234 /* Highly reuse the vectors to speed up the computation */
235 #define CALCULATE_SHORT_RANGE_RAY(ANGLE,INDEX) \
236  m_cDirection.RotateZ(ANGLE); \
237  m_cOriginRayStart = m_cDirection; \
238  m_cOriginRayEnd = m_cDirection; \
239  m_cOriginRayStart *= SHORT_RANGE_RAY_START; \
240  m_cOriginRayEnd *= SHORT_RANGE_RAY_END; \
241  m_cRayStart = m_pcEmbodiedEntity->GetOriginAnchor().Position; \
242  m_cRayStart += m_cOriginRayStart; \
243  m_cRayStart.SetZ(m_cRayStart.GetZ() + SENSOR_ELEVATION); \
244  m_cRayEnd = m_pcEmbodiedEntity->GetOriginAnchor().Position; \
245  m_cRayEnd += m_cOriginRayEnd; \
246  m_cRayEnd.SetZ(m_cRayEnd.GetZ() + SENSOR_ELEVATION); \
247  m_cShortRangeRays0[INDEX].Set(m_cRayStart, m_cRayEnd); \
248  m_cRayStart = m_pcEmbodiedEntity->GetOriginAnchor().Position; \
249  m_cRayStart -= m_cOriginRayStart; \
250  m_cRayStart.SetZ(m_cRayStart.GetZ() + SENSOR_ELEVATION); \
251  m_cRayEnd = m_pcEmbodiedEntity->GetOriginAnchor().Position; \
252  m_cRayEnd -= m_cOriginRayEnd; \
253  m_cRayEnd.SetZ(m_cRayEnd.GetZ() + SENSOR_ELEVATION); \
254  m_cShortRangeRays2[INDEX].Set(m_cRayStart, m_cRayEnd); \
255  \
256 /* Highly reuse the vectors to speed up the computation */
257 #define CALCULATE_LONG_RANGE_RAY(ANGLE,INDEX) \
258  m_cDirection.RotateZ(ANGLE); \
259  m_cOriginRayStart = m_cDirection; \
260  m_cOriginRayEnd = m_cDirection; \
261  m_cOriginRayStart *= LONG_RANGE_RAY_START; \
262  m_cOriginRayEnd *= LONG_RANGE_RAY_END; \
263  m_cRayStart = m_pcEmbodiedEntity->GetOriginAnchor().Position; \
264  m_cRayStart += m_cOriginRayStart; \
265  m_cRayStart.SetZ(m_cRayStart.GetZ() + SENSOR_ELEVATION); \
266  m_cRayEnd = m_pcEmbodiedEntity->GetOriginAnchor().Position; \
267  m_cRayEnd += m_cOriginRayEnd; \
268  m_cRayEnd.SetZ(m_cRayEnd.GetZ() + SENSOR_ELEVATION); \
269  m_cLongRangeRays1[INDEX].Set(m_cRayStart, m_cRayEnd); \
270  m_cRayStart = m_pcEmbodiedEntity->GetOriginAnchor().Position; \
271  m_cRayStart -= m_cOriginRayStart; \
272  m_cRayStart.SetZ(m_cRayStart.GetZ() + SENSOR_ELEVATION); \
273  m_cRayEnd = m_pcEmbodiedEntity->GetOriginAnchor().Position; \
274  m_cRayEnd -= m_cOriginRayEnd; \
275  m_cRayEnd.SetZ(m_cRayEnd.GetZ() + SENSOR_ELEVATION); \
276  m_cLongRangeRays3[INDEX].Set(m_cRayStart, m_cRayEnd);
277 
278  /****************************************/
279  /****************************************/
280 
281  void CFootBotDistanceScannerRotZOnlySensor::CalculateRaysNotRotating() {
282  /* We make the assumption that the foot-bot is rotated only around Z */
283  /* Get the foot-bot orientation */
284  CRadians cTmp1, cTmp2, cOrientationZ;
285  m_pcEmbodiedEntity->GetOriginAnchor().Orientation.ToEulerAngles(cOrientationZ, cTmp1, cTmp2);
286  /* Sum the distance scanner orientation */
287  cOrientationZ += m_pcDistScanEntity->GetRotation();
288  /* Calculate the 2D vector representing this rotation */
289  CVector2 cAbsoluteOrientation(1.0, cOrientationZ);
290  /* The short range sensors are oriented along the foot-bot local X */
291  m_cDirection = CVector3::X;
292  CALCULATE_SHORT_RANGE_RAY(cAbsoluteOrientation, 0);
293  /* The short range sensors are oriented along the foot-bot local Y */
294  m_cDirection = CVector3::Y;
295  CALCULATE_LONG_RANGE_RAY(cAbsoluteOrientation, 0);
296  }
297 
298  /****************************************/
299  /****************************************/
300 
301  void CFootBotDistanceScannerRotZOnlySensor::CalculateRaysRotating() {
302  /* We make the assumption that the foot-bot is rotated only around Z */
303  /* Get the foot-bot orientation */
304  CRadians cTmp1, cTmp2, cOrientationZ;
305  m_pcEmbodiedEntity->GetOriginAnchor().Orientation.ToEulerAngles(cOrientationZ, cTmp1, cTmp2);
306  /* Sum the distance scanner orientation */
307  cOrientationZ += m_cLastDistScanRotation;
308  /* Calculate the 2D vector representing this rotation */
309  CVector2 cAbsoluteOrientation(1.0, cOrientationZ);
310  /* The sensor is rotating, so calculate the span between each successive ray */
311  CVector2 cInterSensorSpan(1.0f, (m_pcDistScanEntity->GetRotation() - m_cLastDistScanRotation).UnsignedNormalize() / 6.0f);
312  /* The short range sensors are oriented along the foot-bot local X */
313  m_cDirection = CVector3::X;
314  CALCULATE_SHORT_RANGE_RAY(cAbsoluteOrientation, 0);
315  CALCULATE_SHORT_RANGE_RAY(cInterSensorSpan, 1);
316  CALCULATE_SHORT_RANGE_RAY(cInterSensorSpan, 2);
317  CALCULATE_SHORT_RANGE_RAY(cInterSensorSpan, 3);
318  CALCULATE_SHORT_RANGE_RAY(cInterSensorSpan, 4);
319  CALCULATE_SHORT_RANGE_RAY(cInterSensorSpan, 5);
320  /* The long range sensors are oriented along the foot-bot local Y */
321  m_cDirection = CVector3::Y;
322  CALCULATE_LONG_RANGE_RAY(cAbsoluteOrientation, 0);
323  CALCULATE_LONG_RANGE_RAY(cInterSensorSpan, 1);
324  CALCULATE_LONG_RANGE_RAY(cInterSensorSpan, 2);
325  CALCULATE_LONG_RANGE_RAY(cInterSensorSpan, 3);
326  CALCULATE_LONG_RANGE_RAY(cInterSensorSpan, 4);
327  CALCULATE_LONG_RANGE_RAY(cInterSensorSpan, 5);
328  }
329 
330  /****************************************/
331  /****************************************/
332 
334  "footbot_distance_scanner", "rot_z_only",
335  "Carlo Pinciroli [ilpincy@gmail.com]",
336  "1.0",
337  "The foot-bot distance scanner sensor (optimized for 2D).",
338  "This sensor accesses the foot-bot distance scanner sensor. For a complete\n"
339  "description of its usage, refer to the common interface.\n"
340  "In this implementation, the readings are calculated under the assumption that\n"
341  "the foot-bot is always parallel to the XY plane, i.e., it rotates only around\n"
342  "the Z axis. This implementation is faster than a 3D one and should be used\n"
343  "only when the assumption about the foot-bot rotation holds.\n\n"
344 
345  "This sensor is enabled by default.\n\n"
346 
347  "REQUIRED XML CONFIGURATION\n\n"
348  " <controllers>\n"
349  " ...\n"
350  " <my_controller ...>\n"
351  " ...\n"
352  " <sensors>\n"
353  " ...\n"
354  " <footbot_distance_scanner implementation=\"rot_z_only\" />\n"
355  " ...\n"
356  " </sensors>\n"
357  " ...\n"
358  " </my_controller>\n"
359  " ...\n"
360  " </controllers>\n\n"
361  "OPTIONAL XML CONFIGURATION\n\n"
362  "It is possible to draw the rays shot by the distance scanner in the OpenGL\n"
363  "visualization. This can be useful for sensor debugging but also to understand\n"
364  "what's wrong in your controller. In OpenGL, the rays are drawn in cyan when\n"
365  "they are not obstructed and in purple when they are. In case a ray is\n"
366  "obstructed, a black dot is drawn where the intersection occurred.\n"
367  "To turn this functionality on, add the attribute 'show_rays=\"true\"' in the\n"
368  "XML as in this example:\n\n"
369  " <controllers>\n"
370  " ...\n"
371  " <my_controller ...>\n"
372  " ...\n"
373  " <sensors>\n"
374  " ...\n"
375  " <footbot_distance_scanner implementation=\"rot_z_only\"\n"
376  " show_rays=\"true\" />\n"
377  " ...\n"
378  " </sensors>\n"
379  " ...\n"
380  " </my_controller>\n"
381  " ...\n"
382  " </controllers>\n",
383  "Usable"
384  );
385 
386 }
#define THROW_ARGOSEXCEPTION_NESTED(message, nested)
This macro throws an ARGoS exception with the passed message and nesting the passed exception.
float Real
Collects all ARGoS code.
Definition: datatypes.h:39
#define CALCULATE_LONG_RANGE_RAY(ANGLE, INDEX)
#define ADD_READINGS(RAYS, MAP, MINDIST)
#define CALCULATE_SHORT_RANGE_RAY(ANGLE, INDEX)
The namespace containing all the ARGoS related code.
Definition: ci_actuator.h:12
bool GetClosestEmbodiedEntityIntersectedByRay(SEmbodiedEntityIntersectionItem &s_item, const CRay3 &c_ray)
Returns the closest intersection with an embodied entity to the ray start.
void GetNodeAttributeOrDefault(TConfigurationNode &t_node, const std::string &str_attribute, T &t_buffer, const T &t_default)
Returns the value of a node's attribute, or the passed default value.
REGISTER_SENSOR(CEPuckProximityDefaultSensor, "epuck_proximity", "default", "Danesh Tarapore [daneshtarapore@gmail.com]", "1.0", "The E-Puck proximity sensor.", "This sensor accesses the epuck proximity sensor. For a complete description\n" "of its usage, refer to the ci_epuck_proximity_sensor.h interface. For the XML\n" "configuration, refer to the default proximity sensor.\n", "Usable")
ticpp::Element TConfigurationNode
The ARGoS configuration XML node.
virtual void Enable()
Enables updating of sensor information in the event loop.
Definition: ci_sensor.h:78
virtual void Init(TConfigurationNode &t_node)
Initializes the sensor from the XML configuration tree.
Definition: ci_sensor.h:54
bool IsDisabled() const
Definition: ci_sensor.h:86
Basic class for an entity that contains other entities.
CEntity & GetComponent(const std::string &str_component)
Returns the component with the passed string label.
An entity that contains a pointer to the user-defined controller.
void AddIntersectionPoint(const CRay3 &c_ray, Real f_t_on_ray)
Adds an intersection point to the list.
void AddCheckedRay(bool b_obstructed, const CRay3 &c_ray)
Adds a ray to the list of checked rays.
This entity is a link to a body in the physics engine.
const SAnchor & GetOriginAnchor() const
Returns a const reference to the origin anchor associated to this entity.
void Enable()
Enables the entity.
Definition: entity.h:265
CQuaternion Orientation
The orientation of the anchor wrt the global coordinate system.
Definition: physics_model.h:53
The core class of ARGOS.
Definition: simulator.h:62
The exception that wraps all errors in ARGoS.
It defines the basic type CRadians, used to store an angle value in radians.
Definition: angles.h:42
static const CRadians PI
The PI constant.
Definition: angles.h:49
static const CRadians PI_OVER_TWO
Set to PI / 2.
Definition: angles.h:59
CRadians & SignedNormalize()
Normalizes the value in the range [-PI:PI].
Definition: angles.h:137
static const CRadians ZERO
Set to zero radians.
Definition: angles.h:79
void ToEulerAngles(CRadians &c_z_angle, CRadians &c_y_angle, CRadians &c_x_angle) const
Definition: quaternion.h:172
T GetSpan() const
Definition: range.h:64
static CRNG * CreateRNG(const std::string &str_category)
Creates a new RNG inside the given category.
Definition: rng.cpp:347
static const CVector3 Y
The y axis.
Definition: vector3.h:39
static const CVector3 X
The x axis.
Definition: vector3.h:36
TReadingsMap m_tLongReadingsMap
Map storing the last received packets from the long distance sensors.
TReadingsMap m_tReadingsMap
Map storing all the last received packets.
TReadingsMap m_tShortReadingsMap
Map storing the last received packets from the short distance sensors.
virtual void SetRobot(CComposableEntity &c_entity)
Sets the entity associated to this sensor.
virtual void Reset()
Resets the sensor to the state it had just after Init().
virtual void Update()
Updates the state of the entity associated to this sensor, if the sensor is currently enabled.
virtual void Init(TConfigurationNode &t_tree)
Initializes the sensor from the XML configuration tree.