floor_entity.cpp
Go to the documentation of this file.
1 
7 #include "floor_entity.h"
8 #include <argos3/core/simulator/simulator.h>
9 #include <argos3/core/simulator/space/space.h>
10 #include <argos3/core/simulator/loop_functions.h>
11 
12 #ifdef ARGOS_WITH_FREEIMAGE
13 #include <FreeImagePlus.h>
14 #endif
15 
16 namespace argos {
17 
18  /****************************************/
19  /****************************************/
20 
21 #ifdef ARGOS_WITH_FREEIMAGE
22  class CFloorColorFromImageFile : public CFloorEntity::CFloorColorSource {
23 
24  public:
25 
26  CFloorColorFromImageFile(const std::string& str_path) {
27  const CVector3& cArenaSize = CSimulator::GetInstance().GetSpace().GetArenaSize();
28  m_cHalfArenaSize.Set(
29  cArenaSize.GetX() * 0.5f,
30  cArenaSize.GetY() * 0.5f);
31  const CVector3& cArenaCenter = CSimulator::GetInstance().GetSpace().GetArenaCenter();
32  m_cArenaCenter.Set(cArenaCenter.GetX(),
33  cArenaCenter.GetY());
34  LoadImage(str_path);
35  }
36 
37  virtual void Reset() {
38  LoadImage(m_strImageFileName);
39  }
40 
41  virtual CColor GetColorAtPoint(Real f_x,
42  Real f_y) {
43  /* Compute coordinates on the image */
44  UInt32 x = static_cast<UInt32>((f_x + m_cHalfArenaSize.GetX()) * m_fArenaToImageCoordinateXFactor);
45  UInt32 y = static_cast<UInt32>((f_y + m_cHalfArenaSize.GetY()) * m_fArenaToImageCoordinateYFactor);
46  /* Check the bit depth */
47  if(m_cImage.getBitsPerPixel() <= 8) {
48  RGBQUAD* ptColorPalette;
49  BYTE tPixelIndex;
50  /* 1, 4 or 8 bits per pixel */
51  if(! m_cImage.getPixelIndex(x, y, &tPixelIndex)) {
52  THROW_ARGOSEXCEPTION("Unable to access image pixel at (" << x << "," << y <<
53  "). Image size (" << m_cImage.getWidth() << "," <<
54  m_cImage.getHeight() << ")");
55  }
56  ptColorPalette = m_cImage.getPalette();
57  return CColor(ptColorPalette[tPixelIndex].rgbRed,
58  ptColorPalette[tPixelIndex].rgbGreen,
59  ptColorPalette[tPixelIndex].rgbBlue);
60  }
61  else {
62  /* 16, 24 or 32 bits per pixel */
63  RGBQUAD tColorPixel;
64  if(! m_cImage.getPixelColor(x, y, &tColorPixel)) {
65  THROW_ARGOSEXCEPTION("Unable to access image pixel at (" << x << "," << y <<
66  "). Image size (" << m_cImage.getWidth() << "," <<
67  m_cImage.getHeight() << ")");
68  }
69  return CColor(tColorPixel.rgbRed,
70  tColorPixel.rgbGreen,
71  tColorPixel.rgbBlue);
72  }
73  }
74 
75  virtual void SaveAsImage(const std::string& str_path) {
76  m_strImageFileName = str_path;
77  m_cImage.save(str_path.c_str());
78  }
79 
80  virtual const std::string& GetImageFileName() const {
81  return m_strImageFileName;
82  }
83 
84  protected:
85 
86  void LoadImage(const std::string& str_path) {
87  m_strImageFileName = str_path;
88  if(!m_cImage.load(m_strImageFileName.c_str())) {
89  THROW_ARGOSEXCEPTION("Could not load image \"" <<
90  m_strImageFileName <<
91  "\"");
92  }
93  const CVector3& cArenaSize = CSimulator::GetInstance().GetSpace().GetArenaSize();
94  m_fArenaToImageCoordinateXFactor = m_cImage.getWidth() / cArenaSize.GetX();
95  m_fArenaToImageCoordinateYFactor = m_cImage.getHeight() / cArenaSize.GetY();
96  }
97 
98  private:
99 
100  fipImage m_cImage;
101  Real m_fArenaToImageCoordinateXFactor;
102  Real m_fArenaToImageCoordinateYFactor;
103  CVector2 m_cHalfArenaSize;
104  CVector2 m_cArenaCenter;
105  std::string m_strImageFileName;
106 
107  };
108 #endif
109 
110  /****************************************/
111  /****************************************/
112 
114 
115  public:
116 
117  CFloorColorFromLoopFunctions(UInt32 un_pixels_per_meter) :
118  m_cLoopFunctions(CSimulator::GetInstance().GetLoopFunctions()),
119  m_unPixelsPerMeter(un_pixels_per_meter) {
120  const CVector3& cArenaSize = CSimulator::GetInstance().GetSpace().GetArenaSize();
121  m_cHalfArenaSize.Set(
122  cArenaSize.GetX() * 0.5f,
123  cArenaSize.GetY() * 0.5f);
124  const CVector3& cArenaCenter = CSimulator::GetInstance().GetSpace().GetArenaCenter();
125  m_cArenaCenter.Set(cArenaCenter.GetX(),
126  cArenaCenter.GetY());
127  }
128 
130  Real f_y) {
131  return m_cLoopFunctions.GetFloorColor(CVector2(f_x, f_y));
132  }
133 
134 #ifdef ARGOS_WITH_FREEIMAGE
135  virtual void SaveAsImage(const std::string& str_path) {
136  fipImage cImage(FIT_BITMAP,
137  static_cast<UInt32>(m_unPixelsPerMeter * m_cHalfArenaSize.GetX()*2),
138  static_cast<UInt32>(m_unPixelsPerMeter * m_cHalfArenaSize.GetY()*2), 24);
139  Real fFactor = 1.0f / static_cast<Real>(m_unPixelsPerMeter);
140  CVector2 cFloorPos;
141  CColor cARGoSPixel;
142  RGBQUAD tFIPPixel;
143  for(UInt32 y = 0; y < cImage.getHeight(); ++y) {
144  for(UInt32 x = 0; x < cImage.getWidth(); ++x) {
145  cFloorPos.Set(x * fFactor, y * fFactor);
146  cFloorPos -= m_cHalfArenaSize;
147  cFloorPos += m_cArenaCenter;
148  cARGoSPixel = m_cLoopFunctions.GetFloorColor(cFloorPos);
149  tFIPPixel.rgbRed = cARGoSPixel.GetRed();
150  tFIPPixel.rgbGreen = cARGoSPixel.GetGreen();
151  tFIPPixel.rgbBlue = cARGoSPixel.GetBlue();
152  cImage.setPixelColor(x, y, &tFIPPixel);
153  }
154  }
155  if(!cImage.save(str_path.c_str())) {
156  THROW_ARGOSEXCEPTION("Cannot save image \"" << str_path << "\" for floor entity.");
157  }
158  }
159 #endif
160 
161  private:
162 
163  CLoopFunctions& m_cLoopFunctions;
164  UInt32 m_unPixelsPerMeter;
165  CVector2 m_cHalfArenaSize;
166  CVector2 m_cArenaCenter;
167  };
168 
169  /****************************************/
170  /****************************************/
171 
173  CEntity(nullptr),
174  m_eColorSource(UNSET),
175  m_pcColorSource(nullptr),
176  m_bHasChanged(true) {}
177 
178  /****************************************/
179  /****************************************/
180 
181 #ifdef ARGOS_WITH_FREEIMAGE
182  CFloorEntity::CFloorEntity(const std::string& str_id,
183  const std::string& str_file_name) :
184  CEntity(nullptr, str_id),
185  m_eColorSource(FROM_IMAGE),
186  m_pcColorSource(nullptr),
187  m_bHasChanged(true) {
188  std::string strFileName = str_file_name;
189  ExpandEnvVariables(strFileName);
190  m_pcColorSource = new CFloorColorFromImageFile(strFileName);
191  }
192 #endif
193 
194  /****************************************/
195  /****************************************/
196 
197  CFloorEntity::CFloorEntity(const std::string& str_id,
198  UInt32 un_pixels_per_meter) :
199  CEntity(nullptr, str_id),
200  m_eColorSource(FROM_LOOP_FUNCTIONS),
201  m_pcColorSource(new CFloorColorFromLoopFunctions(un_pixels_per_meter)),
202  m_bHasChanged(true) {}
203 
204  /****************************************/
205  /****************************************/
206 
208  if(m_pcColorSource != nullptr) {
209  delete m_pcColorSource;
210  }
211  }
212 
213  /****************************************/
214  /****************************************/
215 
217  /* Init parent */
218  CEntity::Init(t_tree);
219  /* Parse XML */
220  std::string strColorSource;
221  GetNodeAttribute(t_tree, "source", strColorSource);
222  if(strColorSource == "loop_functions") {
223  m_eColorSource = FROM_LOOP_FUNCTIONS;
224  UInt32 unPixelsPerMeter;
225  GetNodeAttribute(t_tree, "pixels_per_meter", unPixelsPerMeter);
226  m_pcColorSource = new CFloorColorFromLoopFunctions(unPixelsPerMeter);
227  }
228  else if(strColorSource == "image") {
229 #ifdef ARGOS_WITH_FREEIMAGE
230  m_eColorSource = FROM_IMAGE;
231  std::string strPath;
232  GetNodeAttribute(t_tree, "path", strPath);
233  ExpandEnvVariables(strPath);
234  m_pcColorSource = new CFloorColorFromImageFile(strPath);
235 #else
236  THROW_ARGOSEXCEPTION("ARGoS was compiled without FreeImage, this image source is unsupported for the floor entity \"" <<
237  GetId() <<
238  "\"");
239 #endif
240  }
241  else {
242  THROW_ARGOSEXCEPTION("Unknown image source \"" <<
243  strColorSource <<
244  "\" for the floor entity \"" <<
245  GetId() <<
246  "\"");
247  }
248  }
249 
250  /****************************************/
251  /****************************************/
252 
254  m_pcColorSource->Reset();
255  }
256 
257  /****************************************/
258  /****************************************/
259 
260 #ifdef ARGOS_WITH_FREEIMAGE
261  void CFloorEntity::SaveAsImage(const std::string& str_path) {
262  m_pcColorSource->SaveAsImage(str_path);
263  }
264 #endif
265 
266  /****************************************/
267  /****************************************/
268 
270  "floor",
271  "Carlo Pinciroli [ilpincy@gmail.com]",
272  "1.0",
273  "It contains the properties of the arena floor.",
274  "The floor entity contains the properties of the arena floor. In the current\n"
275  "implementation, it contains only the color of the floor. The floor color is\n"
276  "detected by the robots' ground sensors.\n\n"
277  "REQUIRED XML CONFIGURATION\n\n"
278  " <arena ...>\n"
279  " ...\n"
280  " <floor id=\"floor\"\n"
281  " source=\"SOURCE\" />\n"
282  " ...\n"
283  " </arena>\n\n"
284  "The 'id' attribute is necessary and must be unique among the entities. If two\n"
285  "entities share the same id, initialization aborts.\n"
286  "The 'source' attribute specifies where to get the color of the floor from. Its\n"
287  "value, here denoted as SOURCE, can assume the following values:\n\n"
288  " image The color is calculated from the passed image file\n"
289  " loop_functions The color is calculated calling the loop functions\n\n"
290  "When 'source' is set to 'image', as showed in the following example, you have\n"
291  "to specify the image path in the additional attribute 'path':\n\n"
292  " <arena ...>\n"
293  " ...\n"
294  " <floor id=\"floor\"\n"
295  " source=\"image\"\n"
296  " path=\"/path/to/imagefile.ext\" />\n"
297  " ...\n"
298  " </arena>\n\n"
299  "Many image formats are available, such as PNG, JPG, BMP, GIF and many more.\n"
300  "Refer to the FreeImage webpage for a complete list of supported image formats\n"
301  "(http://freeimage.sourceforge.net/features.html).\n\n"
302  "When 'source' is set to 'loop_functions', as showed in the following example,\n"
303  "an image is implicitly created to be used as texture for graphical\n"
304  "visualizations. The algorithm that creates the texture needs to convert from\n"
305  "meters (in the arena) to pixels (of the texture). You control how many pixels\n"
306  "per meter are used with the attribute 'pixels_per_meter'. Clearly, the higher\n"
307  "value, the higher the quality, but also the slower the algorithm and the bigger\n"
308  "the texture. The algorithm is called only once at init time, so the fact that\n"
309  "it is slow is not so important. However, the image size is limited by OpenGL.\n"
310  "Every implementation has its own limit, and you should check yours if any\n"
311  "texture-related problem arises. Now for the example:\n\n"
312  " <arena ...>\n"
313  " ...\n"
314  " <floor id=\"floor\"\n"
315  " source=\"loop_functions\"\n"
316  " pixels_per_meter=\"100\" />\n"
317  " ...\n"
318  " </arena>\n\n"
319  "OPTIONAL XML CONFIGURATION\n\n"
320  "None for the time being.\n",
321  "Usable"
322  );
323 
324  /****************************************/
325  /****************************************/
326 
328  public:
329  void ApplyTo(CSpace& c_space, CFloorEntity& c_entity) {
330  c_space.AddEntity(c_entity);
331  c_space.SetFloorEntity(c_entity);
332  }
333  };
334 
337  CFloorEntity);
339 
340  /****************************************/
341  /****************************************/
342 
343 }
#define THROW_ARGOSEXCEPTION(message)
This macro throws an ARGoS exception with the passed message.
unsigned int UInt32
32-bit unsigned integer.
Definition: datatypes.h:97
float Real
Collects all ARGoS code.
Definition: datatypes.h:39
The namespace containing all the ARGoS related code.
Definition: ci_actuator.h:12
std::string & ExpandEnvVariables(std::string &str_buffer)
Searches into str_buffer for occurrences of an environment variable of the form $VAR and substitutes ...
ticpp::Element TConfigurationNode
The ARGoS configuration XML node.
REGISTER_SPACE_OPERATION(CSpaceOperationAddEntity, CSpaceOperationAddCFloorEntity, CFloorEntity)
REGISTER_STANDARD_SPACE_OPERATION_REMOVE_ENTITY(CFloorEntity)
void GetNodeAttribute(TConfigurationNode &t_node, const std::string &str_attribute, T &t_buffer)
Returns the value of a node's attribute.
REGISTER_ENTITY(CFloorEntity, "floor", "Carlo Pinciroli [ilpincy@gmail.com]", "1.0", "It contains the properties of the arena floor.", "The floor entity contains the properties of the arena floor. In the current\n" "implementation, it contains only the color of the floor. The floor color is\n" "detected by the robots' ground sensors.\n\n" "REQUIRED XML CONFIGURATION\n\n" " <arena ...>\n" " ...\n" " <floor id=\"floor\"\n" " source=\"SOURCE\" />\n" " ...\n" " </arena>\n\n" "The 'id' attribute is necessary and must be unique among the entities. If two\n" "entities share the same id, initialization aborts.\n" "The 'source' attribute specifies where to get the color of the floor from. Its\n" "value, here denoted as SOURCE, can assume the following values:\n\n" " image The color is calculated from the passed image file\n" " loop_functions The color is calculated calling the loop functions\n\n" "When 'source' is set to 'image', as showed in the following example, you have\n" "to specify the image path in the additional attribute 'path':\n\n" " <arena ...>\n" " ...\n" " <floor id=\"floor\"\n" " source=\"image\"\n" " path=\"/path/to/imagefile.ext\" />\n" " ...\n" " </arena>\n\n" "Many image formats are available, such as PNG, JPG, BMP, GIF and many more.\n" "Refer to the FreeImage webpage for a complete list of supported image formats\n" "(http://freeimage.sourceforge.net/features.html).\n\n" "When 'source' is set to 'loop_functions', as showed in the following example,\n" "an image is implicitly created to be used as texture for graphical\n" "visualizations. The algorithm that creates the texture needs to convert from\n" "meters (in the arena) to pixels (of the texture). You control how many pixels\n" "per meter are used with the attribute 'pixels_per_meter'. Clearly, the higher\n" "value, the higher the quality, but also the slower the algorithm and the bigger\n" "the texture. The algorithm is called only once at init time, so the fact that\n" "it is slow is not so important. However, the image size is limited by OpenGL.\n" "Every implementation has its own limit, and you should check yours if any\n" "texture-related problem arises. Now for the example:\n\n" " <arena ...>\n" " ...\n" " <floor id=\"floor\"\n" " source=\"loop_functions\"\n" " pixels_per_meter=\"100\" />\n" " ...\n" " </arena>\n\n" "OPTIONAL XML CONFIGURATION\n\n" "None for the time being.\n", "Usable")
The basic entity type.
Definition: entity.h:90
const std::string & GetId() const
Returns the id of this entity.
Definition: entity.h:157
virtual void Init(TConfigurationNode &t_tree)
Initializes the state of the entity from the XML configuration tree.
Definition: entity.cpp:40
CFloorColorFromLoopFunctions(UInt32 un_pixels_per_meter)
virtual CColor GetColorAtPoint(Real f_x, Real f_y)
void ApplyTo(CSpace &c_space, CFloorEntity &c_entity)
virtual void Reset()
Restores the initial state of the floor.
CFloorEntity()
Class constructor.
virtual void Init(TConfigurationNode &t_tree)
Initializes the entity from an XML tree.
virtual ~CFloorEntity()
Class destructor.
virtual CColor GetFloorColor(const CVector2 &c_pos_on_floor)
Returns the color of the floor in the specified point.
The core class of ARGOS.
Definition: simulator.h:62
CSpace & GetSpace() const
Returns a reference to the simulated space.
Definition: simulator.h:104
static CSimulator & GetInstance()
Returns the instance to the CSimulator class.
Definition: simulator.cpp:78
void SetFloorEntity(CFloorEntity &c_floor_entity)
Sets the floor entity.
Definition: space.h:248
void AddEntity(ENTITY &c_entity)
Adds an entity of the given type.
Definition: space.h:274
const CVector3 & GetArenaSize() const
Returns the arena size.
Definition: space.h:371
const CVector3 & GetArenaCenter() const
Returns the arena center.
Definition: space.h:389
The basic color type.
Definition: color.h:25
UInt8 GetBlue() const
Returns the blue channel of the color.
Definition: color.h:101
UInt8 GetGreen() const
Returns the green channel of the color.
Definition: color.h:90
UInt8 GetRed() const
Returns the red channel of the color.
Definition: color.h:79
A 2D vector class.
Definition: vector2.h:27
Real GetY() const
Returns the y coordinate of this vector.
Definition: vector2.h:110
void Set(Real f_x, Real f_y)
Sets the vector contents from Cartesian coordinates.
Definition: vector2.h:127
Real GetX() const
Returns the x coordinate of this vector.
Definition: vector2.h:94
A 3D vector class.
Definition: vector3.h:31
Real GetX() const
Returns the x coordinate of this vector.
Definition: vector3.h:105
void Set(const Real f_x, const Real f_y, const Real f_z)
Sets the vector contents from Cartesian coordinates.
Definition: vector3.h:155
Real GetY() const
Returns the y coordinate of this vector.
Definition: vector3.h:121