navigation_scoring_plugin.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2019 Open Source Robotics Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16 */
17 
18 #include <cmath>
19 #include <gazebo/common/Assert.hh>
20 #include <gazebo/common/Console.hh>
22 
25  const gazebo::physics::ModelPtr _leftMarkerModel,
26  const gazebo::physics::ModelPtr _rightMarkerModel)
27  : leftMarkerModel(_leftMarkerModel),
28  rightMarkerModel(_rightMarkerModel)
29 {
30  this->Update();
31 }
32 
35 {
36  if (!this->leftMarkerModel || !this->rightMarkerModel)
37  return;
38 
39  // The pose of the markers delimiting the gate.
40  const auto leftMarkerPose = this->leftMarkerModel->GetWorldPose();
41  const auto rightMarkerPose = this->rightMarkerModel->GetWorldPose();
42 
43  // Unit vector from the left marker to the right one.
44  auto v1 = leftMarkerPose.pos - rightMarkerPose.pos;
45  v1.Normalize();
46 
47  // Unit vector perpendicular to v1 in the direction we like to cross gates.
48  const auto v2 = gazebo::math::Vector3::UnitZ.Cross(v1);
49 
50  // This is the center point of the gate.
51  const auto middle = (leftMarkerPose.pos + rightMarkerPose.pos) / 2.0;
52 
53  // Yaw of the gate in world coordinates.
54  const auto yaw = atan2(v2.y, v2.x);
55 
56  // The updated pose.
57  this->pose.Set(middle, gazebo::math::Vector3(0, 0, yaw));
58 
59  // The updated width.
60  this->width = leftMarkerPose.pos.Distance(rightMarkerPose.pos);
61 }
62 
65  const gazebo::math::Pose &_robotWorldPose) const
66 {
67  // Transform to gate frame.
68  const gazebo::math::Vector3 robotLocalPosition =
69  this->pose.rot.GetInverse().RotateVector(_robotWorldPose.pos -
70  this->pose.pos);
71 
72  // Are we within the width?
73  if (fabs(robotLocalPosition.y) <= this->width / 2.0)
74  {
75  if (robotLocalPosition.x >= 0.0)
77  else
79  }
80  else
82 }
83 
84 
87 {
88  gzmsg << "Navigation scoring plugin loaded" << std::endl;
89 }
90 
92 void NavigationScoringPlugin::Load(gazebo::physics::WorldPtr _world,
93  sdf::ElementPtr _sdf)
94 {
95  ScoringPlugin::Load(_world, _sdf);
96 
97  // This is a required element.
98  if (!_sdf->HasElement("gates"))
99  {
100  gzerr << "Unable to find <gates> element in SDF." << std::endl;
101  return;
102  }
103 
104  // Parse all the gates.
105  auto const &gatesElem = _sdf->GetElement("gates");
106  if (!this->ParseGates(gatesElem))
107  {
108  gzerr << "Score has been disabled" << std::endl;
109  return;
110  }
111 
112  gzmsg << "Task [" << this->TaskName() << "]" << std::endl;
113 
114  this->updateConnection = gazebo::event::Events::ConnectWorldUpdateBegin(
115  std::bind(&NavigationScoringPlugin::Update, this));
116 }
117 
119 bool NavigationScoringPlugin::ParseGates(sdf::ElementPtr _sdf)
120 {
121  GZ_ASSERT(_sdf, "NavigationScoringPlugin::ParseGates(): NULL _sdf pointer");
122 
123  // We need at least one gate.
124  if (!_sdf->HasElement("gate"))
125  {
126  gzerr << "Unable to find <gate> element in SDF." << std::endl;
127  return false;
128  }
129 
130  auto gateElem = _sdf->GetElement("gate");
131 
132  // Parse a new gate.
133  while (gateElem)
134  {
135  // The left marker's name.
136  if (!gateElem->HasElement("left_marker"))
137  {
138  gzerr << "Unable to find <left_marker> element in SDF." << std::endl;
139  return false;
140  }
141 
142  const std::string leftMarkerName =
143  gateElem->Get<std::string>("left_marker");
144 
145  // The right marker's name.
146  if (!gateElem->HasElement("right_marker"))
147  {
148  gzerr << "Unable to find <right_marker> element in SDF." << std::endl;
149  return false;
150  }
151 
152  const std::string rightMarkerName =
153  gateElem->Get<std::string>("right_marker");
154 
155  if (!this->AddGate(leftMarkerName, rightMarkerName))
156  return false;
157 
158  // Parse the next gate.
159  gateElem = gateElem->GetNextElement("gate");
160  }
161 
162  return true;
163 }
164 
166 bool NavigationScoringPlugin::AddGate(const std::string &_leftMarkerName,
167  const std::string &_rightMarkerName)
168 {
169  gazebo::physics::ModelPtr leftMarkerModel =
170  this->world->GetModel(_leftMarkerName);
171 
172  // Sanity check: Make sure that the model exists.
173  if (!leftMarkerModel)
174  {
175  gzerr << "Unable to find model [" << _leftMarkerName << "]" << std::endl;
176  return false;
177  }
178 
179  gazebo::physics::ModelPtr rightMarkerModel =
180  this->world->GetModel(_rightMarkerName);
181 
182  // Sanity check: Make sure that the model exists.
183  if (!rightMarkerModel)
184  {
185  gzerr << "Unable to find model [" << _rightMarkerName << "]" << std::endl;
186  return false;
187  }
188 
189  // Save the new gate.
190  this->gates.push_back(Gate(leftMarkerModel, rightMarkerModel));
191 
192  return true;
193 }
194 
197 {
198  // The vehicle might not be ready yet, let's try to get it.
199  if (!this->vehicleModel)
200  {
201  this->vehicleModel = this->world->GetModel(this->vehicleName);
202  if (!this->vehicleModel)
203  return;
204  }
205 
206  const auto robotPose = this->vehicleModel->GetWorldPose();
207 
208  // Update the state of all gates.
209  for (auto &gate : this->gates)
210  {
211  // Ignore all gates that have been crossed or are invalid.
212  if (gate.state == GateState::CROSSED || gate.state == GateState::INVALID)
213  continue;
214 
215  // Update this gate (in case it moved).
216  gate.Update();
217 
218  // Check if we have crossed this gate.
219  auto currentState = gate.IsPoseInGate(robotPose);
220  if (currentState == GateState::VEHICLE_AFTER &&
221  gate.state == GateState::VEHICLE_BEFORE)
222  {
223  currentState = GateState::CROSSED;
224  gzmsg << "New gate crossed!" << std::endl;
225  }
226  // Just checking: did we go backward through the gate?
227  else if (currentState == GateState::VEHICLE_BEFORE &&
228  gate.state == GateState::VEHICLE_AFTER)
229  {
230  currentState = GateState::INVALID;
231  gzmsg << "Transited the gate in the wrong direction. Gate invalidated!"
232  << std::endl;
233  }
234 
235  gate.state = currentState;
236  }
237 }
238 
241 {
242  gzmsg << "OnReady" << std::endl;
243 }
244 
247 {
248  gzmsg << "OnRunning" << std::endl;
249 }
250 
253 {
254  gzmsg << "OnFinished" << std::endl;
255 }
256 
257 // Register plugin with gazebo
258 GZ_REGISTER_WORLD_PLUGIN(NavigationScoringPlugin)
std::vector< Gate > gates
All the gates.
std::string TaskName() const
Get the task name.
Gate invalid. E.g.: if crossed in the wrong direction.
double width
The width of the gate in meters.
GateState IsPoseInGate(const gazebo::math::Pose &_robotWorldPose) const
Where is the given robot pose with respect to the gate?
void Load(gazebo::physics::WorldPtr _world, sdf::ElementPtr _sdf)
void OnReady() override
Callback executed when the task state transition into "ready".
gazebo::physics::ModelPtr rightMarkerModel
The right marker model.
bool ParseGates(sdf::ElementPtr _sdf)
Parse the gates from SDF.
void Load(gazebo::physics::WorldPtr _world, sdf::ElementPtr _sdf)
Gate(const gazebo::physics::ModelPtr _leftMarkerModel, const gazebo::physics::ModelPtr _rightMarkerModel)
Constructor.
gazebo::physics::WorldPtr world
A world pointer.
gazebo::physics::ModelPtr vehicleModel
Pointer to the vehicle to score.
void Update()
Recalculate the pose and width of the gate.
void OnFinished() override
Callback executed when the task state transition into "finished".
bool AddGate(const std::string &_leftMarkerName, const std::string &_rightMarkerName)
Register a new gate.
INLINE Rall1d< T, V, S > atan2(const Rall1d< T, V, S > &y, const Rall1d< T, V, S > &x)
gazebo::math::Pose pose
The center of the gate in the world frame. Note that the roll and pitch are ignored. Only yaw is relevant and it points into the direction in which the gate should be crossed.
void OnRunning() override
Callback executed when the task state transition into "running".
void Update()
Callback executed at every world update.
std::string vehicleName
The name of the vehicle to score.
gazebo::physics::ModelPtr leftMarkerModel
The left marker model.
gazebo::event::ConnectionPtr updateConnection
Pointer to the update event connection.
A plugin for computing the score of the navigation task. This plugin derives from the generic Scoring...


vmrc_gazebo
Author(s): Brian Bingham , Carlos Aguero
autogenerated on Sun Feb 17 2019 03:14:16