light_buoy_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 <algorithm>
19 #include <gazebo/rendering/Scene.hh>
21 
22 const std::array<LightBuoyPlugin::Colors_t, 5> LightBuoyPlugin::kColors
23  = {LightBuoyPlugin::Colors_t(CreateColor(1.0, 0.0, 0.0, 1.0), "red"),
24  LightBuoyPlugin::Colors_t(CreateColor(0.0, 1.0, 0.0, 1.0), "green"),
25  LightBuoyPlugin::Colors_t(CreateColor(0.0, 0.0, 1.0, 1.0), "blue"),
26  LightBuoyPlugin::Colors_t(CreateColor(1.0, 1.0, 0.0, 1.0), "yellow"),
27  LightBuoyPlugin::Colors_t(CreateColor(0.0, 0.0, 0.0, 1.0), "off")};
28 
30 std_msgs::ColorRGBA LightBuoyPlugin::CreateColor(const double _r,
31  const double _g, const double _b, const double _a)
32 {
33  static std_msgs::ColorRGBA color;
34  color.r = _r;
35  color.g = _g;
36  color.b = _b;
37  color.a = _a;
38  return color;
39 }
40 
42 uint8_t LightBuoyPlugin::IndexFromColor(const std::string &_color)
43 {
44  uint8_t index = 0u;
45  for (auto color : kColors)
46  {
47  if (_color == color.second)
48  return index;
49 
50  ++index;
51  }
52 
53  return std::numeric_limits<uint8_t>::max();
54 }
55 
58 {
59  for (uint8_t i = 0u; i < this->kColors.size() - 1; ++i)
60  {
61  for (uint8_t j = 0u; j < this->kColors.size() - 1; ++j)
62  {
63  if (j == i)
64  continue;
65 
66  for (uint8_t k = 0u; k < this->kColors.size() - 1; ++k)
67  {
68  if (k == j)
69  continue;
70 
71  // The last two colors are always OFF.
72  this->allPatterns.push_back({i, j, k,
73  this->IndexFromColor("off"), this->IndexFromColor("off")});
74  }
75  }
76  }
77 }
78 
81  gzNode(new gazebo::transport::Node())
82 {
83 }
84 
88 {
89  pattern[0] = IndexFromColor(_msg->color_1());
90  pattern[1] = IndexFromColor(_msg->color_2());
91  pattern[2] = IndexFromColor(_msg->color_3());
92  pattern[3] = IndexFromColor("off");
93  pattern[4] = IndexFromColor("off");
94 
95  // If we get a new pattern, reinitialize the sequence.
96  std::lock_guard<std::mutex> lock(this->mutex);
97  this->nextUpdateTime = this->scene->SimTime() + gazebo::common::Time(1.0);
98  this->state = 0;
99 
100  return;
101 }
102 
104 void LightBuoyPlugin::Load(gazebo::rendering::VisualPtr _parent,
105  sdf::ElementPtr _sdf)
106 {
107  GZ_ASSERT(_parent != nullptr, "Received NULL model pointer");
108 
109  this->scene = _parent->GetScene();
110 
111  GZ_ASSERT(this->scene != nullptr, "NULL scene");
112 
113  this->InitializeAllPatterns();
114 
115  if (!this->ParseSDF(_sdf))
116  return;
117 
118  // Quit if ros plugin was not loaded
119  if (!ros::isInitialized())
120  {
121  ROS_ERROR("ROS was not initialized.");
122  return;
123  }
124 
125  if (this->shuffleEnabled)
126  {
127  this->nh = ros::NodeHandle(this->ns);
128  this->changePatternSub = this->nh.subscribe(
130  }
131 
132  this->nextUpdateTime = this->scene->SimTime();
133 
134  this->updateConnection = gazebo::event::Events::ConnectPreRender(
135  std::bind(&LightBuoyPlugin::Update, this));
136 
137  gzNode->Init();
138  this->colorSub = this->gzNode->Subscribe
140 }
141 
143 bool LightBuoyPlugin::ParseSDF(sdf::ElementPtr _sdf)
144 {
145  // Required: Sequence of colors.
146  uint8_t i = 0u;
147  for (auto colorIndex : {"color_1", "color_2", "color_3"})
148  {
149  if (!_sdf->HasElement(colorIndex))
150  {
151  ROS_ERROR("<%s> missing", colorIndex);
152  return false;
153  }
154 
155  auto color = _sdf->GetElement(colorIndex)->Get<std::string>();
156  std::transform(color.begin(), color.end(), color.begin(), ::tolower);
157 
158  // Sanity check: color should be red, green, blue, yellow or off.
159  if (color != "red" && color != "green" &&
160  color != "blue" && color != "yellow" && color != "off")
161  {
162  ROS_ERROR("Invalid color [%s]", color.c_str());
163  return false;
164  }
165 
166  this->pattern[i++] = IndexFromColor(color);
167  }
168 
169  // The last two colors of the pattern are always black.
170  this->pattern[3] = IndexFromColor("off");
171  this->pattern[4] = IndexFromColor("off");
172 
173  // Required: visuals.
174  if (!_sdf->HasElement("visuals"))
175  {
176  ROS_ERROR("<visuals> missing");
177  return false;
178  }
179 
180  auto visualsElem = _sdf->GetElement("visuals");
181  if (!visualsElem->HasElement("visual"))
182  {
183  ROS_ERROR("<visual> missing");
184  return false;
185  }
186 
187  auto visualElem = visualsElem->GetElement("visual");
188  while (visualElem)
189  {
190  std::string visualName = visualElem->Get<std::string>();
191  this->visualNames.push_back(visualName);
192  visualElem = visualElem->GetNextElement();
193  }
194 
195  // Optional: Is shuffle enabled?
196  if (_sdf->HasElement("shuffle"))
197  {
198  this->shuffleEnabled = _sdf->GetElement("shuffle")->Get<bool>();
199 
200  // Required if shuffle enabled: ROS topic.
201  if (!_sdf->HasElement("ros_shuffle_topic"))
202  {
203  ROS_ERROR("<ros_shuffle_topic> missing");
204  }
205  this->rosShuffleTopic = _sdf->GetElement
206  ("ros_shuffle_topic")->Get<std::string>();
207  }
208 
209  // optional gzColorsTopic
210  if (!_sdf->HasElement("gz_colors_topic"))
211  {
212  this->gzColorsTopic = "/vrx/light_buoy/new_pattern";
213  }
214  else
215  {
216  this->gzColorsTopic = _sdf->GetElement
217  ("gz_colors_topic")->Get<std::string>();
218  }
219  // Optional: ROS namespace.
220  if (_sdf->HasElement("robot_namespace"))
221  this->ns = _sdf->GetElement("robot_namespace")->Get<std::string>();
222 
223  return true;
224 }
225 
228 {
229  // Get the visuals if needed.
230  if (this->visuals.empty())
231  {
232  for (auto visualName : this->visualNames)
233  {
234  auto visualPtr = this->scene->GetVisual(visualName);
235  if (visualPtr)
236  this->visuals.push_back(visualPtr);
237  else
238  ROS_ERROR("Unable to find [%s] visual", visualName.c_str());
239  }
240  }
241 
242  std::lock_guard<std::mutex> lock(this->mutex);
243 
244  if (this->scene->SimTime() < this->nextUpdateTime)
245  return;
246 
247  this->nextUpdateTime = this->nextUpdateTime + gazebo::common::Time(1.0);
248 
249  // Start over if at end of pattern
250  if (this->state > 4)
251  this->state = 0;
252 
253  auto color = this->kColors[this->pattern[this->state]].first;
254  #if GAZEBO_MAJOR_VERSION >= 8
255  ignition::math::Color gazeboColor(color.r, color.g, color.b, color.a);
256  #else
257  gazebo::common::Color gazeboColor(color.r, color.g, color.b, color.a);
258  #endif
259  // Update the visuals.
260  for (auto visual : this->visuals)
261  {
262  visual->SetAmbient(gazeboColor);
263  visual->SetDiffuse(gazeboColor);
264  }
265 
266  // Increment index for next timer callback
267  ++this->state;
268 }
269 
271 void LightBuoyPlugin::ChangePattern(const std_msgs::Empty::ConstPtr &_msg)
272 {
273  this->pattern = this->allPatterns[this->allPatternsIdx];
274  this->allPatternsIdx = (this->allPatternsIdx + 1) % this->allPatterns.size();
275 
276  // Generate string representing pattern, ex: "RGB"
277  std::string colorSeq = "";
278  for (size_t i = 0; i < 3; ++i)
279  colorSeq += this->kColors[this->pattern[i]].second[0];
280  // Log the new pattern
281  ROS_INFO_NAMED("LightBuoyPlugin", "Pattern is %s", colorSeq.c_str());
282 }
283 
284 // Register plugin with gazebo
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.
std::vector< gazebo::rendering::VisualPtr > visuals
Pointer to the visual elements to modify.
void ChangePatternTo(gazebo::ConstLightBuoyColorsPtr &_msg)
Gazebo callback for changing light to a specific color pattern.
#define ROS_INFO_NAMED(name,...)
gazebo::transport::SubscriberPtr colorSub
void Load(gazebo::rendering::VisualPtr _parent, sdf::ElementPtr _sdf)
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
bool shuffleEnabled
Whether shuffle is enabled via a ROS topic or not.
Visual plugin for changing the color of some visual elements using ROS messages. This plugin accepts ...
ROSCPP_DECL bool isInitialized()
std::string rosShuffleTopic
ROS topic.
std::vector< std::string > visualNames
Collection of visual names.
bool ParseSDF(sdf::ElementPtr _sdf)
Parse all SDF parameters.
void InitializeAllPatterns()
Initialize all color sequences.
ros::NodeHandle nh
ROS Node handle.
static uint8_t IndexFromColor(const std::string &_color)
Return the index of the color from its string.
std::string ns
ROS namespace.
std::pair< std_msgs::ColorRGBA, std::string > Colors_t
void Update()
Display the next color in the sequence, or start over if at the end.
static const std::array< Colors_t, 5 > kColors
List of the color options (red, green, blue, yellow and no color) with their string name for logging...
Pattern_t pattern
The color pattern.
gazebo::transport::NodePtr gzNode
std::string gzColorsTopic
gazebo topic.
gazebo::rendering::ScenePtr scene
Pointer to the scene node.
size_t allPatternsIdx
The index pointing to one of the potential color sequences.
std::mutex mutex
Locks state and pattern member variables.
GZ_REGISTER_VISUAL_PLUGIN(GazeboRosVideo)
uint8_t state
Track current index in pattern.
gazebo::event::ConnectionPtr updateConnection
Connects to rendering update event.
std::vector< Pattern_t > allPatterns
All color sequences.
ros::Subscriber changePatternSub
Subscriber to generate and display a new color sequence.
gazebo::common::Time nextUpdateTime
Next time where the plugin should be updated.
#define ROS_ERROR(...)
void ChangePattern(const std_msgs::Empty::ConstPtr &_msg)
ROS callback for generating a new color pattern.


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