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 
12 namespace 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 */
37  CCI_CameraSensor::Init(t_tree);
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;
91  TConfigurationNodeIterator itAlgorithm;
92  for(itAlgorithm = itAlgorithm.begin(&(*itCamera));
93  itAlgorithm != itAlgorithm.end();
94  ++itAlgorithm) {
95  /* create the algorithm */
96  CCameraSensorSimulatedAlgorithm* pcAlgorithm =
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.
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.
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.
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.
Definition: physics_model.h:38
The exception that wraps all errors in ARGoS.
CSquareMatrix< DIM > GetInverse() const
Definition: squarematrix.h:120
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
CVector3 & CrossProduct(const CVector3 &c_vector3)
Calculates the cross product between this vector and the passed one.
Definition: vector3.h:382
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
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
Definition: factory_impl.h:48
SInterface::TVector m_vecInterfaces
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