Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00030
00031
00032 #include <cstdio>
00033 #include <vector>
00034 #include <list>
00035 #include "ros/console.h"
00036 #include "std_msgs/String.h"
00037 #include "topic_tools/MuxSelect.h"
00038 #include "topic_tools/MuxAdd.h"
00039 #include "topic_tools/MuxList.h"
00040 #include "topic_tools/MuxDelete.h"
00041 #include "topic_tools/shape_shifter.h"
00042 #include "topic_tools/parse.h"
00043 #include <nodelet/nodelet.h>
00044 #include <pluginlib/class_list_macros.h>
00045
00046 using std::string;
00047 using std::vector;
00048 using std::list;
00049 using namespace topic_tools;
00050
00051 const static string g_none_topic = "__none";
00052
00053 struct sub_info_t
00054 {
00055 ros::Subscriber sub;
00056 ShapeShifter* msg;
00057 };
00058
00059 class MuxNodelet : public nodelet::Nodelet
00060 {
00061 public:
00062 ros::NodeHandle g_node;
00063 ros::NodeHandle g_pnh;
00064 bool g_advertised;
00065 string g_output_topic;
00066 ros::Publisher g_pub;
00067 ros::Publisher g_pub_selected;
00068 list<struct sub_info_t> g_subs;
00069 list<struct sub_info_t>::iterator g_selected;
00070 ros::ServiceServer ss;
00071
00072 ros::ServiceServer ss_select;
00073 ros::ServiceServer ss_add;
00074 ros::ServiceServer ss_list;
00075 ros::ServiceServer ss_del;
00076
00077 MuxNodelet () : g_advertised(false), g_selected(g_subs.end())
00078 {}
00079
00080
00081 void onInit()
00082 {
00083
00084
00085
00086
00087
00088
00089
00090
00091 ros::NodeHandle mux_nh = getNodeHandle();
00092 ros::NodeHandle nh_priv = getPrivateNodeHandle();
00093 std::string topic_name = "output";
00094 nh_priv.param("topic_name", topic_name, topic_name);
00095
00096 ros::NodeHandle n;
00097 g_node = getMTNodeHandle();
00098 g_pnh = getMTPrivateNodeHandle();
00099 g_output_topic = topic_name;
00100
00101
00102
00103 g_pub_selected = nh_priv.advertise<std_msgs::String> (string("selected"), 1, true);
00104
00105
00106
00107 ss_select = nh_priv.advertiseService(string("select"), &MuxNodelet::sel_srv_cb, this);
00108 ss_add = nh_priv.advertiseService(string("add"), &MuxNodelet::add_topic_cb, this);
00109 ss_list = nh_priv.advertiseService(string("list"), &MuxNodelet::list_topic_cb, this);
00110 ss_del = nh_priv.advertiseService(string("delete"), &MuxNodelet::del_topic_cb, this);
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131 }
00132
00133 bool sel_srv_cb(topic_tools::MuxSelect::Request &req, topic_tools::MuxSelect::Response &res)
00134 {
00135 bool ret = false;
00136 if (g_selected != g_subs.end())
00137 res.prev_topic = g_selected->sub.getTopic();
00138 else
00139 res.prev_topic = string("");
00140
00141 if (req.topic == g_none_topic)
00142 {
00143 ROS_INFO("mux selected to no input.");
00144 g_selected = g_subs.end();
00145 ret = true;
00146 }
00147 else
00148 {
00149 ROS_INFO("trying to switch mux to %s", req.topic.c_str());
00150
00151 for (list<struct sub_info_t>::iterator it = g_subs.begin(); it != g_subs.end(); ++it)
00152 {
00153 if (ros::names::resolve(it->sub.getTopic()) == ros::names::resolve(req.topic))
00154 {
00155 g_selected = it;
00156 ROS_INFO("mux selected input: [%s]", it->sub.getTopic().c_str());
00157 ret = true;
00158 }
00159 }
00160 }
00161
00162 if (ret)
00163 {
00164 std_msgs::String t;
00165 t.data = req.topic;
00166 g_pub_selected.publish(t);
00167 }
00168
00169 return ret;
00170 }
00171
00172 bool sel_srv_cb_dep(topic_tools::MuxSelect::Request &req, topic_tools::MuxSelect::Response &res)
00173 {
00174 ROS_WARN("the <topic>_select service is deprecated; use mux/select instead");
00175 return sel_srv_cb(req, res);
00176 }
00177
00178 void in_cb(const boost::shared_ptr<ShapeShifter const>& msg, ShapeShifter* s)
00179 {
00180 if (!g_advertised)
00181 {
00182 ROS_INFO("advertising");
00183 g_pub = msg->advertise(g_pnh, g_output_topic, 10);
00184 g_advertised = true;
00185 }
00186 if (s == g_selected->msg)
00187 g_pub.publish(msg);
00188 }
00189
00190 bool list_topic_cb(topic_tools::MuxList::Request& req, topic_tools::MuxList::Response& res)
00191 {
00192 for (list<struct sub_info_t>::iterator it = g_subs.begin(); it != g_subs.end(); ++it)
00193 {
00194 res.topics.push_back(it->sub.getTopic());
00195 }
00196
00197 return true;
00198 }
00199
00200 bool add_topic_cb(topic_tools::MuxAdd::Request& req, topic_tools::MuxAdd::Response& res)
00201 {
00202
00203 ROS_INFO("trying to add %s to mux", req.topic.c_str());
00204
00205
00206
00207 if (req.topic == g_none_topic)
00208 {
00209 ROS_WARN("failed to add topic %s to mux, because it's reserved for special use", req.topic.c_str());
00210 return false;
00211 }
00212
00213
00214 for (list<struct sub_info_t>::iterator it = g_subs.begin(); it != g_subs.end(); ++it)
00215 {
00216 if (ros::names::resolve(it->sub.getTopic()) == ros::names::resolve(req.topic))
00217 {
00218 ROS_WARN("tried to add a topic that mux was already listening to: [%s]", it->sub.getTopic().c_str());
00219 return false;
00220 }
00221 }
00222
00223 struct sub_info_t sub_info;
00224 sub_info.msg = new ShapeShifter;
00225 try
00226 {
00227 sub_info.sub = g_node.subscribe<ShapeShifter> (req.topic, 10, boost::bind(&MuxNodelet::in_cb, this, _1, sub_info.msg));
00228 }
00229 catch (ros::InvalidNameException& e)
00230 {
00231 ROS_WARN("failed to add topic %s to mux, because it's an invalid name: %s", req.topic.c_str(), e.what());
00232 delete sub_info.msg;
00233 return false;
00234 }
00235 g_subs.push_back(sub_info);
00236
00237 ROS_INFO("added %s to mux", req.topic.c_str());
00238
00239 return true;
00240 }
00241
00242 bool del_topic_cb(topic_tools::MuxDelete::Request& req, topic_tools::MuxDelete::Response& res)
00243 {
00244
00245 ROS_INFO("trying to delete %s from mux", req.topic.c_str());
00246
00247 for (list<struct sub_info_t>::iterator it = g_subs.begin(); it != g_subs.end(); ++it)
00248 {
00249 if (ros::names::resolve(it->sub.getTopic()) == ros::names::resolve(req.topic))
00250 {
00251
00252 if (it == g_selected)
00253 {
00254 ROS_WARN("tried to delete currently selected topic %s from mux", req.topic.c_str());
00255 return false;
00256 }
00257 it->sub.shutdown();
00258 delete it->msg;
00259 g_subs.erase(it);
00260 ROS_INFO("deleted topic %s from mux", req.topic.c_str());
00261 return true;
00262 }
00263 }
00264
00265 ROS_WARN("tried to delete non-subscribed topic %s from mux", req.topic.c_str());
00266 return false;
00267 }
00268
00269 };
00270 PLUGINLIB_DECLARE_CLASS(starmac_tools, MuxNodelet, MuxNodelet, nodelet::Nodelet)
00271 ;
00272