vrpn_client_ros.cpp
Go to the documentation of this file.
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 }  // namespace vrpn_client_ros


vrpn_client_ros
Author(s): Paul Bovbel
autogenerated on Thu Jun 6 2019 18:13:13