stationkeeping_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 <std_msgs/Float64.h>
19 #include <cmath>
20 #include <gazebo/common/Console.hh>
21 #include <gazebo/common/SphericalCoordinates.hh>
22 #include <gazebo/physics/Model.hh>
23 #include <ignition/math/Quaternion.hh>
24 #include <ignition/math/Vector3.hh>
25 
27 
30  : waypointMarkers("station_keeping_marker")
31 {
32  gzmsg << "Stationkeeping scoring plugin loaded" << std::endl;
33 
34  this->timer.Stop();
35  this->timer.Reset();
36 }
37 
39 void StationkeepingScoringPlugin::Load(gazebo::physics::WorldPtr _world,
40  sdf::ElementPtr _sdf)
41 {
42  ScoringPlugin::Load(_world, _sdf);
43  gzmsg << "Task [" << this->TaskName() << "]" << std::endl;
44 
45  // Get lat, lon and yaw from SDF
46  ignition::math::Vector3d latlonyaw(0, 0, 0);
47  if (!_sdf->HasElement("goal_pose"))
48  {
49  ROS_ERROR("Unable to find <goal_pose> element in SDF.");
50  ROS_ERROR("Using default pose: 0 0 0");
51  }
52  else
53  {
54  latlonyaw = _sdf->Get<ignition::math::Vector3d>("goal_pose");
55  }
56  // Store spherical 2D location
57  this->goalLat = latlonyaw.X();
58  this->goalLon = latlonyaw.Y();
59 
60  // Convert lat/lon to local
61  // Snippet from UUV Simulator SphericalCoordinatesROSInterfacePlugin.cc
62  ignition::math::Vector3d scVec(this->goalLat, this->goalLon, 0.0);
63 
64 #if GAZEBO_MAJOR_VERSION >= 8
65  ignition::math::Vector3d cartVec =
66  _world->SphericalCoords()->LocalFromSpherical(scVec);
67 #else
68  ignition::math::Vector3d cartVec =
69  _world->GetSphericalCoordinates()->LocalFromSpherical(scVec);
70 #endif
71 
72  // Store local 2D location and yaw
73  this->goalX = cartVec.X();
74  this->goalY = cartVec.Y();
75  this->goalYaw = latlonyaw.Z();
76 
77  // Print some debugging messages
78  gzmsg << "StationKeeping Goal, Spherical: Lat = " << this->goalLat
79  << " Lon = " << this->goalLon << std::endl;
80  gzmsg << "StationKeeping Goal, Local: X = " << this->goalX
81  << " Y = " << this->goalY << " Yaw = " << this->goalYaw << std::endl;
82 
83  // Setup ROS node and publisher
84  this->rosNode.reset(new ros::NodeHandle());
85  this->goalPub = this->rosNode->advertise<geographic_msgs::GeoPoseStamped>(
86  this->goalTopic, 10, true);
87 
88  this->poseErrorPub = this->rosNode->advertise<std_msgs::Float64>(
89  this->poseErrorTopic, 100);
90  this->meanErrorPub = this->rosNode->advertise<std_msgs::Float64>(
91  this->meanErrorTopic, 100);
92 
93  this->updateConnection = gazebo::event::Events::ConnectWorldUpdateBegin(
94  std::bind(&StationkeepingScoringPlugin::Update, this));
95 
96  if (_sdf->HasElement("markers"))
97  {
98  this->waypointMarkers.Load(_sdf->GetElement("markers"));
99  if (this->waypointMarkers.IsAvailable())
100  {
101  if (!this->waypointMarkers.DrawMarker(0, this->goalX, this->goalY,
102  this->goalYaw))
103  {
104  gzerr << "Error creating visual marker" << std::endl;
105  }
106  }
107  else
108  {
109  gzwarn << "Cannot display gazebo markers (Gazebo version < 8)"
110  << std::endl;
111  }
112  }
113 }
114 
117 {
118  // The vehicle might not be ready yet, let's try to get it.
119  if (!this->vehicleModel)
120  {
121  #if GAZEBO_MAJOR_VERSION >= 8
122  this->vehicleModel = this->world->ModelByName(this->vehicleName);
123  #else
124  this->vehicleModel = this->world->GetModel(this->vehicleName);
125  #endif
126  if (!this->vehicleModel)
127  return;
128  }
129 
130  // Nothing to do if the task is not in "running" state.
131  if (this->ScoringPlugin::TaskState() != "running")
132  return;
133 
134  std_msgs::Float64 poseErrorMsg;
135  std_msgs::Float64 meanErrorMsg;
136 
137  #if GAZEBO_MAJOR_VERSION >= 8
138  const auto robotPose = this->vehicleModel->WorldPose();
139  #else
140  const auto robotPose = this->vehicleModel->GetWorldPose().Ign();
141  #endif
142 
143  double currentHeading = robotPose.Rot().Euler().Z();
144  double dx = this->goalX - robotPose.Pos().X();
145  double dy = this->goalY - robotPose.Pos().Y();
146  double dhdg = abs(this->goalYaw - currentHeading);
147  double headError = 1 - abs(dhdg - M_PI)/M_PI;
148 
149  this->poseError = sqrt(pow(dx, 2) + pow(dy, 2)) + headError;
150  this->totalPoseError += this->poseError;
151  this->sampleCount++;
152 
153  this->meanError = this->totalPoseError / this->sampleCount;
154 
155  poseErrorMsg.data = this->poseError;
156  meanErrorMsg.data = this->meanError;
157 
158  // Publish at 1 Hz.
159  if (this->timer.GetElapsed() >= gazebo::common::Time(1.0))
160  {
161  this->poseErrorPub.publish(poseErrorMsg);
162  this->meanErrorPub.publish(meanErrorMsg);
163  this->timer.Reset();
164  this->timer.Start();
165  }
166 
167  this->ScoringPlugin::SetScore(this->meanError);
168 }
169 
172 {
173  gzmsg << "Publishing Goal coordinates" << std::endl;
174  geographic_msgs::GeoPoseStamped goal;
175 
176  // populating GeoPoseStamped... must be a better way?
177  goal.pose.position.latitude = this->goalLat;
178  goal.pose.position.longitude = this->goalLon;
179  goal.pose.position.altitude = 0.0;
180 
181  const ignition::math::Quaternion<double> orientation(0.0, 0.0, this->goalYaw);
182 
183  goal.pose.orientation.x = orientation.X();
184  goal.pose.orientation.y = orientation.Y();
185  goal.pose.orientation.z = orientation.Z();
186  goal.pose.orientation.w = orientation.W();
187 
188  goal.header.stamp = ros::Time::now();
189 
190  this->goalPub.publish(goal);
191 }
192 
195 {
196  gzmsg << "OnReady" << std::endl;
197 
198  this->PublishGoal();
199 }
200 
203 {
204  gzmsg << "OnRunning" << std::endl;
205 
206  this->timer.Start();
207 }
208 
209 
210 // Register plugin with gazebo
void OnReady() override
Callback executed when the task state transition into "ready".
std::string poseErrorTopic
Topic where 2D pose error is published.
A plugin for computing the score of the station keeping task. This plugin derives from the generic Sc...
std::string TaskName() const
Get the task name.
WaypointMarkers waypointMarkers
Waypoint visualization markers.
void publish(const boost::shared_ptr< M > &message) const
double meanError
Cumulative 2D RMS error in meters.
double goalY
Goal pose in local (Gazebo) coordinates.
GZ_REGISTER_WORLD_PLUGIN(UsvWindPlugin)
bool IsAvailable()
Returns if markers are available for current system.
std::string TaskState() const
Get the task state.
double poseError
Combined 2D pose error (distance and yaw).
ros::Publisher goalPub
Publisher for the goal.
void Load(gazebo::physics::WorldPtr _world, sdf::ElementPtr _sdf)
void Update()
Callback executed at every world update.
double goalLon
Goal pose in spherical (WGS84) coordinates.
double goalLat
Goal pose in spherical (WGS84) coordinates.
void PublishGoal()
Publish the goal pose.
gazebo::event::ConnectionPtr updateConnection
Pointer to the update event connection.
std::string meanErrorTopic
Topic where mean pose error is published.
std::string goalTopic
Topic where the task stats are published.
double goalYaw
Goal pose in local (Gazebo) coordinates.
double totalPoseError
Sum of all pose error scores calculated so far.
void Load(gazebo::physics::WorldPtr _world, sdf::ElementPtr _sdf)
void Load(sdf::ElementPtr _sdf)
Load marker parameters from SDF.
void OnRunning() override
Callback executed when the task state transition into "running".
INLINE Rall1d< T, V, S > sqrt(const Rall1d< T, V, S > &arg)
gazebo::physics::WorldPtr world
A world pointer.
gazebo::physics::ModelPtr vehicleModel
Pointer to the vehicle to score.
INLINE Rall1d< T, V, S > pow(const Rall1d< T, V, S > &arg, double m)
INLINE Rall1d< T, V, S > abs(const Rall1d< T, V, S > &x)
std::unique_ptr< ros::NodeHandle > rosNode
ROS node handle.
bool DrawMarker(int _marker_id, double _x, double _y, double _yaw, std::string _text="")
Draw waypoint marker in Gazebo.
static Time now()
unsigned int sampleCount
Number of instant pose error scores calculated so far .
ros::Publisher meanErrorPub
Publisher for the current mean error.
gazebo::common::Timer timer
Timer used to calculate the elapsed time docked in the bay.
ros::Publisher poseErrorPub
Publisher for the combined 2D pose error.
void SetScore(double _newScore)
Set the score.
#define ROS_ERROR(...)
double goalX
Goal pose in local (Gazebo) coordinates.
std::string vehicleName
The name of the vehicle to score.


vrx_gazebo
Author(s): Brian Bingham , Carlos Aguero
autogenerated on Thu May 7 2020 03:54:56