ARGoS 3
A parallel, multi-engine simulator for swarm robotics
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
16namespace 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
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
339
340 /****************************************/
341 /****************************************/
342
343}
unsigned int UInt32
32-bit unsigned integer.
Definition datatypes.h:97
float Real
Collects all ARGoS code.
Definition datatypes.h:39
#define THROW_ARGOSEXCEPTION(message)
This macro throws an ARGoS exception with the passed message.
#define REGISTER_SPACE_OPERATION(ACTION, OPERATION, ENTITY)
Definition space.h:549
#define REGISTER_STANDARD_SPACE_OPERATION_REMOVE_ENTITY(ENTITY)
Definition space.h:558
#define REGISTER_ENTITY(CLASSNAME, LABEL, AUTHOR, VERSION, BRIEF_DESCRIPTION, LONG_DESCRIPTION, STATUS)
Definition entity.h:432
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.
void GetNodeAttribute(TConfigurationNode &t_node, const std::string &str_attribute, T &t_buffer)
Returns the value of a node's attribute.
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
const CVector3 & GetArenaCenter() const
Returns the arena center.
Definition space.h:389
const CVector3 & GetArenaSize() const
Returns the arena size.
Definition space.h:371
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
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
Real GetY() const
Returns the y coordinate of this vector.
Definition vector3.h:121