placard_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 <gazebo/rendering/Scene.hh>
20 
21 // Static initialization.
22 std::map<std::string, std_msgs::ColorRGBA> PlacardPlugin::kColors =
23  {
24  {"red", CreateColor(1.0, 0.0, 0.0, 1.0)},
25  {"green", CreateColor(0.0, 1.0, 0.0, 1.0)},
26  {"blue", CreateColor(0.0, 0.0, 1.0, 1.0)},
27  };
28 
29 std::vector<std::string> PlacardPlugin::kShapes =
30  {"circle", "cross", "triangle"};
31 
34  gzNode(new gazebo::transport::Node())
35 {
36 }
37 
39 std_msgs::ColorRGBA PlacardPlugin::CreateColor(const double _r,
40  const double _g, const double _b, const double _a)
41 {
42  static std_msgs::ColorRGBA color;
43  color.r = _r;
44  color.g = _g;
45  color.b = _b;
46  color.a = _a;
47  return color;
48 }
49 
52 {
53  for (auto const &colorPair : this->kColors)
54  for (auto const &shape : this->kShapes)
55  this->allPatterns.push_back({colorPair.first, shape});
56 }
57 
59 void PlacardPlugin::Load(gazebo::rendering::VisualPtr _parent,
60  sdf::ElementPtr _sdf)
61 {
62  GZ_ASSERT(_parent != nullptr, "Received NULL model pointer");
63 
64  this->scene = _parent->GetScene();
65  GZ_ASSERT(this->scene != nullptr, "NULL scene");
66 
67  this->InitializeAllPatterns();
68 
69  if (!this->ParseSDF(_sdf))
70  return;
71 
72  // Quit if ros plugin was not loaded
73  if (!ros::isInitialized())
74  {
75  ROS_ERROR("ROS was not initialized.");
76  return;
77  }
78 
79  if (this->shuffleEnabled)
80  {
81  this->nh = ros::NodeHandle(this->ns);
82  this->changeSymbolSub = this->nh.subscribe(
84  }
85 
86  this->nextUpdateTime = this->scene->SimTime();
87 
88  this->updateConnection = gazebo::event::Events::ConnectPreRender(
89  std::bind(&PlacardPlugin::Update, this));
90 
91  this->gzNode->Init();
92  this->symbolSub = gzNode->Subscribe(this->symbolSubTopic,
94 }
95 
97 {
98  std::lock_guard<std::mutex> lock(this->mutex);
99  this->shape = _msg->shape();
100  this->color = _msg->color();
101 }
102 
103 
105 bool PlacardPlugin::ParseSDF(sdf::ElementPtr _sdf)
106 {
107  // We initialize it with a random shape and color.
108  this->ChangeSymbol(std_msgs::Empty::ConstPtr());
109 
110  // Parse the shape.
111  if (_sdf->HasElement("shape"))
112  {
113  std::string aShape = _sdf->GetElement("shape")->Get<std::string>();
114  std::transform(aShape.begin(), aShape.end(), aShape.begin(), ::tolower);
115  // Sanity check: Make sure the shape is allowed.
116  if (std::find(this->kShapes.begin(), this->kShapes.end(), aShape) !=
117  this->kShapes.end())
118  {
119  this->shape = aShape;
120  }
121  else
122  {
123  ROS_INFO_NAMED("PlacardPlugin",
124  "incorrect [%s] <shape>, using random shape", aShape.c_str());
125  }
126  }
127 
128  // Parse the color. We initialize it with a random color.
129  if (_sdf->HasElement("color"))
130  {
131  std::string aColor = _sdf->GetElement("color")->Get<std::string>();
132  std::transform(aColor.begin(), aColor.end(), aColor.begin(), ::tolower);
133  // Sanity check: Make sure the color is allowed.
134  if (this->kColors.find(aColor) != this->kColors.end())
135  {
136  this->color = aColor;
137  }
138  else
139  {
140  ROS_INFO_NAMED("PlacardPlugin",
141  "incorrect [%s] <color>, using random color", aColor.c_str());
142  }
143  }
144 
145  // Required: visuals.
146  if (!_sdf->HasElement("visuals"))
147  {
148  ROS_ERROR("<visuals> missing");
149  return false;
150  }
151 
152  auto visualsElem = _sdf->GetElement("visuals");
153  if (!visualsElem->HasElement("visual"))
154  {
155  ROS_ERROR("<visual> missing");
156  return false;
157  }
158 
159  auto visualElem = visualsElem->GetElement("visual");
160  while (visualElem)
161  {
162  std::string visualName = visualElem->Get<std::string>();
163  this->visualNames.push_back(visualName);
164  visualElem = visualElem->GetNextElement();
165  }
166 
167  // Optional: Is shuffle enabled?
168  if (_sdf->HasElement("shuffle"))
169  {
170  this->shuffleEnabled = _sdf->GetElement("shuffle")->Get<bool>();
171 
172  // Required if shuffle enabled: ROS topic.
173  if (!_sdf->HasElement("ros_shuffle_topic"))
174  {
175  ROS_ERROR("<ros_shuffle_topic> missing");
176  }
177  this->rosShuffleTopic = _sdf->GetElement
178  ("ros_shuffle_topic")->Get<std::string>();
179  }
180 
181  // Required: namespace.
182  if (!_sdf->HasElement("robot_namespace"))
183  {
184  ROS_ERROR("<robot_namespace> missing");
185  }
186  this->ns = _sdf->GetElement("robot_namespace")->Get<std::string>();
187  if (!_sdf->HasElement("gz_symbol_topic"))
188  {
189  this->symbolSubTopic = "/" + this->ns + "/symbol";
190  }
191  else
192  {
193  this->symbolSubTopic = _sdf->GetElement
194  ("gz_symbol_topic")->Get<std::string>();
195  }
196  return true;
197 }
198 
201 {
202  // Get the visuals if needed.
203  if (this->visuals.empty())
204  {
205  for (auto visualName : this->visualNames)
206  {
207  auto visualPtr = this->scene->GetVisual(visualName);
208  if (visualPtr)
209  this->visuals.push_back(visualPtr);
210  else
211  ROS_ERROR("Unable to find [%s] visual", visualName.c_str());
212  }
213  }
214 
215  // Only update the plugin at 1Hz.
216  if (this->scene->SimTime() < this->nextUpdateTime)
217  return;
218 
219  this->nextUpdateTime = this->nextUpdateTime + gazebo::common::Time(1.0);
220 
221  std::lock_guard<std::mutex> lock(this->mutex);
222 
223  // Update the visuals.
224  for (auto visual : this->visuals)
225  {
226  std_msgs::ColorRGBA color;
227  color.a = 0.0;
228 
229  #if GAZEBO_MAJOR_VERSION >= 8
230  auto name = visual->Name();
231  #else
232  auto name = visual->GetName();
233  #endif
234  auto delim = name.rfind("/");
235  auto shortName = name.substr(delim + 1);
236  if (shortName.find(this->shape) != std::string::npos)
237  {
238  color = this->kColors[this->color];
239  }
240  #if GAZEBO_MAJOR_VERSION >= 8
241  ignition::math::Color gazeboColor(color.r, color.g, color.b, color.a);
242  #else
243  gazebo::common::Color gazeboColor(color.r, color.g, color.b, color.a);
244  #endif
245 
246  visual->SetAmbient(gazeboColor);
247  visual->SetDiffuse(gazeboColor);
248  }
249 }
250 
252 void PlacardPlugin::ChangeSymbol(const std_msgs::Empty::ConstPtr &_msg)
253 {
254  {
255  std::lock_guard<std::mutex> lock(this->mutex);
256  this->color = this->allPatterns[this->allPatternsIdx].at(0);
257  this->shape = this->allPatterns[this->allPatternsIdx].at(1);
258  this->allPatternsIdx =
259  (this->allPatternsIdx + 1) % this->allPatterns.size();
260  }
261 
262  ROS_INFO_NAMED("PlacardPlugin", "New symbol is %s %s", this->color.c_str(),
263  this->shape.c_str());
264 }
265 
266 // Register plugin with gazebo
static std::vector< std::string > kShapes
List of the shape options (circle, cross, triangle) with their string name for logging.
#define ROS_INFO_NAMED(name,...)
ros::NodeHandle nh
ROS Node handle.
gazebo::rendering::ScenePtr scene
Pointer to the scene node.
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
void InitializeAllPatterns()
Initialize all color/symbol sequences.
gazebo::event::ConnectionPtr updateConnection
Connects to rendering update event.
ROSCPP_DECL bool isInitialized()
std::mutex mutex
Locks state and pattern member variables.
ros::Subscriber changeSymbolSub
Service to generate and display a new symbol.
bool ParseSDF(sdf::ElementPtr _sdf)
Parse all SDF parameters.
std::string rosShuffleTopic
ROS topic.
gazebo::transport::NodePtr gzNode
gazebo Node
gazebo::common::Time nextUpdateTime
Next time where the plugin should be updated.
std::string color
The current color.
size_t allPatternsIdx
The index pointing to one of the potential color/symbol sequence.
void ChangeSymbolTo(gazebo::ConstDockPlacardPtr &_msg)
Gazebo callback for changing light to a specific color pattern.
Controls the shape and color of a symbol.
std::vector< std::array< std::string, 2u > > allPatterns
All color/symbol sequences.
std::vector< std::string > visualNames
Collection of visual names.
void Update()
Display the symbol in the placard.
GZ_REGISTER_VISUAL_PLUGIN(GazeboRosVideo)
bool shuffleEnabled
Whether shuffle is enabled via a ROS topic or not.
static std::map< std::string, std_msgs::ColorRGBA > kColors
List of the color options (red, green, blue, and no color) with their string name for logging...
void Load(gazebo::rendering::VisualPtr _parent, sdf::ElementPtr _sdf)
std::string ns
ROS namespace.
std::string symbolSubTopic
gazebo symbol sub topic
std::vector< gazebo::rendering::VisualPtr > visuals
Pointer to the visual elements to modify.
std::string shape
The current shape.
static std_msgs::ColorRGBA CreateColor(const double _r, const double _g, const double _b, const double _a)
Creates a std_msgs::ColorRGBA message from 4 doubles.
gazebo::transport::SubscriberPtr symbolSub
symbol subscriber
#define ROS_ERROR(...)
void ChangeSymbol(const std_msgs::Empty::ConstPtr &_msg)
ROS callback for changing a symbol and its color.


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