@@ -64,6 +64,8 @@ ign service -s /artifact/move_to \
64
64
#include < sdf/World.hh>
65
65
66
66
#include " subt_ign/Common.hh"
67
+ #include " subt_communication_broker/subt_communication_client.h"
68
+ #include " subt_ign/protobuf/artifact.pb.h"
67
69
68
70
IGNITION_ADD_PLUGIN (
69
71
subt::ArtifactValidator,
@@ -107,9 +109,26 @@ class subt::ArtifactValidatorPrivate
107
109
public: bool OnPrev (const ignition::msgs::StringMsg &_msg,
108
110
ignition::msgs::StringMsg &_rep);
109
111
112
+ // / \brief Callback fired when the score service is called.
113
+ // / \param[in] _msg Service request
114
+ // / \param[out] _rep Service response
115
+ public: bool OnScore (const ignition::msgs::StringMsg &_msg,
116
+ ignition::msgs::StringMsg &_rep);
117
+
118
+ public: bool ReportArtifact (const ArtifactType _type,
119
+ const ignition::msgs::Pose &_pose);
120
+
121
+ public: void OnArtifactAck (const std::string &/* _srcAddress*/ ,
122
+ const std::string &/* _dstAddress*/ ,
123
+ const uint32_t /* _dstPort*/ ,
124
+ const std::string &_data);
125
+
110
126
// / \brief Map of artifact names to additional artifact data.
111
127
public: std::map<std::string, Artifact> artifacts;
112
128
129
+ // / \brief Queue of artifacts to report
130
+ public: std::deque<Artifact*> toReport;
131
+
113
132
// / \brief Iterator to current position in map
114
133
public: std::map<std::string, Artifact>::iterator artifactsIter;
115
134
@@ -121,6 +140,12 @@ class subt::ArtifactValidatorPrivate
121
140
122
141
// / \brief World name of current world.
123
142
public: std::string worldName;
143
+
144
+ // / \brief Next time to check if client is nullptr
145
+ public: std::chrono::steady_clock::duration clientCheck{0 };
146
+
147
+ // / \brief Communication client.
148
+ public: std::unique_ptr<subt::CommsClient> client {nullptr };
124
149
};
125
150
126
151
// ///////////////////////////////////////////////
@@ -145,12 +170,13 @@ bool ArtifactValidatorPrivate::MoveTo(const ignition::msgs::StringMsg &_msg,
145
170
req.mutable_position ()->set_z (artifact.pose .Pos ().Z ());
146
171
_rep.set_data (_msg.data ());
147
172
148
- msgs::Boolean res;
173
+ ignition:: msgs::Boolean res;
149
174
bool result;
150
175
unsigned int timeout = 1000 ;
151
176
std::string service {" /world/" + this ->worldName + " /set_pose" };
152
177
node.Request (service, req, timeout, res, result);
153
178
igndbg << " Result: " << res.data () << " " << result << std::endl;
179
+
154
180
return result;
155
181
}
156
182
@@ -163,6 +189,79 @@ bool ArtifactValidatorPrivate::MoveToString(const std::string &_name,
163
189
return this ->MoveTo (msg, _rep);
164
190
}
165
191
192
+ // ///////////////////////////////////////////////
193
+ bool ArtifactValidatorPrivate::OnScore (const ignition::msgs::StringMsg& _req,
194
+ ignition::msgs::StringMsg& /* _rep*/ )
195
+ {
196
+ // Report the artifact that we are currently at
197
+ //
198
+ auto newIter = this ->artifacts .find (_req.data ());
199
+ if (newIter == this ->artifacts .end ())
200
+ {
201
+ ignerr << " Artifact: " << _req.data () << " does not exist" << std::endl;
202
+ return false ;
203
+ }
204
+ this ->artifactsIter = newIter;
205
+
206
+ auto artifact = this ->artifactsIter ->second ;
207
+ std::cout << " Reporting: " << artifact.String () << std::endl;
208
+
209
+ auto origin = this ->artifacts .find (" artifact_origin" )->second ;
210
+
211
+ ignition::msgs::Pose reportPose;
212
+ reportPose.mutable_position ()->set_x (artifact.pose .Pos ().X () - origin.pose .Pos ().X ());
213
+ reportPose.mutable_position ()->set_y (artifact.pose .Pos ().Y () - origin.pose .Pos ().Y ());
214
+ reportPose.mutable_position ()->set_z (artifact.pose .Pos ().Z () - origin.pose .Pos ().Z ());
215
+
216
+ return this ->ReportArtifact (artifact.type ,
217
+ reportPose);
218
+ }
219
+
220
+ // ///////////////////////////////////////////////
221
+ bool ArtifactValidatorPrivate::ReportArtifact (const ArtifactType _type,
222
+ const ignition::msgs::Pose &_pose)
223
+ {
224
+ subt::msgs::Artifact artifact;
225
+ artifact.set_type (static_cast <uint32_t >(_type));
226
+ artifact.mutable_pose ()->CopyFrom (_pose);
227
+
228
+ // Serialize the artifact.
229
+ std::string serializedData;
230
+
231
+ if (!artifact.SerializeToString (&serializedData)) {
232
+ std::cerr
233
+ << " ReportArtifact(): Error serializing message\n "
234
+ << artifact.DebugString () << std::endl;
235
+ return false ;
236
+ }
237
+
238
+ if (this ->client )
239
+ {
240
+ this ->client ->SendTo (serializedData, subt::kBaseStationName );
241
+ return true ;
242
+ }
243
+ else
244
+ {
245
+ return false ;
246
+ }
247
+ }
248
+
249
+ // ///////////////////////////////////////////////
250
+ void ArtifactValidatorPrivate::OnArtifactAck (const std::string &/* _srcAddress*/ ,
251
+ const std::string &/* _dstAddress*/ ,
252
+ const uint32_t /* _dstPort*/ ,
253
+ const std::string &_data)
254
+ {
255
+ subt::msgs::ArtifactScore ack;
256
+ if (!ack.ParseFromString (_data))
257
+ {
258
+ std::cerr << " Error parsing artifact score response" << std::endl;
259
+ }
260
+ else
261
+ {
262
+ }
263
+ }
264
+
166
265
// ///////////////////////////////////////////////
167
266
bool ArtifactValidatorPrivate::OnNext (const ignition::msgs::StringMsg& /* _req*/ ,
168
267
ignition::msgs::StringMsg& _rep)
@@ -264,17 +363,13 @@ void ArtifactValidator::Configure(const ignition::gazebo::Entity & /*_entity*/,
264
363
265
364
std::string fullPath;
266
365
subt::FullWorldPath (worldName, fullPath);
366
+ ignmsg << " Loading SDF world file[" << fullPath + " .sdf" << " ].\n " ;
267
367
268
- common::SystemPaths systemPaths;
269
- systemPaths.SetFilePathEnv (" IGN_GAZEBO_RESOURCE_PATH" );
270
- systemPaths.AddFilePaths (IGN_GAZEBO_WORLD_INSTALL_DIR);
271
- std::string filePath = systemPaths.FindFile (fullPath);
272
- ignmsg << " Loading SDF world file[" << filePath << " ].\n " ;
273
-
274
- auto errors = this ->dataPtr ->sdfRoot .Load (filePath);
368
+ auto errors = this ->dataPtr ->sdfRoot .Load (fullPath + " .sdf" );
275
369
276
370
if (!errors.empty ())
277
371
{
372
+ ignerr << " Couldn't load SDF" << std::endl;
278
373
for (auto &err : errors)
279
374
ignerr << err << " \n " ;
280
375
return ;
@@ -288,13 +383,38 @@ void ArtifactValidator::Configure(const ignition::gazebo::Entity & /*_entity*/,
288
383
&ArtifactValidatorPrivate::OnNext, this ->dataPtr .get ());
289
384
this ->dataPtr ->node .Advertise (" /artifact/prev" ,
290
385
&ArtifactValidatorPrivate::OnPrev, this ->dataPtr .get ());
386
+ this ->dataPtr ->node .Advertise (" /artifact/score" ,
387
+ &ArtifactValidatorPrivate::OnScore, this ->dataPtr .get ());
388
+
389
+ {
390
+ // Start the SubT competition
391
+ ignition::msgs::Boolean req;
392
+ ignition::msgs::Boolean rep;
393
+ unsigned int timeout = 5000 ;
394
+ bool result;
395
+ req.set_data (true );
396
+ this ->dataPtr ->node .Request (" /subt/start" , req, timeout, rep, result);
397
+ }
291
398
}
292
399
293
400
// ///////////////////////////////////////////////
294
401
void ArtifactValidator::PostUpdate (
295
- const ignition::gazebo::UpdateInfo &/* _info*/ ,
402
+ const ignition::gazebo::UpdateInfo &_info,
296
403
const ignition::gazebo::EntityComponentManager &/* _ecm*/ )
297
404
{
405
+ if (!this ->dataPtr ->client &&
406
+ _info.simTime > this ->dataPtr ->clientCheck )
407
+ {
408
+ this ->dataPtr ->client .reset (new subt::CommsClient (" validator" , false , true ));
409
+ auto bound = this ->dataPtr ->client ->Bind (&ArtifactValidatorPrivate::OnArtifactAck,
410
+ this ->dataPtr .get ());
411
+
412
+ if (!bound) {
413
+ this ->dataPtr ->client .reset (nullptr );
414
+ this ->dataPtr ->clientCheck = _info.simTime + std::chrono::milliseconds (100 );
415
+ }
416
+ }
417
+
298
418
if (this ->dataPtr ->artifactsIter == this ->dataPtr ->artifacts .end ())
299
419
{
300
420
this ->dataPtr ->artifactsIter = this ->dataPtr ->artifacts .begin ();
0 commit comments