ARGoS 3
A parallel, multi-engine simulator for swarm robotics
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
13namespace 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 CALCULATE_LONG_RANGE_RAY(ANGLE, INDEX)
#define ADD_READINGS(RAYS, MAP, MINDIST)
#define CALCULATE_SHORT_RANGE_RAY(ANGLE, INDEX)
float Real
Collects all ARGoS code.
Definition datatypes.h:39
#define THROW_ARGOSEXCEPTION_NESTED(message, nested)
This macro throws an ARGoS exception with the passed message and nesting the passed exception.
#define REGISTER_SENSOR(CLASSNAME, LABEL, IMPLEMENTATION, AUTHOR, VERSION, BRIEF_DESCRIPTION, LONG_DESCRIPTION, STATUS)
Registers a new sensor model inside ARGoS.
Definition sensor.h:63
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.
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.
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.