Go to the documentation of this file.00001
00029 #include <iostream>
00030 #include <boost/thread.hpp>
00031 #include <boost/foreach.hpp>
00032
00033 #include <ros/ros.h>
00034 #include <geometry_msgs/Twist.h>
00035 #include <std_msgs/Int32.h>
00036
00037 using namespace std;
00038 using namespace ros;
00039
00040 #define foreach BOOST_FOREACH
00041
00042
00043
00044
00045
00046 volatile bool _enableOutput;
00047
00048 int _currentInput;
00049 int _currentOutput;
00050
00051 vector<Subscriber> _inputs;
00052 vector<Publisher> _outputs;
00053
00054 Subscriber _setInputSubscriber;
00055 Subscriber _setOutputSubscriber;
00056
00057 Publisher _currentInputPublisher;
00058 Publisher _currentOutputPublisher;
00059
00060 boost::thread* _velocityPublishThread;
00061 Timer _statusPublishTimer;
00062
00063 geometry_msgs::Twist _currentVelocity;
00064
00065
00066
00067
00068
00069 void onSetInputMessage(const std_msgs::Int32::ConstPtr inputIdMessage) {
00070 if (inputIdMessage->data >= 1 && inputIdMessage->data <= _inputs.size()) {
00071 _currentInput = inputIdMessage->data - 1;
00072 ROS_INFO("Current input changed to '#%i' ['%s']", inputIdMessage->data, _inputs[_currentInput].getTopic().c_str());
00073 }
00074 }
00075
00076 void onSetOutputMessage(const std_msgs::Int32::ConstPtr outputIdMessage) {
00077 if (outputIdMessage->data >= 1 && outputIdMessage->data <= _outputs.size()) {
00078 _currentOutput = outputIdMessage->data - 1;
00079 _enableOutput = true;
00080 ROS_INFO("Current output changed to '#%i' ['%s']", outputIdMessage->data, _outputs[_currentOutput].getTopic().c_str());
00081 }
00082
00083 if (outputIdMessage->data == 0) {
00084 _enableOutput = false;
00085 ROS_INFO("Current output changed to NONE [Disabled]");
00086 }
00087 }
00088
00089 void onInputVelocityMessage(const geometry_msgs::Twist::ConstPtr velocityMessage, int inputId) {
00090 if (inputId == _currentInput + 1)
00091 _currentVelocity = *velocityMessage;
00092 }
00093
00094
00095
00096
00097
00098 void publishStatus(TimerEvent timerEvent) {
00099 std_msgs::Int32 intMessage;
00100
00101 intMessage.data = _currentInput + 1;
00102 _currentInputPublisher.publish(intMessage);
00103
00104 intMessage.data = _currentOutput + 1;
00105 _currentOutputPublisher.publish(intMessage);
00106 }
00107
00108 void publishVelocity() {
00109 while (ros::ok()) {
00110
00111 if (_enableOutput)
00112 _outputs[_currentOutput].publish(_currentVelocity);
00113
00114 boost::this_thread::sleep(boost::posix_time::milliseconds(1000.0 / 20.0));
00115 }
00116 }
00117
00118 void createSubscribersAndPublishers(NodeHandle& node, map<string, string>& inputs, vector<string>& outputs) {
00122 int inputId = 1;
00123 ROS_INFO("[Preparing inputs]");
00124 pair<string, string> input;
00125 foreach (input, inputs) {
00126 ROS_INFO(" - Setting up input topic #%i: %s", inputId, input.second.c_str());
00127
00128 _inputs.push_back(node.subscribe<geometry_msgs::Twist>
00129 (input.second, 100, boost::bind(onInputVelocityMessage, _1, inputId++)));
00130 }
00131
00135 int outputId = 1;
00136 ROS_INFO("[Preparing outputs]");
00137 foreach (string output, outputs) {
00138 ROS_INFO(" - Setting up output topic #%i: %s", outputId++, output.c_str());
00139
00140 _outputs.push_back(node.advertise<geometry_msgs::Twist>(output, 1, false));
00141 }
00142
00146 _setInputSubscriber = node.subscribe("/velocity_dispatcher/set_input", 1, onSetInputMessage);
00147 _setOutputSubscriber = node.subscribe("/velocity_dispatcher/set_output", 1, onSetOutputMessage);
00148
00152 _currentInputPublisher = node.advertise<std_msgs::Int32>("/velocity_dispatcher/current_input", 1, true);
00153 _currentOutputPublisher = node.advertise<std_msgs::Int32>("/velocity_dispatcher/current_output", 1, true);
00154
00158 _statusPublishTimer = node.createTimer(Duration(1), boost::bind(publishStatus, _1));
00159 _velocityPublishThread = new boost::thread(publishVelocity);
00160 }
00161
00162 bool setupInputOutput(NodeHandle& node) {
00163
00164 map<string, string> inputTopics;
00165 vector<string> outputTopics;
00166
00167 if (node.hasParam("/mr_teleoperator/input_topics"))
00168 node.getParam("/mr_teleoperator/input_topics", inputTopics);
00169 else {
00170 ROS_ERROR("No input topics provided");
00171 return false;
00172 }
00173
00174 if (node.hasParam("/mr_teleoperator/output_topics"))
00175 node.getParam("/mr_teleoperator/output_topics", outputTopics);
00176 else {
00177 ROS_ERROR("No output topics provided");
00178 return false;
00179 }
00180
00181 _enableOutput = true;
00182 _currentInput = 0;
00183 _currentOutput = 0;
00184
00185 createSubscribersAndPublishers(node, inputTopics, outputTopics);
00186
00187 return true;
00188
00189 }
00190
00191
00192
00193
00194
00195 int main(int argc, char **argv) {
00196 init(argc, argv, "velocity_dispatcher");
00197
00198 NodeHandle node;
00199
00200 if (!setupInputOutput(node))
00201 return 1;
00202
00203 spin();
00204 return 0;
00205 }
00206
00207