00001
00032 #include "vrpn_client_ros/vrpn_client_ros.h"
00033
00034 #include "tf2/LinearMath/Quaternion.h"
00035 #include "tf2/LinearMath/Matrix3x3.h"
00036 #include "tf2_ros/transform_broadcaster.h"
00037
00038 #include <vector>
00039 #include <unordered_set>
00040
00041 namespace
00042 {
00043 std::unordered_set<std::string> name_blacklist_({"VRPN Control"});
00044 }
00045
00046 namespace vrpn_client_ros
00047 {
00048
00049 VrpnTrackerRos::VrpnTrackerRos(std::string tracker_name, ConnectionPtr connection, ros::NodeHandle nh)
00050 {
00051 tracker_remote_ = std::make_shared<vrpn_Tracker_Remote>(tracker_name.c_str(), connection.get());
00052 init(tracker_name, nh, false);
00053 }
00054
00055 VrpnTrackerRos::VrpnTrackerRos(std::string tracker_name, std::string host, ros::NodeHandle nh)
00056 {
00057 std::string tracker_address;
00058 tracker_address = tracker_name + "@" + host;
00059 tracker_remote_ = std::make_shared<vrpn_Tracker_Remote>(tracker_address.c_str());
00060 init(tracker_name, nh, true);
00061 }
00062
00063 void VrpnTrackerRos::init(std::string tracker_name, ros::NodeHandle nh, bool create_mainloop_timer)
00064 {
00065 ROS_INFO_STREAM("Creating new tracker " << tracker_name);
00066
00067 tracker_remote_->register_change_handler(this, &VrpnTrackerRos::handle_pose);
00068 tracker_remote_->register_change_handler(this, &VrpnTrackerRos::handle_twist);
00069 tracker_remote_->register_change_handler(this, &VrpnTrackerRos::handle_accel);
00070 tracker_remote_->shutup = true;
00071
00072 std::string error;
00073 if (!ros::names::validate(tracker_name, error))
00074 {
00075 ROS_ERROR_STREAM("Invalid tracker name " << tracker_name << ", not creating topics : " << error);
00076 return;
00077 }
00078
00079 this->tracker_name = tracker_name;
00080
00081 output_nh_ = ros::NodeHandle(nh, tracker_name);
00082
00083 std::string frame_id;
00084 nh.param<std::string>("frame_id", frame_id, "world");
00085 nh.param<bool>("use_server_time", use_server_time_, false);
00086 nh.param<bool>("broadcast_tf", broadcast_tf_, false);
00087 nh.param<bool>("process_sensor_id", process_sensor_id_, false);
00088
00089 pose_msg_.header.frame_id = twist_msg_.header.frame_id = accel_msg_.header.frame_id = transform_stamped_.header.frame_id = frame_id;
00090
00091 if (create_mainloop_timer)
00092 {
00093 double update_frequency;
00094 nh.param<double>("update_frequency", update_frequency, 100.0);
00095 mainloop_timer = nh.createTimer(ros::Duration(1 / update_frequency),
00096 boost::bind(&VrpnTrackerRos::mainloop, this));
00097 }
00098 }
00099
00100 VrpnTrackerRos::~VrpnTrackerRos()
00101 {
00102 ROS_INFO_STREAM("Destroying tracker " << transform_stamped_.child_frame_id);
00103 tracker_remote_->unregister_change_handler(this, &VrpnTrackerRos::handle_pose);
00104 tracker_remote_->unregister_change_handler(this, &VrpnTrackerRos::handle_twist);
00105 tracker_remote_->unregister_change_handler(this, &VrpnTrackerRos::handle_accel);
00106 }
00107
00108 void VrpnTrackerRos::mainloop()
00109 {
00110 tracker_remote_->mainloop();
00111 }
00112
00113 void VRPN_CALLBACK VrpnTrackerRos::handle_pose(void *userData, const vrpn_TRACKERCB tracker_pose)
00114 {
00115 VrpnTrackerRos *tracker = static_cast<VrpnTrackerRos *>(userData);
00116
00117 ros::Publisher *pose_pub;
00118 std::size_t sensor_index(0);
00119 ros::NodeHandle nh = tracker->output_nh_;
00120
00121 if (tracker->process_sensor_id_)
00122 {
00123 sensor_index = static_cast<std::size_t>(tracker_pose.sensor);
00124 nh = ros::NodeHandle(tracker->output_nh_, std::to_string(tracker_pose.sensor));
00125 }
00126
00127 if (tracker->pose_pubs_.size() <= sensor_index)
00128 {
00129 tracker->pose_pubs_.resize(sensor_index + 1);
00130 }
00131 pose_pub = &(tracker->pose_pubs_[sensor_index]);
00132
00133 if (pose_pub->getTopic().empty())
00134 {
00135 *pose_pub = nh.advertise<geometry_msgs::PoseStamped>("pose", 1);
00136 }
00137
00138 if (pose_pub->getNumSubscribers() > 0)
00139 {
00140 if (tracker->use_server_time_)
00141 {
00142 tracker->pose_msg_.header.stamp.sec = tracker_pose.msg_time.tv_sec;
00143 tracker->pose_msg_.header.stamp.nsec = tracker_pose.msg_time.tv_usec * 1000;
00144 }
00145 else
00146 {
00147 tracker->pose_msg_.header.stamp = ros::Time::now();
00148 }
00149
00150 tracker->pose_msg_.pose.position.x = tracker_pose.pos[0];
00151 tracker->pose_msg_.pose.position.y = tracker_pose.pos[1];
00152 tracker->pose_msg_.pose.position.z = tracker_pose.pos[2];
00153
00154 tracker->pose_msg_.pose.orientation.x = tracker_pose.quat[0];
00155 tracker->pose_msg_.pose.orientation.y = tracker_pose.quat[1];
00156 tracker->pose_msg_.pose.orientation.z = tracker_pose.quat[2];
00157 tracker->pose_msg_.pose.orientation.w = tracker_pose.quat[3];
00158
00159 pose_pub->publish(tracker->pose_msg_);
00160 }
00161
00162 if (tracker->broadcast_tf_)
00163 {
00164 static tf2_ros::TransformBroadcaster tf_broadcaster;
00165
00166 if (tracker->use_server_time_)
00167 {
00168 tracker->transform_stamped_.header.stamp.sec = tracker_pose.msg_time.tv_sec;
00169 tracker->transform_stamped_.header.stamp.nsec = tracker_pose.msg_time.tv_usec * 1000;
00170 }
00171 else
00172 {
00173 tracker->transform_stamped_.header.stamp = ros::Time::now();
00174 }
00175
00176 if (tracker->process_sensor_id_)
00177 {
00178 tracker->transform_stamped_.child_frame_id = tracker->tracker_name + "/" + std::to_string(tracker_pose.sensor);
00179 }
00180 else
00181 {
00182 tracker->transform_stamped_.child_frame_id = tracker->tracker_name;
00183 }
00184
00185 tracker->transform_stamped_.transform.translation.x = tracker_pose.pos[0];
00186 tracker->transform_stamped_.transform.translation.y = tracker_pose.pos[1];
00187 tracker->transform_stamped_.transform.translation.z = tracker_pose.pos[2];
00188
00189 tracker->transform_stamped_.transform.rotation.x = tracker_pose.quat[0];
00190 tracker->transform_stamped_.transform.rotation.y = tracker_pose.quat[1];
00191 tracker->transform_stamped_.transform.rotation.z = tracker_pose.quat[2];
00192 tracker->transform_stamped_.transform.rotation.w = tracker_pose.quat[3];
00193
00194 tf_broadcaster.sendTransform(tracker->transform_stamped_);
00195 }
00196 }
00197
00198 void VRPN_CALLBACK VrpnTrackerRos::handle_twist(void *userData, const vrpn_TRACKERVELCB tracker_twist)
00199 {
00200 VrpnTrackerRos *tracker = static_cast<VrpnTrackerRos *>(userData);
00201
00202 ros::Publisher *twist_pub;
00203 std::size_t sensor_index(0);
00204 ros::NodeHandle nh = tracker->output_nh_;
00205
00206 if (tracker->process_sensor_id_)
00207 {
00208 sensor_index = static_cast<std::size_t>(tracker_twist.sensor);
00209 nh = ros::NodeHandle(tracker->output_nh_, std::to_string(tracker_twist.sensor));
00210 }
00211
00212 if (tracker->twist_pubs_.size() <= sensor_index)
00213 {
00214 tracker->twist_pubs_.resize(sensor_index + 1);
00215 }
00216 twist_pub = &(tracker->twist_pubs_[sensor_index]);
00217
00218 if (twist_pub->getTopic().empty())
00219 {
00220 *twist_pub = nh.advertise<geometry_msgs::TwistStamped>("twist", 1);
00221 }
00222
00223 if (twist_pub->getNumSubscribers() > 0)
00224 {
00225 if (tracker->use_server_time_)
00226 {
00227 tracker->twist_msg_.header.stamp.sec = tracker_twist.msg_time.tv_sec;
00228 tracker->twist_msg_.header.stamp.nsec = tracker_twist.msg_time.tv_usec * 1000;
00229 }
00230 else
00231 {
00232 tracker->twist_msg_.header.stamp = ros::Time::now();
00233 }
00234
00235 tracker->twist_msg_.twist.linear.x = tracker_twist.vel[0];
00236 tracker->twist_msg_.twist.linear.y = tracker_twist.vel[1];
00237 tracker->twist_msg_.twist.linear.z = tracker_twist.vel[2];
00238
00239 double roll, pitch, yaw;
00240 tf2::Matrix3x3 rot_mat(
00241 tf2::Quaternion(tracker_twist.vel_quat[0], tracker_twist.vel_quat[1], tracker_twist.vel_quat[2],
00242 tracker_twist.vel_quat[3]));
00243 rot_mat.getRPY(roll, pitch, yaw);
00244
00245 tracker->twist_msg_.twist.angular.x = roll;
00246 tracker->twist_msg_.twist.angular.y = pitch;
00247 tracker->twist_msg_.twist.angular.z = yaw;
00248
00249 twist_pub->publish(tracker->twist_msg_);
00250 }
00251 }
00252
00253 void VRPN_CALLBACK VrpnTrackerRos::handle_accel(void *userData, const vrpn_TRACKERACCCB tracker_accel)
00254 {
00255 VrpnTrackerRos *tracker = static_cast<VrpnTrackerRos *>(userData);
00256
00257 ros::Publisher *accel_pub;
00258 std::size_t sensor_index(0);
00259 ros::NodeHandle nh = tracker->output_nh_;
00260
00261 if (tracker->process_sensor_id_)
00262 {
00263 sensor_index = static_cast<std::size_t>(tracker_accel.sensor);
00264 nh = ros::NodeHandle(tracker->output_nh_, std::to_string(tracker_accel.sensor));
00265 }
00266
00267 if (tracker->accel_pubs_.size() <= sensor_index)
00268 {
00269 tracker->accel_pubs_.resize(sensor_index + 1);
00270 }
00271 accel_pub = &(tracker->accel_pubs_[sensor_index]);
00272
00273 if (accel_pub->getTopic().empty())
00274 {
00275 *accel_pub = nh.advertise<geometry_msgs::TwistStamped>("accel", 1);
00276 }
00277
00278 if (accel_pub->getNumSubscribers() > 0)
00279 {
00280 if (tracker->use_server_time_)
00281 {
00282 tracker->accel_msg_.header.stamp.sec = tracker_accel.msg_time.tv_sec;
00283 tracker->accel_msg_.header.stamp.nsec = tracker_accel.msg_time.tv_usec * 1000;
00284 }
00285 else
00286 {
00287 tracker->accel_msg_.header.stamp = ros::Time::now();
00288 }
00289
00290 tracker->accel_msg_.accel.linear.x = tracker_accel.acc[0];
00291 tracker->accel_msg_.accel.linear.y = tracker_accel.acc[1];
00292 tracker->accel_msg_.accel.linear.z = tracker_accel.acc[2];
00293
00294 double roll, pitch, yaw;
00295 tf2::Matrix3x3 rot_mat(
00296 tf2::Quaternion(tracker_accel.acc_quat[0], tracker_accel.acc_quat[1], tracker_accel.acc_quat[2],
00297 tracker_accel.acc_quat[3]));
00298 rot_mat.getRPY(roll, pitch, yaw);
00299
00300 tracker->accel_msg_.accel.angular.x = roll;
00301 tracker->accel_msg_.accel.angular.y = pitch;
00302 tracker->accel_msg_.accel.angular.z = yaw;
00303
00304 accel_pub->publish(tracker->accel_msg_);
00305 }
00306 }
00307
00308 VrpnClientRos::VrpnClientRos(ros::NodeHandle nh, ros::NodeHandle private_nh)
00309 {
00310 output_nh_ = private_nh;
00311
00312 host_ = getHostStringFromParams(private_nh);
00313
00314 ROS_INFO_STREAM("Connecting to VRPN server at " << host_);
00315 connection_ = std::shared_ptr<vrpn_Connection>(vrpn_get_connection_by_name(host_.c_str()));
00316 ROS_INFO("Connection established");
00317
00318 double update_frequency;
00319 private_nh.param<double>("update_frequency", update_frequency, 100.0);
00320 mainloop_timer = nh.createTimer(ros::Duration(1 / update_frequency), boost::bind(&VrpnClientRos::mainloop, this));
00321
00322 double refresh_tracker_frequency;
00323 private_nh.param<double>("refresh_tracker_frequency", refresh_tracker_frequency, 0.0);
00324
00325 if (refresh_tracker_frequency > 0.0)
00326 {
00327 refresh_tracker_timer_ = nh.createTimer(ros::Duration(1 / refresh_tracker_frequency),
00328 boost::bind(&VrpnClientRos::updateTrackers, this));
00329 }
00330
00331 std::vector<std::string> param_tracker_names_;
00332 if (private_nh.getParam("trackers", param_tracker_names_))
00333 {
00334 for (std::vector<std::string>::iterator it = param_tracker_names_.begin();
00335 it != param_tracker_names_.end(); ++it)
00336 {
00337 trackers_.insert(std::make_pair(*it, std::make_shared<VrpnTrackerRos>(*it, connection_, output_nh_)));
00338 }
00339 }
00340 }
00341
00342 std::string VrpnClientRos::getHostStringFromParams(ros::NodeHandle host_nh)
00343 {
00344 std::stringstream host_stream;
00345 std::string server;
00346 int port;
00347
00348 host_nh.param<std::string>("server", server, "localhost");
00349 host_stream << server;
00350
00351 if (host_nh.getParam("port", port))
00352 {
00353 host_stream << ":" << port;
00354 }
00355 return host_stream.str();
00356 }
00357
00358 void VrpnClientRos::mainloop()
00359 {
00360 connection_->mainloop();
00361 if (!connection_->doing_okay())
00362 {
00363 ROS_WARN("VRPN connection is not 'doing okay'");
00364 }
00365 for (TrackerMap::iterator it = trackers_.begin(); it != trackers_.end(); ++it)
00366 {
00367 it->second->mainloop();
00368 }
00369 }
00370
00371 void VrpnClientRos::updateTrackers()
00372 {
00373 int i = 0;
00374 while (connection_->sender_name(i) != NULL)
00375 {
00376 if (trackers_.count(connection_->sender_name(i)) == 0 && name_blacklist_.count(connection_->sender_name(i)) == 0)
00377 {
00378 ROS_INFO_STREAM("Found new sender: " << connection_->sender_name(i));
00379 trackers_.insert(std::make_pair(connection_->sender_name(i),
00380 std::make_shared<VrpnTrackerRos>(connection_->sender_name(i), connection_,
00381 output_nh_)));
00382 }
00383 i++;
00384 }
00385 }
00386 }