1 #include <led_msgs/SetLEDs.h> 2 #include <led_msgs/LEDStateArray.h> 6 #include <gazebo/common/Plugin.hh> 7 #include <gazebo/rendering/rendering.hh> 9 #if GAZEBO_MAJOR_VERSION >= 9 10 #include <ignition/math/Color.hh> 13 #include <gazebo/common/Color.hh> 18 #include <unordered_map> 50 std::unique_ptr<ros::NodeHandle>
nh;
59 bool setLeds(led_msgs::SetLEDs::Request& req, led_msgs::SetLEDs::Response& resp);
60 void handleLedsMsg(
const led_msgs::LEDStateArrayConstPtr& leds);
63 LedController(
const std::string& robotNamespace) : robotNamespace(robotNamespace)
68 ROS_FATAL_NAMED(
"LedController",
"Tried to load ROS plugin when ROS Gazebo API is not loaded. Please use gazebo_ros node to" 73 ROS_INFO_NAMED((
"LedController_" + robotNamespace).c_str(),
"LedController has started (as %s)", role == Role::Client ?
"client" :
"server");
76 if (role == Role::Server)
78 setLedsSrv = nh->advertiseService(
"led/set_leds", &LedController::setLeds,
this);
79 statePublisher = nh->advertise<led_msgs::LEDStateArray>(
"led/state", 1,
true);
84 stateSubscriber = nh->subscribe<led_msgs::LEDStateArray>(
"led/state", 1, &LedController::handleLedsMsg,
this);
95 assert(ledIdx < totalLeds);
96 std::lock_guard<std::mutex> lock(registryMutex);
98 registeredLeds.resize(totalLeds);
99 ledState.leds.resize(totalLeds);
101 ROS_DEBUG_NAMED((
"LedController_" + robotNamespace).c_str(),
"Registering LED visual plugin to %s (LED id=%d)", (role == Role::Client) ?
"client" :
"server", ledIdx);
102 registeredLeds[ledIdx] = plugin;
103 ledState.leds[ledIdx].index = ledIdx;
104 if (role == Role::Server)
105 statePublisher.
publish(ledState);
110 std::lock_guard<std::mutex> lock(registryMutex);
111 auto it = std::find(registeredLeds.begin(), registeredLeds.end(), plugin);
112 if (it != registeredLeds.end())
114 ROS_DEBUG_STREAM_NAMED((
"LedController_" + robotNamespace).c_str(),
"Unregistering LED visual plugin (LED id=" << (it - registeredLeds.begin()) <<
")");
125 static std::unordered_map<std::string, std::unique_ptr<LedController>> controllers;
126 std::lock_guard<std::mutex> lock(controllerMutex);
127 auto it = controllers.find(robotNamespace);
128 if (it == controllers.end()) {
129 gzwarn <<
"Creating new LED controller for namespace " << robotNamespace <<
"\n";
130 controllers[robotNamespace].reset(
new LedController(robotNamespace));
131 return *controllers[robotNamespace];
133 return *(it->second);
145 gazebo::rendering::VisualPtr
vptr;
148 void Load(gazebo::rendering::VisualPtr visual, sdf::ElementPtr sdf)
override {
153 auto parentName = sdf->GetParent()->GetAttribute(
"name")->GetAsString();
154 auto lastDashPos = parentName.rfind(
'_');
156 if (lastDashPos != std::string::npos)
158 auto indexStr = parentName.substr(lastDashPos + 1);
160 myIndex = std::stoi(indexStr);
161 }
catch(
const std::exception &e) {
162 gzwarn <<
"Failed to convert " << indexStr <<
" to integer: " << e.what() <<
", assuming 0\n";
168 gzerr <<
"Failed to parse parent name: " << parentName <<
"; could not determine our index\n";
172 if (sdf->HasElement(
"robotNamespace")) {
173 ns = sdf->Get<std::string>(
"robotNamespace");
175 if (!sdf->HasElement(
"ledCount")) {
176 gzerr <<
"ledCount is not set, but is required for the plugin to function correctly\n";
179 int totalLeds = sdf->Get<
int>(
"ledCount");
192 vptr->SetEmissive(emissive);
201 std::lock_guard<std::mutex> lock(registryMutex);
202 for(
const auto& led : req.leds)
204 if (led.index < registeredLeds.size()) {
205 auto color =
GazeboColor(led.r / 255.0f, led.g / 255.0f, led.b / 255.0f);
206 auto ledPlugin = registeredLeds[led.index];
207 if (ledPlugin) ledPlugin->SetColor(color);
208 ledState.leds[led.index].r = led.r;
209 ledState.leds[led.index].g = led.g;
210 ledState.leds[led.index].b = led.b;
213 statePublisher.publish(ledState);
220 std::lock_guard<std::mutex> lock(registryMutex);
221 for(
const auto& led : leds->leds)
223 if (led.index < registeredLeds.size())
225 auto color =
GazeboColor(led.r / 255.0f, led.g / 255.0f, led.b / 255.0f);
226 auto ledPlugin = registeredLeds[led.index];
227 if (ledPlugin) ledPlugin->SetColor(color);
LedController & get(std::string robotNamespace)
gazebo::rendering::VisualPtr vptr
#define ROS_INFO_NAMED(name,...)
#define ROS_DEBUG_STREAM_NAMED(name, args)
LedController: a class that provides ROS interface for the LEDs.
ros::ServiceServer setLedsSrv
void handleLedsMsg(const led_msgs::LEDStateArrayConstPtr &leds)
void unregisterPlugin(sim_led::LedVisualPlugin *plugin)
ROSCPP_DECL bool isInitialized()
Role
Role for the current controller.
led_msgs::LEDStateArray ledState
ROSCPP_DECL const std::string & getName()
std::unique_ptr< ros::NodeHandle > nh
#define ROS_DEBUG_NAMED(name,...)
GZ_REGISTER_VISUAL_PLUGIN(sim_led::LedVisualPlugin)
void publish(const boost::shared_ptr< M > &message) const
void SetColor(const GazeboColor &emissive)
gazebo::common::Color GazeboColor
std::string robotNamespace
bool setLeds(led_msgs::SetLEDs::Request &req, led_msgs::SetLEDs::Response &resp)
ros::Subscriber stateSubscriber
void registerPlugin(sim_led::LedVisualPlugin *plugin, int ledIdx=0, int totalLeds=0)
std::vector< sim_led::LedVisualPlugin * > registeredLeds
void Load(gazebo::rendering::VisualPtr visual, sdf::ElementPtr sdf) override
LedController(const std::string &robotNamespace)
#define ROS_FATAL_NAMED(name,...)
std::mutex controllerMutex
ros::Publisher statePublisher