Skip to content

Commit d20782e

Browse files
authored
Validate artifact scoring (#825)
* Add the ability to score an artifact via service. Signed-off-by: Michael Carroll <[email protected]> * Local updates Signed-off-by: Michael Carroll <[email protected]> * Add a retry mechanism for comms client If the comms client doesn't connect, it will retry every 100 ms of sim time. Signed-off-by: Michael Carroll <[email protected]>
1 parent 21ab9b6 commit d20782e

File tree

2 files changed

+189
-9
lines changed

2 files changed

+189
-9
lines changed

subt_ign/launch/validate_artifacts.ign

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,26 @@ ign service -s /artifact/move_to \
103103
name="ignition::gazebo::systems::SceneBroadcaster">
104104
</plugin>
105105

106+
<!-- The SubT challenge logic plugin -->
107+
<plugin entity_name="<%= $worldName %>"
108+
entity_type="world"
109+
filename="libGameLogicPlugin.so"
110+
name="subt::GameLogicPlugin">
111+
<!-- The collection of artifacts to locate -->
112+
<world_name><%= $worldName %></world_name>
113+
<ros>false</ros>
114+
115+
<duration_seconds><%= $durationSec %></duration_seconds>
116+
117+
<logging>
118+
<!-- Use the <path> element to control where to record the log file.
119+
The HOME path is used by default -->
120+
<path>/tmp/ign/logs</path>
121+
<filename_prefix>subt_<%= $circuit %></filename_prefix>
122+
<elevation_step_size>5</elevation_step_size>
123+
</logging>
124+
</plugin>
125+
106126
<!-- The SubT challenge logic plugin -->
107127
<plugin entity_name="<%= $worldName %>"
108128
entity_type="world"
@@ -205,6 +225,46 @@ ign service -s /artifact/move_to \
205225
</executable_wrapper>
206226
<%end%>
207227

228+
<!-- The SubT challenge comms broker plugin -->
229+
<plugin entity_name="<%= $worldName %>"
230+
entity_type="world"
231+
name="subt::CommsBrokerPlugin"
232+
filename="libCommsBrokerPlugin.so">
233+
<generate_table>true</generate_table>
234+
<world_name><%= $worldName %></world_name>
235+
<comms_model>
236+
<comms_model_type>visibility_range</comms_model_type>
237+
238+
<range_config>
239+
<max_range>500.0</max_range>
240+
<fading_exponent>0</fading_exponent>
241+
<L0>40</L0>
242+
<sigma>10.0</sigma>
243+
<scaling_factor>1</scaling_factor>
244+
<range_per_hop>2.0</range_per_hop>
245+
</range_config>
246+
247+
<visibility_config>
248+
<visibility_cost_to_fading_exponent>0.2</visibility_cost_to_fading_exponent>
249+
<comms_cost_max>10</comms_cost_max>
250+
</visibility_config>
251+
252+
<radio_config>
253+
<capacity>1000000</capacity>
254+
<tx_power>20</tx_power>
255+
<noise_floor>-90</noise_floor>
256+
<modulation>QPSK</modulation>
257+
</radio_config>
258+
</comms_model>
259+
</plugin>
260+
261+
<!-- The SubT challenge base station plugin -->
262+
<plugin entity_name="base_station"
263+
entity_type="model"
264+
name="subt::BaseStationPlugin"
265+
filename="libBaseStationPlugin.so">
266+
</plugin>
267+
208268
<plugin name="ignition::launch::GazeboFactory"
209269
filename="libignition-launch-gazebo-factory.so">
210270
<name>validator</name>

subt_ign/src/ArtifactValidator.cc

Lines changed: 129 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ ign service -s /artifact/move_to \
6464
#include <sdf/World.hh>
6565

6666
#include "subt_ign/Common.hh"
67+
#include "subt_communication_broker/subt_communication_client.h"
68+
#include "subt_ign/protobuf/artifact.pb.h"
6769

6870
IGNITION_ADD_PLUGIN(
6971
subt::ArtifactValidator,
@@ -107,9 +109,26 @@ class subt::ArtifactValidatorPrivate
107109
public: bool OnPrev(const ignition::msgs::StringMsg &_msg,
108110
ignition::msgs::StringMsg &_rep);
109111

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+
110126
/// \brief Map of artifact names to additional artifact data.
111127
public: std::map<std::string, Artifact> artifacts;
112128

129+
/// \brief Queue of artifacts to report
130+
public: std::deque<Artifact*> toReport;
131+
113132
/// \brief Iterator to current position in map
114133
public: std::map<std::string, Artifact>::iterator artifactsIter;
115134

@@ -121,6 +140,12 @@ class subt::ArtifactValidatorPrivate
121140

122141
/// \brief World name of current world.
123142
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};
124149
};
125150

126151
/////////////////////////////////////////////////
@@ -145,12 +170,13 @@ bool ArtifactValidatorPrivate::MoveTo(const ignition::msgs::StringMsg &_msg,
145170
req.mutable_position()->set_z(artifact.pose.Pos().Z());
146171
_rep.set_data(_msg.data());
147172

148-
msgs::Boolean res;
173+
ignition::msgs::Boolean res;
149174
bool result;
150175
unsigned int timeout = 1000;
151176
std::string service {"/world/" + this->worldName + "/set_pose"};
152177
node.Request(service, req, timeout, res, result);
153178
igndbg << "Result: " << res.data() << " " << result << std::endl;
179+
154180
return result;
155181
}
156182

@@ -163,6 +189,79 @@ bool ArtifactValidatorPrivate::MoveToString(const std::string &_name,
163189
return this->MoveTo(msg, _rep);
164190
}
165191

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+
166265
/////////////////////////////////////////////////
167266
bool ArtifactValidatorPrivate::OnNext(const ignition::msgs::StringMsg& /*_req*/,
168267
ignition::msgs::StringMsg& _rep)
@@ -264,17 +363,13 @@ void ArtifactValidator::Configure(const ignition::gazebo::Entity & /*_entity*/,
264363

265364
std::string fullPath;
266365
subt::FullWorldPath(worldName, fullPath);
366+
ignmsg << "Loading SDF world file[" << fullPath + ".sdf" << "].\n";
267367

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");
275369

276370
if (!errors.empty())
277371
{
372+
ignerr << "Couldn't load SDF" << std::endl;
278373
for (auto &err : errors)
279374
ignerr << err << "\n";
280375
return;
@@ -288,13 +383,38 @@ void ArtifactValidator::Configure(const ignition::gazebo::Entity & /*_entity*/,
288383
&ArtifactValidatorPrivate::OnNext, this->dataPtr.get());
289384
this->dataPtr->node.Advertise("/artifact/prev",
290385
&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+
}
291398
}
292399

293400
/////////////////////////////////////////////////
294401
void ArtifactValidator::PostUpdate(
295-
const ignition::gazebo::UpdateInfo &/*_info*/,
402+
const ignition::gazebo::UpdateInfo &_info,
296403
const ignition::gazebo::EntityComponentManager &/*_ecm*/)
297404
{
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+
298418
if (this->dataPtr->artifactsIter == this->dataPtr->artifacts.end())
299419
{
300420
this->dataPtr->artifactsIter = this->dataPtr->artifacts.begin();

0 commit comments

Comments
 (0)