ARGoS 3
A parallel, multi-engine simulator for swarm robotics
rab_medium.cpp
Go to the documentation of this file.
1#include "rab_medium.h"
2#include <argos3/core/simulator/entity/embodied_entity.h>
3#include <argos3/core/simulator/simulator.h>
4#include <argos3/core/simulator/space/space.h>
5#include <argos3/core/simulator/space/positional_indices/grid.h>
6#include <argos3/core/utility/configuration/argos_exception.h>
7#include <argos3/core/utility/logging/argos_log.h>
8
9namespace argos {
10
11 /****************************************/
12 /****************************************/
13
15 m_bCheckOcclusions(true) {
16 }
17
18 /****************************************/
19 /****************************************/
20
23
24 /****************************************/
25 /****************************************/
26
28 try {
29 CMedium::Init(t_tree);
30 /* Check occlusions? */
31 GetNodeAttributeOrDefault(t_tree, "check_occlusions", m_bCheckOcclusions, m_bCheckOcclusions);
32 /* Get the positional index method */
33 std::string strPosIndexMethod("grid");
34 GetNodeAttributeOrDefault(t_tree, "index", strPosIndexMethod, strPosIndexMethod);
35 /* Get the arena center and size */
36 CVector3 cArenaCenter;
37 CVector3 cArenaSize;
38 TConfigurationNode& tArena = GetNode(CSimulator::GetInstance().GetConfigurationRoot(), "arena");
39 GetNodeAttribute(tArena, "size", cArenaSize);
40 GetNodeAttributeOrDefault(tArena, "center", cArenaCenter, cArenaCenter);
41 /* Create the positional index for embodied entities */
42 if(strPosIndexMethod == "grid") {
43 size_t punGridSize[3];
44 if(!NodeAttributeExists(t_tree, "grid_size")) {
45 punGridSize[0] = static_cast<size_t>(cArenaSize.GetX());
46 punGridSize[1] = static_cast<size_t>(cArenaSize.GetY());
47 punGridSize[2] = static_cast<size_t>(cArenaSize.GetZ());
48 }
49 else {
50 std::string strPosGridSize;
51 GetNodeAttribute(t_tree, "grid_size", strPosGridSize);
52 ParseValues<size_t>(strPosGridSize, 3, punGridSize, ',');
53 }
55 cArenaCenter - cArenaSize * 0.5f, cArenaCenter + cArenaSize * 0.5f,
56 punGridSize[0], punGridSize[1], punGridSize[2]);
57 m_pcRABEquippedEntityGridUpdateOperation = new CRABEquippedEntityGridEntityUpdater(*pcGrid);
58 pcGrid->SetUpdateEntityOperation(m_pcRABEquippedEntityGridUpdateOperation);
59 m_pcRABEquippedEntityIndex = pcGrid;
60 }
61 else {
62 THROW_ARGOSEXCEPTION("Unknown method \"" << strPosIndexMethod << "\" for the positional index.");
63 }
64 }
65 catch(CARGoSException& ex) {
66 THROW_ARGOSEXCEPTION_NESTED("Error in initialization of the range-and-bearing medium", ex);
67 }
68 }
69
70 /****************************************/
71 /****************************************/
72
74 Update();
75 }
76
77 /****************************************/
78 /****************************************/
79
81 /* Reset positional index of RAB entities */
82 m_pcRABEquippedEntityIndex->Reset();
83 /* Delete routing table */
84 for(TRoutingTable::iterator it = m_tRoutingTable.begin();
85 it != m_tRoutingTable.end();
86 ++it) {
87 it->second.clear();
88 }
89 }
90
91 /****************************************/
92 /****************************************/
93
95 delete m_pcRABEquippedEntityIndex;
96 if(m_pcRABEquippedEntityGridUpdateOperation != nullptr) {
97 delete m_pcRABEquippedEntityGridUpdateOperation;
98 }
99 }
100
101 /****************************************/
102 /****************************************/
103
104 static size_t HashRABPair(const std::pair<CRABEquippedEntity*, CRABEquippedEntity*>& c_pair) {
105 return
106 reinterpret_cast<size_t>(c_pair.first) ^
107 reinterpret_cast<size_t>(c_pair.second);
108 }
109
111 /* Update positional index of RAB entities */
112 m_pcRABEquippedEntityIndex->Update();
113 /* Delete routing table */
114 for(TRoutingTable::iterator it = m_tRoutingTable.begin();
115 it != m_tRoutingTable.end();
116 ++it) {
117 it->second.clear();
118 }
119 /* This map contains the pairs that have already been checked */
120 unordered_map<ssize_t, std::pair<CRABEquippedEntity*, CRABEquippedEntity*> > mapPairsAlreadyChecked;
121 /* Iterator for the above structure */
122 unordered_map<ssize_t, std::pair<CRABEquippedEntity*, CRABEquippedEntity*> >::iterator itPair;
123 /* Used as test key */
124 std::pair<CRABEquippedEntity*, CRABEquippedEntity*> cTestKey;
125 /* Used as hash for the test key */
126 UInt64 unTestHash;
127 /* The ray to use for occlusion checking */
128 CRay3 cOcclusionCheckRay;
129 /* Buffer for the communicating entities */
131 /* Buffer to store the intersection data */
132 SEmbodiedEntityIntersectionItem sIntersectionItem;
133 /* The distance between two RABs in line of sight */
134 Real fDistance;
135 /* Go through the RAB entities */
136 for(TRoutingTable::iterator it = m_tRoutingTable.begin();
137 it != m_tRoutingTable.end();
138 ++it) {
139 /* Get a reference to the current RAB entity */
140 CRABEquippedEntity& cRAB = *reinterpret_cast<CRABEquippedEntity*>(GetSpace().GetEntityVector()[it->first]);
141 /* Initialize the occlusion check ray start to the position of the robot */
142 cOcclusionCheckRay.SetStart(cRAB.GetPosition());
143 /* For each RAB entity, get the list of RAB entities in range */
144 cOtherRABs.clear();
145 m_pcRABEquippedEntityIndex->GetEntitiesAt(cOtherRABs, cRAB.GetPosition());
146 /* Go through the RAB entities in range */
147 for(CSet<CRABEquippedEntity*>::iterator it2 = cOtherRABs.begin();
148 it2 != cOtherRABs.end();
149 ++it2) {
150 /* Get a reference to the RAB entity */
151 CRABEquippedEntity& cOtherRAB = **it2;
152 /* First, make sure the entities are not the same */
153 if(&cRAB != &cOtherRAB) {
154 /* Proceed if the pair has not been checked already */
155 if(&cRAB < &cOtherRAB) {
156 cTestKey.first = &cRAB;
157 cTestKey.second = &cOtherRAB;
158 }
159 else {
160 cTestKey.first = &cOtherRAB;
161 cTestKey.second = &cRAB;
162 }
163 unTestHash = HashRABPair(cTestKey);
164 itPair = mapPairsAlreadyChecked.find(unTestHash);
165 if(itPair == mapPairsAlreadyChecked.end() || /* Pair does not exist */
166 itPair->second.first != cTestKey.first || /* Pair exists, but first RAB involved is different */
167 itPair->second.second != cTestKey.second) { /* Pair exists, but second RAB involved is different */
168 /* Mark this pair as already checked */
169 mapPairsAlreadyChecked[unTestHash] = cTestKey;
170 /* Proceed if the message size is compatible */
171 if(cRAB.GetMsgSize() == cOtherRAB.GetMsgSize()) {
172 /* Proceed if the two entities are not obstructed by another object */
173 cOcclusionCheckRay.SetEnd(cOtherRAB.GetPosition());
174 if((!m_bCheckOcclusions) ||
176 cOcclusionCheckRay,
177 cRAB.GetEntityBody())) ||
178 (&cOtherRAB.GetEntityBody() == sIntersectionItem.IntersectedEntity)) {
179 /* If we get here, the two RAB entities are in direct line of sight */
180 /* cRAB can receive cOtherRAB's message if it is in range, and viceversa */
181 /* Calculate square distance */
182 fDistance = cOcclusionCheckRay.GetLength();
183 if(fDistance < cOtherRAB.GetRange()) {
184 /* cRAB receives cOtherRAB's message */
185 m_tRoutingTable[cRAB.GetIndex()].insert(&cOtherRAB);
186 }
187 if(fDistance < cRAB.GetRange()) {
188 /* cOtherRAB receives cRAB's message */
189 m_tRoutingTable[cOtherRAB.GetIndex()].insert(&cRAB);
190 }
191 } // occlusion found?
192 } // is msg size the same?
193 } // is check necessary?
194 } // are entities the same?
195 } // for entities in range
196 } // for routing table
197 }
198
199 /****************************************/
200 /****************************************/
201
203 m_tRoutingTable.insert(
204 std::make_pair<ssize_t, CSet<CRABEquippedEntity*,SEntityComparator> >(
206 m_pcRABEquippedEntityIndex->AddEntity(c_entity);
207 m_pcRABEquippedEntityIndex->Update();
208 }
209
210 /****************************************/
211 /****************************************/
212
214 m_pcRABEquippedEntityIndex->RemoveEntity(c_entity);
215 m_pcRABEquippedEntityIndex->Update();
216 TRoutingTable::iterator it = m_tRoutingTable.find(c_entity.GetIndex());
217 if(it != m_tRoutingTable.end())
218 m_tRoutingTable.erase(it);
219 }
220
221 /****************************************/
222 /****************************************/
223
225 TRoutingTable::const_iterator it = m_tRoutingTable.find(c_entity.GetIndex());
226 if(it != m_tRoutingTable.end()) {
227 return it->second;
228 }
229 else {
230 THROW_ARGOSEXCEPTION("RAB entity \"" << c_entity.GetContext() << c_entity.GetId() << "\" is not managed by the RAB medium \"" << GetId() << "\"");
231 }
232 }
233
234 /****************************************/
235 /****************************************/
236
238 "range_and_bearing",
239 "Carlo Pinciroli [ilpincy@gmail.com]",
240 "1.0",
241 "It simulates the communication across range-and-bearing-equipped robots.",
242 "This medium is required to simulate communication across range-and-bearing-\n"
243 "equipped robots. You need to add it to the <media> section every time you add\n"
244 "a range-and-bearing-equipped entity whose controller has a range-and-bearing\n"
245 "device activated.\n\n"
246 "REQUIRED XML CONFIGURATION\n\n"
247 "<range_and_bearing id=\"rab\" />\n\n"
248 "OPTIONAL XML CONFIGURATION\n\n"
249 "By default, the RAB medium requires two robots to be in direct line-of-sight in\n"
250 "order to be able to exchange messages. You can toggle this behavior on or off\n"
251 "through the 'check_occlusions' attribute:\n\n"
252 "<range_and_bearing id=\"rab\" check_occlusions=\"false\" />\n\n",
253 "Under development"
254 );
255
256 /****************************************/
257 /****************************************/
258
259}
unsigned long long UInt64
64-bit unsigned integer.
Definition datatypes.h:107
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 THROW_ARGOSEXCEPTION(message)
This macro throws an ARGoS exception with the passed message.
#define REGISTER_MEDIUM(CLASSNAME, LABEL, AUTHOR, VERSION, BRIEF_DESCRIPTION, LONG_DESCRIPTION, STATUS)
Definition medium.h:108
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.
bool NodeAttributeExists(TConfigurationNode &t_node, const std::string &str_attribute)
Returns true if the specified attribute of a node exists.
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.
void ParseValues(std::istream &str_input, UInt32 un_num_fields, T *pt_field_buffer, const char ch_delimiter='\n')
ticpp::Element TConfigurationNode
The ARGoS configuration XML node.
TConfigurationNode & GetNode(TConfigurationNode &t_node, const std::string &str_tag)
Given a tree root node, returns the first of its child nodes with the wanted name.
void GetNodeAttribute(TConfigurationNode &t_node, const std::string &str_attribute, T &t_buffer)
Returns the value of a node's attribute.
const std::string & GetId() const
Returns the id of this entity.
Definition entity.h:157
std::string GetContext() const
Returns the context of this entity.
Definition entity.cpp:79
ssize_t GetIndex() const
Returns the entity index.
Definition entity.h:234
const CVector3 & GetPosition() const
virtual void Init(TConfigurationNode &t_tree)
Initialized the medium.
Definition medium.cpp:16
CSpace & GetSpace()
Returns a reference to the ARGoS space.
Definition medium.h:92
const std::string & GetId() const
Returns the id of this medium.
Definition medium.h:76
static CSimulator & GetInstance()
Returns the instance to the CSimulator class.
Definition simulator.cpp:78
void SetUpdateEntityOperation(CEntityOperation *pc_operation)
Definition grid_impl.h:907
CEntity::TVector & GetEntityVector()
Returns a vector of all the entities in the space.
Definition space.h:136
The exception that wraps all errors in ARGoS.
The CSet iterator.
Definition set.h:39
Defines a very simple double-linked list that stores unique elements.
Definition set.h:101
iterator begin() const
Returns an iterator to the first element.
Definition set.h:389
void clear()
Erases the contents of the list.
Definition set.h:351
iterator end() const
Returns an invalid iterator.
Definition set.h:397
void SetEnd(const CVector3 &c_end)
Definition ray3.h:57
Real GetLength() const
Definition ray3.h:96
void SetStart(const CVector3 &c_start)
Definition ray3.h:53
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
Real GetZ() const
Returns the z coordinate of this vector.
Definition vector3.h:137
CEmbodiedEntity & GetEntityBody()
virtual void Update()
Updates the state of this medium.
void AddEntity(CRABEquippedEntity &c_entity)
Adds the specified entity to the list of managed entities.
virtual void Destroy()
Undoes whatever was done by Init().
const CSet< CRABEquippedEntity *, SEntityComparator > & GetRABsCommunicatingWith(CRABEquippedEntity &c_entity) const
Returns an immutable vector of RAB entities that can communicated with the given entity.
CRABMedium()
Class constructor.
virtual void PostSpaceInit()
Executes extra initialization activities after the space has been initialized.
void RemoveEntity(CRABEquippedEntity &c_entity)
Removes the specified entity from the list of managed entities.
virtual ~CRABMedium()
Class destructor.
virtual void Reset()
Resets the resource.
virtual void Init(TConfigurationNode &t_tree)
Initialized the medium.