ARGoS 3
A parallel, multi-engine simulator for swarm robotics
camera_default_sensor.cpp
Go to the documentation of this file.
1
8#include <argos3/core/simulator/simulator.h>
9#include <argos3/core/simulator/entity/composable_entity.h>
10#include <argos3/plugins/robots/generic/simulator/camera_sensor_algorithm.h>
11
12namespace argos {
13
14 /****************************************/
15 /****************************************/
16
18 m_bShowFrustum(false),
19 m_pcEmbodiedEntity(nullptr),
20 m_pcControllableEntity(nullptr) {}
21
22 /****************************************/
23 /****************************************/
24
26 /* Get the embodied and controllable entities */
27 m_pcEmbodiedEntity = &(c_entity.GetComponent<CEmbodiedEntity>("body"));
28 m_pcControllableEntity = &(c_entity.GetComponent<CControllableEntity>("controller"));
29 }
30
31 /****************************************/
32 /****************************************/
33
35 try {
36 /* Parent class init */
38 /* Show the frustums */
40 /* For each camera */
41 TConfigurationNodeIterator itCamera("camera");
42 for(itCamera = itCamera.begin(&t_tree);
43 itCamera != itCamera.end();
44 ++itCamera) {
45 /* Get camera indentifier */
46 std::string strId;
47 GetNodeAttribute(*itCamera, "id", strId);
48 /* Parse and look up the anchor */
49 std::string strAnchorId;
50 GetNodeAttribute(*itCamera, "anchor", strAnchorId);
51 SAnchor& sAnchor = m_pcEmbodiedEntity->GetAnchor(strAnchorId);
52 /* parse the offset */
53 CVector3 cOffsetPosition;
54 CQuaternion cOffsetOrientation;
55 GetNodeAttribute(*itCamera, "position", cOffsetPosition);
56 GetNodeAttribute(*itCamera, "orientation", cOffsetOrientation);
57 CTransformationMatrix3 cOffset(cOffsetOrientation, cOffsetPosition);
58 /* parse the range */
59 CRange<Real> cRange;
60 GetNodeAttribute(*itCamera, "range", cRange);
61 /* create the projection matrix */
62 CSquareMatrix<3> cProjectionMatrix;
63 cProjectionMatrix.SetIdentityMatrix();
64 /* set the focal length */
65 CVector2 cFocalLength;
66 GetNodeAttribute(*itCamera, "focal_length", cFocalLength);
67 cProjectionMatrix(0,0) = cFocalLength.GetX(); // Fx
68 cProjectionMatrix(1,1) = cFocalLength.GetY(); // Fy
69 /* set the principal point */
70 CVector2 cPrincipalPoint;
71 GetNodeAttribute(*itCamera, "principal_point", cPrincipalPoint);
72 cProjectionMatrix(0,2) = cPrincipalPoint.GetX(); // Px
73 cProjectionMatrix(1,2) = cPrincipalPoint.GetY(); // Py
74 /* set the distortion parameters */
75 /*
76 CMatrix<1,5> cDistortionParameters;
77 std::string strDistortionParameters;
78 Real pfDistortionParameters[3];
79 GetNodeAttribute(*itCamera, "distortion_parameters", strDistortionParameters);
80 ParseValues<Real>(strDistortionParameters, 3, pfDistortionParameters, ',');
81 cDistortionParameters(0,0) = pfDistortionParameters[0]; // K1
82 cDistortionParameters(0,1) = pfDistortionParameters[1]; // K2
83 cDistortionParameters(0,4) = pfDistortionParameters[2]; // K3
84 */
85 /* parse the resolution */
86 CVector2 cResolution;
87 GetNodeAttribute(*itCamera, "resolution", cResolution);
88 /* create and initialise the algorithms */
89 std::vector<CCameraSensorSimulatedAlgorithm*> vecSimulatedAlgorithms;
90 std::vector<CCI_CameraSensorAlgorithm*> vecAlgorithms;
92 for(itAlgorithm = itAlgorithm.begin(&(*itCamera));
93 itAlgorithm != itAlgorithm.end();
94 ++itAlgorithm) {
95 /* create the algorithm */
98 /* check that algorithm inherits from a control interface */
99 auto* pcCIAlgorithm =
100 dynamic_cast<CCI_CameraSensorAlgorithm*>(pcAlgorithm);
101 if(pcCIAlgorithm == nullptr) {
102 THROW_ARGOSEXCEPTION("Algorithm \"" << itAlgorithm->Value() <<
103 "\" does not inherit from CCI_CameraSensorAlgorithm");
104 }
105 /* initialize the algorithm's control interface */
106 pcCIAlgorithm->Init(*itAlgorithm);
107 /* store pointers to the algorithms */
108 vecSimulatedAlgorithms.push_back(pcAlgorithm);
109 vecAlgorithms.push_back(pcCIAlgorithm);
110 }
111 /* create the simulated sensor */
112 m_vecSensors.emplace_back(sAnchor, cOffset, cRange, cProjectionMatrix,
113 cResolution, vecSimulatedAlgorithms);
114 /* create the sensor's control interface */
115 m_vecInterfaces.emplace_back(strId, vecAlgorithms);
116 }
117 }
118 catch(CARGoSException& ex) {
119 THROW_ARGOSEXCEPTION_NESTED("Error initializing camera sensor", ex);
120 }
121 /* sensor is disabled by default */
122 Disable();
123 }
124
125 /****************************************/
126 /****************************************/
127
129 /* sensor is disabled--nothing to do */
130 if (IsDisabled()) {
131 return;
132 }
133 /* vector of controller rays */
134 std::vector<std::pair<bool, CRay3> >& vecCheckedRays =
136 /* sensor parameters */
137 CTransformationMatrix3 cWorldToAnchorTransform;
138 CTransformationMatrix3 cWorldToCameraTransform;
139 CTransformationMatrix3 cCameraToWorldTransform;
140 CVector3 cCameraLocation, cLookAt, cUp;
141 CVector3 cX, cY, cZ;
142 CVector3 cNearCenter, cNearTopLeft, cNearTopRight, cNearBottomLeft, cNearBottomRight;
143 CVector3 cFarCenter, cFarTopLeft, cFarTopRight, cFarBottomLeft, cFarBottomRight;
144 std::array<CPlane, 6> arrFrustumPlanes;
145 CVector3 cBoundingBoxMinCorner, cBoundingBoxMaxCorner;
146 CVector3 cBoundingBoxPosition, cBoundingBoxHalfExtents;
147 /* for each camera sensor */
148 for(SSensor& s_sensor : m_vecSensors) {
149 /* calculate transform matrices */
150 cWorldToAnchorTransform.SetFromComponents(s_sensor.Anchor.Orientation, s_sensor.Anchor.Position);
151 cWorldToCameraTransform = cWorldToAnchorTransform * s_sensor.Offset;
152 cCameraToWorldTransform = cWorldToCameraTransform.GetInverse();
153 /* calculate camera direction vectors */
154 cCameraLocation = cWorldToCameraTransform.GetTranslationVector();
155 cLookAt = cWorldToCameraTransform * CVector3::Z;
156 cUp = CVector3(0,-1,0); // -Y
157 cUp.Rotate(cWorldToCameraTransform.GetRotationMatrix());
158 /* calculate direction vectors */
159 cZ = cCameraLocation - cLookAt;
160 cZ.Normalize();
161 cX = cUp;
162 cX.CrossProduct(cZ);
163 cX.Normalize();
164 cY = cZ;
165 cY.CrossProduct(cX);
166 /* calculate frustum coordinates */
167 cNearCenter = cCameraLocation - cZ * s_sensor.Range.GetMin();
168 cFarCenter = cCameraLocation - cZ * s_sensor.Range.GetMax();
169 cNearTopLeft = cNearCenter + (cY * s_sensor.NearPlaneHeight) - (cX * s_sensor.NearPlaneWidth);
170 cNearTopRight = cNearCenter + (cY * s_sensor.NearPlaneHeight) + (cX * s_sensor.NearPlaneWidth);
171 cNearBottomLeft = cNearCenter - (cY * s_sensor.NearPlaneHeight) - (cX * s_sensor.NearPlaneWidth);
172 cNearBottomRight = cNearCenter - (cY * s_sensor.NearPlaneHeight) + (cX * s_sensor.NearPlaneWidth);
173 cFarTopLeft = cFarCenter + (cY * s_sensor.FarPlaneHeight) - (cX * s_sensor.FarPlaneWidth);
174 cFarTopRight = cFarCenter + (cY * s_sensor.FarPlaneHeight) + (cX * s_sensor.FarPlaneWidth);
175 cFarBottomLeft = cFarCenter - (cY * s_sensor.FarPlaneHeight) - (cX * s_sensor.FarPlaneWidth);
176 cFarBottomRight = cFarCenter - (cY * s_sensor.FarPlaneHeight) + (cX * s_sensor.FarPlaneWidth);
177 /* show frustum if enabled by adding outline to the checked rays vector */
178 if(m_bShowFrustum) {
179 vecCheckedRays.emplace_back(false, CRay3(cNearTopLeft, cNearTopRight));
180 vecCheckedRays.emplace_back(false, CRay3(cNearTopRight, cNearBottomRight));
181 vecCheckedRays.emplace_back(false, CRay3(cNearBottomRight, cNearBottomLeft));
182 vecCheckedRays.emplace_back(false, CRay3(cNearBottomLeft, cNearTopLeft));
183 vecCheckedRays.emplace_back(false, CRay3(cFarTopLeft, cFarTopRight));
184 vecCheckedRays.emplace_back(false, CRay3(cFarTopRight, cFarBottomRight));
185 vecCheckedRays.emplace_back(false, CRay3(cFarBottomRight, cFarBottomLeft));
186 vecCheckedRays.emplace_back(false, CRay3(cFarBottomLeft, cFarTopLeft));
187 vecCheckedRays.emplace_back(false, CRay3(cNearTopLeft, cFarTopLeft));
188 vecCheckedRays.emplace_back(false, CRay3(cNearTopRight, cFarTopRight));
189 vecCheckedRays.emplace_back(false, CRay3(cNearBottomRight, cFarBottomRight));
190 vecCheckedRays.emplace_back(false, CRay3(cNearBottomLeft, cFarBottomLeft));
191 }
192 //std::cerr << cFarBottomRight.GetZ() << "\t" << cFarBottomLeft.GetZ() << std::endl; TODO
193 /* generate a bounding box for the frustum */
194 cBoundingBoxMinCorner = cNearCenter;
195 cBoundingBoxMaxCorner = cNearCenter;
196 for(const CVector3& c_point : {
197 cNearTopLeft, cNearTopRight, cNearBottomLeft, cNearBottomRight,
198 cFarTopLeft, cFarTopRight, cFarBottomLeft, cFarBottomRight
199 }) {
200 if(c_point.GetX() > cBoundingBoxMaxCorner.GetX()) {
201 cBoundingBoxMaxCorner.SetX(c_point.GetX());
202 }
203 if(c_point.GetX() < cBoundingBoxMinCorner.GetX()) {
204 cBoundingBoxMinCorner.SetX(c_point.GetX());
205 }
206 if(c_point.GetY() > cBoundingBoxMaxCorner.GetY()) {
207 cBoundingBoxMaxCorner.SetY(c_point.GetY());
208 }
209 if(c_point.GetY() < cBoundingBoxMinCorner.GetY()) {
210 cBoundingBoxMinCorner.SetY(c_point.GetY());
211 }
212 if(c_point.GetZ() > cBoundingBoxMaxCorner.GetZ()) {
213 cBoundingBoxMaxCorner.SetZ(c_point.GetZ());
214 }
215 if(c_point.GetZ() < cBoundingBoxMinCorner.GetZ()) {
216 cBoundingBoxMinCorner.SetZ(c_point.GetZ());
217 }
218 }
219 cBoundingBoxMaxCorner *= 0.5;
220 cBoundingBoxMinCorner *= 0.5;
221 cBoundingBoxPosition = (cBoundingBoxMaxCorner + cBoundingBoxMinCorner);
222 cBoundingBoxHalfExtents = (cBoundingBoxMaxCorner - cBoundingBoxMinCorner);
223 /* generate frustum planes */
224 arrFrustumPlanes[0].SetFromThreePoints(cNearTopRight, cNearTopLeft, cFarTopLeft);
225 arrFrustumPlanes[1].SetFromThreePoints(cNearBottomLeft, cNearBottomRight, cFarBottomRight);
226 arrFrustumPlanes[2].SetFromThreePoints(cNearTopLeft, cNearBottomLeft, cFarBottomLeft);
227 arrFrustumPlanes[3].SetFromThreePoints(cNearBottomRight, cNearTopRight, cFarBottomRight);
228 arrFrustumPlanes[4].SetFromThreePoints(cNearTopLeft, cNearTopRight, cNearBottomRight);
229 arrFrustumPlanes[5].SetFromThreePoints(cFarTopRight, cFarTopLeft, cFarBottomLeft);
230 /* execute each algorithm */
231 for(CCameraSensorSimulatedAlgorithm* pc_algorithm : s_sensor.Algorithms) {
232 pc_algorithm->Update(s_sensor.ProjectionMatrix,
233 arrFrustumPlanes,
234 cCameraToWorldTransform,
235 cCameraLocation,
236 cBoundingBoxPosition,
237 cBoundingBoxHalfExtents);
238 /* transfer any rays to the controllable entity for rendering */
239 vecCheckedRays.insert(std::end(vecCheckedRays),
240 std::begin(pc_algorithm->GetCheckedRays()),
241 std::end(pc_algorithm->GetCheckedRays()));
242 }
243 }
244 }
245
246 /****************************************/
247 /****************************************/
248
250 "cameras", "default",
251 "Michael Allwright [allsey87@gmail.com]",
252 "1.0",
253
254 "A generic multi-camera sensor capable of running various algorithms",
255 "The generic multi-camera sensor can be attached to any composable entity in\n"
256 "ARGoS that contains an embodied entity with at least one anchor. The sensor\n"
257 "can be initialized with a number of cameras each running different algorithms\n"
258 "for detecting different objects in the simulation. The sensor is designed so\n"
259 "that algorithms can project a feature in the simulation on to the virtual\n"
260 "sensor and store its 2D pixel coordinates as a reading. The implementation\n"
261 "of algorithms that behave differently, however, is also possible.\n\n"
262
263 "This sensor is disabled by default, and must be enabled before it can be\n"
264 "used.\n\n"
265
266 "REQUIRED XML CONFIGURATION\n\n"
267 " <controllers>\n"
268 " ...\n"
269 " <my_controller ...>\n"
270 " ...\n"
271 " <sensors>\n"
272 " ...\n"
273 " <cameras implementation=\"default\"/>\n"
274 " ...\n"
275 " </sensors>\n"
276 " ...\n"
277 " </my_controller>\n"
278 " ...\n"
279 " </controllers>\n\n"
280
281 "OPTIONAL XML CONFIGURATION\n\n"
282
283 "It is possible to draw the frustum of each camera sensor in the OpenGL\n"
284 "visualization. This can be useful for sensor debugging but also to understand\n"
285 "what's wrong in your controller. To turn this functionality on, add the\n"
286 "attribute \"show_frustum\" as follows:\n\n"
287
288 " <controllers>\n"
289 " ...\n"
290 " <my_controller ...>\n"
291 " ...\n"
292 " <sensors>\n"
293 " ...\n"
294 " <cameras implementation=\"default\" show_frustum=\"true\"/>\n"
295 " ...\n"
296 " </sensors>\n"
297 " ...\n"
298 " </my_controller>\n"
299 " ...\n"
300 " </controllers>\n\n"
301
302 "To add a camera to the plugin, create a camera node as shown in the following\n"
303 "example. A camera is defined by its range (how close and how far the camera\n"
304 "can see), its anchor and its position and orientation offsets from that\n"
305 "that anchor, its focal length and principal point (which define the\n"
306 "projection matrix), and its resolution.\n\n"
307
308 " <controllers>\n"
309 " ...\n"
310 " <my_controller ...>\n"
311 " ...\n"
312 " <sensors>\n"
313 " ...\n"
314 " <cameras implementation=\"default\" show_frustum=\"true\">\n"
315 " <camera id=\"camera0\" range=\"0.025:0.25\" anchor=\"origin\"\n"
316 " position=\"0.1,0,0.1\" orientation=\"90,-90,0\"\n"
317 " focal_length=\"800,800\" principal_point=\"320,240\"\n"
318 " resolution=\"640,480\"/>\n"
319 " </cameras>\n"
320 " ...\n"
321 " </sensors>\n"
322 " ...\n"
323 " </my_controller>\n"
324 " ...\n"
325 " </controllers>\n\n"
326
327 "To run an algorithm on the camera sensor, simply add the algorithm as a node\n"
328 "under the camera node. At the time of writing, three algorithms are available\n"
329 "by default: led_detector, directional_led_detector, and tag_detector. Each of\n"
330 "algorithms requires a medium attribute that specifies the medium where the\n"
331 "target entities are indexed. By setting the show_rays attribute to true, you\n"
332 "can see whether or not a target was partially occluded by another object in\n"
333 "the simulation. For example:\n\n"
334
335 " <controllers>\n"
336 " ...\n"
337 " <my_controller ...>\n"
338 " ...\n"
339 " <sensors>\n"
340 " ...\n"
341 " <cameras implementation=\"default\" show_frustum=\"true\">\n"
342 " <camera id=\"camera0\" range=\"0.025:0.25\" anchor=\"origin\"\n"
343 " position=\"0.1,0,0.1\" orientation=\"90,-90,0\"\n"
344 " focal_length=\"800,800\" principal_point=\"320,240\"\n"
345 " resolution=\"640,480\">\n"
346 " <led_detector medium=\"leds\" show_rays=\"true\"/>\n"
347 " </camera>\n"
348 " </cameras>\n"
349 " ...\n"
350 " </sensors>\n"
351 " ...\n"
352 " </my_controller>\n"
353 " ...\n"
354 " </controllers>\n",
355
356 "Usable");
357}
#define THROW_ARGOSEXCEPTION_NESTED(message, nested)
This macro throws an ARGoS exception with the passed message and nesting the passed exception.
#define THROW_ARGOSEXCEPTION(message)
This macro throws an ARGoS exception with the passed message.
#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
ticpp::Iterator< ticpp::Element > TConfigurationNodeIterator
The iterator for the ARGoS configuration XML node.
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.
void GetNodeAttribute(TConfigurationNode &t_node, const std::string &str_attribute, T &t_buffer)
Returns the value of a node's attribute.
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
virtual void Disable()
Disables updating of sensor information in the event loop.
Definition ci_sensor.h:83
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.
std::vector< std::pair< bool, CRay3 > > & GetCheckedRays()
Returns the list of checked rays.
This entity is a link to a body in the physics engine.
const SAnchor & GetAnchor(const std::string &str_id) const
Returns the wanted anchor as a const reference.
An anchor related to the body of an entity.
The exception that wraps all errors in ARGoS.
CSquareMatrix< DIM > GetInverse() const
CRotationMatrix3 GetRotationMatrix() const
void SetFromComponents(const CRotationMatrix3 &c_rotation, const CVector3 &c_translation)
A 2D vector class.
Definition vector2.h:27
Real GetY() const
Returns the y coordinate of this vector.
Definition vector2.h:110
Real GetX() const
Returns the x coordinate of this vector.
Definition vector2.h:94
A 3D vector class.
Definition vector3.h:31
void SetY(const Real f_y)
Sets the y coordinate of this vector.
Definition vector3.h:129
CVector3 & Rotate(const CQuaternion &c_quaternion)
Rotates this vector by the given quaternion.
Definition vector3.cpp:23
Real GetX() const
Returns the x coordinate of this vector.
Definition vector3.h:105
CVector3 & CrossProduct(const CVector3 &c_vector3)
Calculates the cross product between this vector and the passed one.
Definition vector3.h:382
void SetX(const Real f_x)
Sets the x coordinate of this vector.
Definition vector3.h:113
CVector3 & Normalize()
Normalizes this vector.
Definition vector3.h:237
void SetZ(const Real f_z)
Sets the z coordinate of this vector.
Definition vector3.h:145
Real GetY() const
Returns the y coordinate of this vector.
Definition vector3.h:121
static const CVector3 Z
The z axis.
Definition vector3.h:42
Real GetZ() const
Returns the z coordinate of this vector.
Definition vector3.h:137
static TYPE * New(const std::string &str_label)
Creates a new object of type TYPE
SInterface::TVector m_vecInterfaces
virtual void Init(TConfigurationNode &t_node)
Initializes the resource.
virtual void Init(TConfigurationNode &t_tree)
Initializes the sensor from the XML configuration tree.
virtual void SetRobot(CComposableEntity &c_entity)
Sets the entity associated to this sensor.
virtual void Update()
Updates the state of the entity associated to this sensor, if the sensor is currently enabled.
CControllableEntity * m_pcControllableEntity
std::vector< SSensor > m_vecSensors
const std::vector< std::pair< bool, CRay3 > > & GetCheckedRays() const
virtual void Update(const CSquareMatrix< 3 > &c_projection_matrix, const std::array< CPlane, 6 > &arr_frustum_planes, const CTransformationMatrix3 &c_world_to_camera_transform, const CVector3 &c_camera_location, const CVector3 &c_bounding_box_position, const CVector3 &c_bounding_box_half_extents)=0