vicon_bridge.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Copyright (c) 2010, UC Regents
00005  *  Copyright (c) 2011, Markus Achtelik, ETH Zurich, Autonomous Systems Lab (modifications)
00006  *  All rights reserved.
00007  *
00008  *  Redistribution and use in source and binary forms, with or without
00009  *  modification, are permitted provided that the following conditions
00010  *  are met:
00011  *
00012  *   * Redistributions of source code must retain the above copyright
00013  *     notice, this list of conditions and the following disclaimer.
00014  *   * Redistributions in binary form must reproduce the above
00015  *     copyright notice, this list of conditions and the following
00016  *     disclaimer in the documentation and/or other materials provided
00017  *     with the distribution.
00018  *   * Neither the name of the University of California nor the names of its
00019  *     contributors may be used to endorse or promote products derived
00020  *     from this software without specific prior written permission.
00021  *
00022  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00023  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00024  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00025  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00026  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00027  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00028  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00029  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00030  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00031  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00032  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00033  *  POSSIBILITY OF SUCH DAMAGE.
00034  *********************************************************************/
00035 
00036 #include <Client.h>
00037 #include <ros/ros.h>
00038 #include <diagnostic_updater/diagnostic_updater.h>
00039 #include <diagnostic_updater/update_functions.h>
00040 #include <tf/tf.h>
00041 #include <tf/transform_broadcaster.h>
00042 #include <geometry_msgs/TransformStamped.h>
00043 #include <vicon_bridge/viconGrabPose.h>
00044 #include <iostream>
00045 
00046 #include <vicon_bridge/Markers.h>
00047 #include <vicon_bridge/Marker.h>
00048 
00049 #include "msvc_bridge.h"
00050 #include <map>
00051 #include <boost/thread.hpp>
00052 #include <vicon_bridge/viconCalibrateSegment.h>
00053 #include <tf/transform_listener.h>
00054 
00055 using std::min;
00056 using std::max;
00057 using std::string;
00058 using std::map;
00059 
00060 using namespace ViconDataStreamSDK::CPP;
00061 
00062 string Adapt(const Direction::Enum i_Direction)
00063 {
00064   switch (i_Direction)
00065   {
00066     case Direction::Forward:
00067       return "Forward";
00068     case Direction::Backward:
00069       return "Backward";
00070     case Direction::Left:
00071       return "Left";
00072     case Direction::Right:
00073       return "Right";
00074     case Direction::Up:
00075       return "Up";
00076     case Direction::Down:
00077       return "Down";
00078     default:
00079       return "Unknown";
00080   }
00081 }
00082 
00083 string Adapt(const Result::Enum i_result)
00084 {
00085   switch (i_result)
00086   {
00087     case Result::ClientAlreadyConnected:
00088       return "ClientAlreadyConnected";
00089     case Result::ClientConnectionFailed:
00090       return "";
00091     case Result::CoLinearAxes:
00092       return "CoLinearAxes";
00093     case Result::InvalidDeviceName:
00094       return "InvalidDeviceName";
00095     case Result::InvalidDeviceOutputName:
00096       return "InvalidDeviceOutputName";
00097     case Result::InvalidHostName:
00098       return "InvalidHostName";
00099     case Result::InvalidIndex:
00100       return "InvalidIndex";
00101     case Result::InvalidLatencySampleName:
00102       return "InvalidLatencySampleName";
00103     case Result::InvalidMarkerName:
00104       return "InvalidMarkerName";
00105     case Result::InvalidMulticastIP:
00106       return "InvalidMulticastIP";
00107     case Result::InvalidSegmentName:
00108       return "InvalidSegmentName";
00109     case Result::InvalidSubjectName:
00110       return "InvalidSubjectName";
00111     case Result::LeftHandedAxes:
00112       return "LeftHandedAxes";
00113     case Result::NoFrame:
00114       return "NoFrame";
00115     case Result::NotConnected:
00116       return "NotConnected";
00117     case Result::NotImplemented:
00118       return "NotImplemented";
00119     case Result::ServerAlreadyTransmittingMulticast:
00120       return "ServerAlreadyTransmittingMulticast";
00121     case Result::ServerNotTransmittingMulticast:
00122       return "ServerNotTransmittingMulticast";
00123     case Result::Success:
00124       return "Success";
00125     case Result::Unknown:
00126       return "Unknown";
00127     default:
00128       return "unknown";
00129   }
00130 }
00131 
00132 class SegmentPublisher
00133 {
00134 public:
00135   ros::Publisher pub;
00136   bool is_ready;
00137   tf::Transform calibration_pose;
00138   bool calibrated;
00139   SegmentPublisher() :
00140     is_ready(false), calibration_pose(tf::Pose::getIdentity()),
00141         calibrated(false)
00142   {
00143   }
00144   ;
00145 };
00146 
00147 typedef map<string, SegmentPublisher> SegmentMap;
00148 
00149 class ViconReceiver
00150 {
00151 private:
00152   ros::NodeHandle nh;
00153   ros::NodeHandle nh_priv;
00154   // Diagnostic Updater
00155   diagnostic_updater::Updater diag_updater;
00156   double min_freq_;
00157   double max_freq_;
00158   diagnostic_updater::FrequencyStatus freq_status_;
00159   // Parameters:
00160   string stream_mode_;
00161   string host_name_;
00162   string tf_ref_frame_id_;
00163   string tracked_frame_suffix_;
00164   // Publisher
00165   ros::Publisher marker_pub_;
00166   // TF Broadcaster
00167   tf::TransformBroadcaster tf_broadcaster_;
00168   //geometry_msgs::PoseStamped vicon_pose;
00169   tf::Transform flyer_transform;
00170   ros::Time now_time;
00171   // TODO: Make the following configurable:
00172   ros::ServiceServer m_grab_vicon_pose_service_server;
00173   ros::ServiceServer calibrate_segment_server_;
00174   //  ViconDataStreamSDK::CPP::Client MyClient;
00175   unsigned int lastFrameNumber;
00176   unsigned int frameCount;
00177   unsigned int droppedFrameCount;
00178   ros::Time time_datum;
00179   unsigned int frame_datum;
00180   unsigned int n_markers;
00181   unsigned int n_unlabeled_markers;
00182   bool segment_data_enabled;
00183   bool marker_data_enabled;
00184   bool unlabeled_marker_data_enabled;
00185 
00186   bool grab_frames_;
00187   boost::thread grab_frames_thread_;
00188   SegmentMap segment_publishers_;
00189   boost::mutex segments_mutex_;
00190   std::vector<std::string> time_log_;
00191 
00192 public:
00193   void startGrabbing()
00194   {
00195     grab_frames_ = true;
00196     // test grabbing in the main loop and run an asynchronous spinner instead
00197     grabThread();
00198     //grab_frames_thread_ = boost::thread(&ViconReceiver::grabThread, this);
00199   }
00200 
00201   void stopGrabbing()
00202   {
00203     grab_frames_ = false;
00204     //grab_frames_thread_.join();
00205   }
00206 
00207   ViconReceiver() :
00208     nh_priv("~"), diag_updater(), min_freq_(0.1), max_freq_(1000),
00209         freq_status_(diagnostic_updater::FrequencyStatusParam(&min_freq_, &max_freq_)), stream_mode_("ClientPull"),
00210         host_name_(""), tf_ref_frame_id_("/world"), tracked_frame_suffix_("vicon"),
00211         lastFrameNumber(0), frameCount(0), droppedFrameCount(0), frame_datum(0), n_markers(0), n_unlabeled_markers(0),
00212         marker_data_enabled(false), unlabeled_marker_data_enabled(false), grab_frames_(false)
00213 
00214   {
00215     // Diagnostics
00216     diag_updater.add("ViconReceiver Status", this, &ViconReceiver::diagnostics);
00217     diag_updater.add(freq_status_);
00218     diag_updater.setHardwareID("none");
00219     diag_updater.force_update();
00220     // Parameters
00221     nh_priv.param("stream_mode", stream_mode_, stream_mode_);
00222     nh_priv.param("datastream_hostport", host_name_, host_name_);
00223     nh_priv.param("tf_ref_frame_id", tf_ref_frame_id_, tf_ref_frame_id_);
00224     ROS_ASSERT(init_vicon());
00225     // Service Server
00226     ROS_INFO("setting up grab_vicon_pose service server ... ");
00227     m_grab_vicon_pose_service_server = nh_priv.advertiseService("grab_vicon_pose", &ViconReceiver::grabPoseCallback,
00228                                                                 this);
00229 
00230     ROS_INFO("setting up segment calibration service server ... ");
00231     calibrate_segment_server_ = nh_priv.advertiseService("calibrate_segment", &ViconReceiver::calibrateSegmentCallback,
00232                                                          this);
00233 
00234     // Publishers
00235     marker_pub_ = nh.advertise<vicon_bridge::Markers> (tracked_frame_suffix_ + "/markers", 10);
00236     startGrabbing();
00237   }
00238 
00239   ~ViconReceiver()
00240   {
00241     for (size_t i = 0; i < time_log_.size(); i++)
00242     {
00243       std::cout << time_log_[i] << std::endl;
00244     }
00245     ROS_ASSERT(shutdown_vicon());
00246   }
00247 
00248 private:
00249   void diagnostics(diagnostic_updater::DiagnosticStatusWrapper& stat)
00250   {
00251     stat.summary(diagnostic_msgs::DiagnosticStatus::OK, "OK");
00252     stat.add("latest VICON frame number", lastFrameNumber);
00253     stat.add("dropped frames", droppedFrameCount);
00254     stat.add("framecount", frameCount);
00255     stat.add("# markers", n_markers);
00256     stat.add("# unlabeled markers", n_unlabeled_markers);
00257   }
00258 
00259   bool init_vicon()
00260   {
00261     ROS_INFO_STREAM("Connecting to Vicon DataStream SDK at " << host_name_ << " ...");
00262 
00263     ros::Duration d(1);
00264     Result::Enum result(Result::Unknown);
00265 
00266     while (!msvcbridge::IsConnected().Connected)
00267     {
00268       msvcbridge::Connect(host_name_);
00269       ROS_INFO(".");
00270       d.sleep();
00271       ros::spinOnce();
00272       if (!ros::ok())
00273         return false;
00274     }
00275     ROS_ASSERT(msvcbridge::IsConnected().Connected);
00276     ROS_INFO_STREAM("... connected!");
00277 
00278     // ClientPullPrefetch doesn't make much sense here, since we're only forwarding the data
00279     if (stream_mode_ == "ServerPush")
00280     {
00281       result = msvcbridge::SetStreamMode(StreamMode::ServerPush).Result;
00282     }
00283     else if (stream_mode_ == "ClientPull")
00284     {
00285       result = msvcbridge::SetStreamMode(StreamMode::ClientPull).Result;
00286     }
00287     else
00288     {
00289       ROS_FATAL("Unknown stream mode -- options are ServerPush, ClientPull");
00290       ros::shutdown();
00291     }
00292 
00293     ROS_INFO_STREAM("Setting Stream Mode to " << stream_mode_<< ": "<< Adapt(result));
00294 
00295     msvcbridge::SetAxisMapping(Direction::Forward, Direction::Left, Direction::Up); // 'Z-up'
00296     Output_GetAxisMapping _Output_GetAxisMapping = msvcbridge::GetAxisMapping();
00297 
00298     ROS_INFO_STREAM("Axis Mapping: X-" << Adapt(_Output_GetAxisMapping.XAxis) << " Y-"
00299         << Adapt(_Output_GetAxisMapping.YAxis) << " Z-" << Adapt(_Output_GetAxisMapping.ZAxis));
00300 
00301     msvcbridge::EnableSegmentData();
00302     ROS_ASSERT(msvcbridge::IsSegmentDataEnabled().Enabled);
00303 
00304     Output_GetVersion _Output_GetVersion = msvcbridge::GetVersion();
00305     ROS_INFO_STREAM("Version: " << _Output_GetVersion.Major << "." << _Output_GetVersion.Minor << "."
00306         << _Output_GetVersion.Point);
00307     return true;
00308   }
00309 
00310   void createSegmentThread(const string subject_name, const string segment_name)
00311   {
00312     ROS_INFO("creating new object %s/%s ...",subject_name.c_str(), segment_name.c_str() );
00313     boost::mutex::scoped_lock lock(segments_mutex_);
00314     SegmentPublisher & spub = segment_publishers_[subject_name + "/" + segment_name];
00315 
00316     // we don't need the lock anymore, since rest is protected by is_ready
00317     lock.unlock();
00318 
00319     spub.pub = nh.advertise<geometry_msgs::TransformStamped> (tracked_frame_suffix_ + "/" + subject_name + "/"
00320         + segment_name, 10);
00321 
00322     // try to get zero pose from parameter server
00323     string param_suffix(subject_name + "/" + segment_name + "/zero_pose/");
00324     double qw, qx, qy, qz, x, y, z;
00325     bool have_params = true;
00326     have_params = have_params && nh_priv.getParam(param_suffix + "orientation/w", qw);
00327     have_params = have_params && nh_priv.getParam(param_suffix + "orientation/x", qx);
00328     have_params = have_params && nh_priv.getParam(param_suffix + "orientation/y", qy);
00329     have_params = have_params && nh_priv.getParam(param_suffix + "orientation/z", qz);
00330     have_params = have_params && nh_priv.getParam(param_suffix + "position/x", x);
00331     have_params = have_params && nh_priv.getParam(param_suffix + "position/y", y);
00332     have_params = have_params && nh_priv.getParam(param_suffix + "position/z", z);
00333 
00334     if (have_params)
00335     {
00336       ROS_INFO("loaded zero pose for %s/%s", subject_name.c_str(), segment_name.c_str());
00337       spub.calibration_pose.setRotation(tf::Quaternion(qx, qy, qz, qw));
00338       spub.calibration_pose.setOrigin(tf::Vector3(x, y, z));
00339       spub.calibration_pose = spub.calibration_pose.inverse();
00340     }
00341     else
00342     {
00343       ROS_WARN("unable to load zero pose for %s/%s", subject_name.c_str(), segment_name.c_str());
00344       spub.calibration_pose.setIdentity();
00345     }
00346 
00347     spub.is_ready = true;
00348     ROS_INFO("... done, advertised as \" %s/%s/%s\" ", tracked_frame_suffix_.c_str(), subject_name.c_str(), segment_name.c_str());
00349 
00350   }
00351 
00352   void createSegment(const string subject_name, const string segment_name)
00353   {
00354     boost::thread(&ViconReceiver::createSegmentThread, this, subject_name, segment_name);
00355   }
00356 
00357   void grabThread()
00358   {
00359     ros::Duration d(1.0 / 240.0);
00360 //    ros::Time last_time = ros::Time::now();
00361 //    double fps = 100.;
00362 //    ros::Duration diff;
00363 //    std::stringstream time_log;
00364     while (ros::ok() && grab_frames_)
00365     {
00366       while (msvcbridge::GetFrame().Result != Result::Success && ros::ok())
00367       {
00368         ROS_INFO("getFrame returned false");
00369         d.sleep();
00370       }
00371       now_time = ros::Time::now();
00372 //      diff = now_time-last_time;
00373 //      fps = 1.0/(0.9/fps + 0.1*diff.toSec());
00374 //      time_log.clear();
00375 //      time_log.str("");
00376 //      time_log <<"timings: dt="<<diff<<" fps=" <<fps;
00377 //      time_log_.push_back(time_log.str());
00378 //      last_time = now_time;
00379 
00380       bool was_new_frame = process_frame();
00381       ROS_WARN_COND(!was_new_frame, "grab frame returned false");
00382 
00383       diag_updater.update();
00384     }
00385   }
00386 
00387   bool shutdown_vicon()
00388   {
00389     ROS_INFO_STREAM("stopping grabbing thread");
00390     stopGrabbing();
00391     ROS_INFO_STREAM("Disconnecting from Vicon DataStream SDK");
00392     msvcbridge::Disconnect();
00393     ROS_ASSERT(!msvcbridge::IsConnected().Connected);
00394     ROS_INFO_STREAM("... disconnected.");
00395     return true;
00396   }
00397 
00398   bool process_frame()
00399   {
00400     static ros::Time lastTime;
00401     Output_GetFrameNumber OutputFrameNum = msvcbridge::GetFrameNumber();
00402 
00403     //frameCount++;
00404     //ROS_INFO_STREAM("Grabbed a frame: " << OutputFrameNum.FrameNumber);
00405     int frameDiff = 0;
00406     if (lastFrameNumber != 0)
00407     {
00408       frameDiff = OutputFrameNum.FrameNumber - lastFrameNumber;
00409       frameCount += frameDiff;
00410       if ((frameDiff) > 1)
00411       {
00412         droppedFrameCount += frameDiff;
00413         double droppedFramePct = (double)droppedFrameCount / frameCount * 100;
00414         ROS_DEBUG_STREAM(frameDiff << " more (total " << droppedFrameCount << "/" << frameCount << ", "
00415             << droppedFramePct << "%) frame(s) dropped. Consider adjusting rates.");
00416       }
00417     }
00418     lastFrameNumber = OutputFrameNum.FrameNumber;
00419 
00420     if (frameDiff == 0)
00421     {
00422       return false;
00423     }
00424     else
00425     {
00426       freq_status_.tick();
00427       ros::Duration vicon_latency(msvcbridge::GetLatencyTotal().Total);
00428 
00429       process_subjects(now_time - vicon_latency);
00430       process_markers(now_time - vicon_latency, lastFrameNumber);
00431 
00432       lastTime = now_time;
00433       return true;
00434     }
00435   }
00436 
00437   void process_subjects(const ros::Time& frame_time)
00438   {
00439     string tracked_frame, subject_name, segment_name;
00440     unsigned int n_subjects = msvcbridge::GetSubjectCount().SubjectCount;
00441     SegmentMap::iterator pub_it;
00442     tf::Transform transform;
00443     std::vector<tf::StampedTransform, std::allocator<tf::StampedTransform> > transforms;
00444     geometry_msgs::TransformStampedPtr pose_msg(new geometry_msgs::TransformStamped);
00445     static unsigned int cnt = 0;
00446 
00447     for (unsigned int i_subjects = 0; i_subjects < n_subjects; i_subjects++)
00448     {
00449 
00450       subject_name = msvcbridge::GetSubjectName(i_subjects).SubjectName;
00451       unsigned int n_segments = msvcbridge::GetSegmentCount(subject_name).SegmentCount;
00452 
00453       for (unsigned int i_segments = 0; i_segments < n_segments; i_segments++)
00454       {
00455         segment_name = msvcbridge::GetSegmentName(subject_name, i_segments).SegmentName;
00456 
00457         Output_GetSegmentGlobalTranslation trans = msvcbridge::GetSegmentGlobalTranslation(subject_name, segment_name);
00458         Output_GetSegmentGlobalRotationQuaternion quat = msvcbridge::GetSegmentGlobalRotationQuaternion(subject_name,
00459                                                                                                         segment_name);
00460 
00461         if (trans.Result == Result::Success && quat.Result == Result::Success)
00462         {
00463           if (!trans.Occluded && !quat.Occluded)
00464           {
00465             transform.setOrigin(tf::Vector3(trans.Translation[0] / 1000, trans.Translation[1] / 1000,
00466                                                   trans.Translation[2] / 1000));
00467             transform.setRotation(tf::Quaternion(quat.Rotation[0], quat.Rotation[1], quat.Rotation[2],
00468                                                        quat.Rotation[3]));
00469 
00470             tracked_frame = tracked_frame_suffix_ + "/" + subject_name + "/" + segment_name;
00471 
00472             boost::mutex::scoped_try_lock lock(segments_mutex_);
00473 
00474             if (lock.owns_lock())
00475             {
00476               pub_it = segment_publishers_.find(subject_name + "/" + segment_name);
00477               if (pub_it != segment_publishers_.end())
00478               {
00479                 SegmentPublisher & seg = pub_it->second;
00480                 //ros::Time thisTime = now_time - ros::Duration(latencyInMs / 1000);
00481 
00482                 if (seg.is_ready)
00483                 {
00484                   transform = transform * seg.calibration_pose;
00485                   transforms.push_back(tf::StampedTransform(transform, frame_time, tf_ref_frame_id_, tracked_frame));
00486 //                  transform = tf::StampedTransform(flyer_transform, frame_time, tf_ref_frame_id_, tracked_frame);
00487 //                  tf_broadcaster_.sendTransform(transform);
00488                   tf::transformStampedTFToMsg(transforms.back(), *pose_msg);
00489                   seg.pub.publish(pose_msg);
00490                 }
00491               }
00492               else
00493               {
00494                 lock.unlock();
00495                 createSegment(subject_name, segment_name);
00496               }
00497             }
00498           }
00499           else
00500           {
00501             if (cnt % 100 == 0)
00502               ROS_WARN_STREAM("" << subject_name <<" occluded, not publishing... " );
00503           }
00504         }
00505         else
00506         {
00507           ROS_WARN("GetSegmentGlobalTranslation/Rotation failed (result = %s, %s), not publishing...",
00508               Adapt(trans.Result).c_str(), Adapt(quat.Result).c_str());
00509         }
00510       }
00511     }
00512 
00513     tf_broadcaster_.sendTransform(transforms);
00514     cnt++;
00515   }
00516 
00517   void process_markers(const ros::Time& frame_time, unsigned int vicon_frame_num)
00518   {
00519     if (marker_pub_.getNumSubscribers() > 0)
00520     {
00521       if (not marker_data_enabled)
00522       {
00523         msvcbridge::EnableMarkerData();
00524         ROS_ASSERT(msvcbridge::IsMarkerDataEnabled().Enabled);
00525         marker_data_enabled = true;
00526       }
00527       if (not unlabeled_marker_data_enabled)
00528       {
00529         msvcbridge::EnableUnlabeledMarkerData();
00530         ROS_ASSERT(msvcbridge::IsUnlabeledMarkerDataEnabled().Enabled);
00531         unlabeled_marker_data_enabled = true;
00532       }
00533       n_markers = 0;
00534       vicon_bridge::Markers markers_msg;
00535       markers_msg.header.stamp = frame_time;
00536       markers_msg.frame_number = vicon_frame_num;
00537       // Count the number of subjects
00538       unsigned int SubjectCount = msvcbridge::GetSubjectCount().SubjectCount;
00539       // Get labeled markers
00540       for (unsigned int SubjectIndex = 0; SubjectIndex < SubjectCount; ++SubjectIndex)
00541       {
00542         std::string this_subject_name = msvcbridge::GetSubjectName(SubjectIndex).SubjectName;
00543         // Count the number of markers
00544         unsigned int num_subject_markers = msvcbridge::GetMarkerCount(this_subject_name).MarkerCount;
00545         n_markers += num_subject_markers;
00546         //std::cout << "    Markers (" << MarkerCount << "):" << std::endl;
00547         for (unsigned int MarkerIndex = 0; MarkerIndex < num_subject_markers; ++MarkerIndex)
00548         {
00549           vicon_bridge::Marker this_marker;
00550           this_marker.marker_name = msvcbridge::GetMarkerName(this_subject_name, MarkerIndex).MarkerName;
00551           this_marker.subject_name = this_subject_name;
00552           this_marker.segment_name
00553               = msvcbridge::GetMarkerParentName(this_subject_name, this_marker.marker_name).SegmentName;
00554 
00555           // Get the global marker translation
00556           Output_GetMarkerGlobalTranslation _Output_GetMarkerGlobalTranslation =
00557               msvcbridge::GetMarkerGlobalTranslation(this_subject_name, this_marker.marker_name);
00558 
00559           this_marker.translation.x = _Output_GetMarkerGlobalTranslation.Translation[0];
00560           this_marker.translation.y = _Output_GetMarkerGlobalTranslation.Translation[1];
00561           this_marker.translation.z = _Output_GetMarkerGlobalTranslation.Translation[2];
00562           this_marker.occluded = _Output_GetMarkerGlobalTranslation.Occluded;
00563 
00564           markers_msg.markers.push_back(this_marker);
00565         }
00566       }
00567       // get unlabeled markers
00568       unsigned int UnlabeledMarkerCount = msvcbridge::GetUnlabeledMarkerCount().MarkerCount;
00569       //ROS_INFO("# unlabeled markers: %d", UnlabeledMarkerCount);
00570       n_markers += UnlabeledMarkerCount;
00571       n_unlabeled_markers = UnlabeledMarkerCount;
00572       for (unsigned int UnlabeledMarkerIndex = 0; UnlabeledMarkerIndex < UnlabeledMarkerCount; ++UnlabeledMarkerIndex)
00573       {
00574         // Get the global marker translation
00575         Output_GetUnlabeledMarkerGlobalTranslation _Output_GetUnlabeledMarkerGlobalTranslation =
00576             msvcbridge::GetUnlabeledMarkerGlobalTranslation(UnlabeledMarkerIndex);
00577 
00578         if (_Output_GetUnlabeledMarkerGlobalTranslation.Result == Result::Success)
00579         {
00580           vicon_bridge::Marker this_marker;
00581           this_marker.translation.x = _Output_GetUnlabeledMarkerGlobalTranslation.Translation[0];
00582           this_marker.translation.y = _Output_GetUnlabeledMarkerGlobalTranslation.Translation[1];
00583           this_marker.translation.z = _Output_GetUnlabeledMarkerGlobalTranslation.Translation[2];
00584           this_marker.occluded = false; // unlabeled markers can't be occluded
00585           markers_msg.markers.push_back(this_marker);
00586         }
00587         else
00588         {
00589           ROS_WARN("GetUnlabeledMarkerGlobalTranslation failed (result = %s)",
00590               Adapt(_Output_GetUnlabeledMarkerGlobalTranslation.Result).c_str());
00591 
00592         }
00593       }
00594       marker_pub_.publish(markers_msg);
00595     }
00596   }
00597 
00598   bool grabPoseCallback(vicon_bridge::viconGrabPose::Request& req, vicon_bridge::viconGrabPose::Response& resp)
00599   {
00600     ROS_INFO("Got request for a VICON pose");
00601     tf::TransformListener tf_listener;
00602     tf::StampedTransform transform;
00603     tf::Quaternion orientation(0, 0, 0, 0);
00604     tf::Vector3 position(0, 0, 0);
00605 
00606     string tracked_segment = tracked_frame_suffix_ + "/" + req.subject_name + "/" + req.segment_name;
00607 
00608     // Gather data:
00609     int N = req.n_measurements;
00610     int n_success = 0;
00611     ros::Duration timeout(0.1);
00612     ros::Duration poll_period(1.0 / 240.0);
00613 
00614     for (int k = 0; k < N; k++)
00615     {
00616       try
00617       {
00618         if (tf_listener.waitForTransform(tf_ref_frame_id_, tracked_segment, ros::Time::now(), timeout, poll_period))
00619         {
00620           tf_listener.lookupTransform(tf_ref_frame_id_, tracked_segment, ros::Time(0), transform);
00621           orientation += transform.getRotation();
00622           position += transform.getOrigin();
00623           n_success++;
00624         }
00625       }
00626       catch (tf::TransformException ex)
00627       {
00628         ROS_ERROR("%s", ex.what());
00629         //              resp.success = false;
00630         //              return false; // TODO: should we really bail here, or just try again?
00631       }
00632     }
00633 
00634     // Average the data
00635     orientation /= n_success;
00636     orientation.normalize();
00637     position /= n_success;
00638 
00639     // copy what we used to service call response:
00640     resp.success = true;
00641     resp.pose.header.stamp = ros::Time::now();
00642     resp.pose.header.frame_id = tf_ref_frame_id_;
00643     resp.pose.pose.position.x = position.x();
00644     resp.pose.pose.position.y = position.y();
00645     resp.pose.pose.position.z = position.z();
00646     resp.pose.pose.orientation.w = orientation.w();
00647     resp.pose.pose.orientation.x = orientation.x();
00648     resp.pose.pose.orientation.y = orientation.y();
00649     resp.pose.pose.orientation.z = orientation.z();
00650 
00651     return true;
00652   }
00653 
00654   bool calibrateSegmentCallback(vicon_bridge::viconCalibrateSegment::Request& req,
00655                                 vicon_bridge::viconCalibrateSegment::Response& resp)
00656   {
00657 
00658     std::string full_name = req.subject_name + "/" + req.segment_name;
00659     ROS_INFO("trying to calibrate %s", full_name.c_str());
00660 
00661     SegmentMap::iterator seg_it = segment_publishers_.find(full_name);
00662 
00663     if (seg_it == segment_publishers_.end())
00664     {
00665       ROS_WARN("frame %s not found --> not calibrating", full_name.c_str());
00666       resp.success = false;
00667       resp.status = "segment " + full_name + " not found";
00668       return false;
00669     }
00670 
00671     SegmentPublisher & seg = seg_it->second;
00672 
00673     if (seg.calibrated)
00674     {
00675       ROS_INFO("%s already calibrated, deleting old calibration", full_name.c_str());
00676       seg.calibration_pose.setIdentity();
00677     }
00678 
00679     vicon_bridge::viconGrabPose::Request grab_req;
00680     vicon_bridge::viconGrabPose::Response grab_resp;
00681 
00682     grab_req.n_measurements = req.n_measurements;
00683     grab_req.subject_name = req.subject_name;
00684     grab_req.segment_name = req.segment_name;
00685 
00686     bool ret = grabPoseCallback(grab_req, grab_resp);
00687 
00688     if (!ret)
00689     {
00690       resp.success = false;
00691       resp.status = "error while grabbing pose from Vicon";
00692       return false;
00693     }
00694 
00695     tf::Transform t;
00696     t.setOrigin(tf::Vector3(grab_resp.pose.pose.position.x, grab_resp.pose.pose.position.y,
00697                             grab_resp.pose.pose.position.z - req.z_offset));
00698     t.setRotation(tf::Quaternion(grab_resp.pose.pose.orientation.x, grab_resp.pose.pose.orientation.y,
00699                                  grab_resp.pose.pose.orientation.z, grab_resp.pose.pose.orientation.w));
00700 
00701     seg.calibration_pose = t.inverse();
00702 
00703     // write zero_pose to parameter server
00704     string param_suffix(full_name + "/zero_pose/");
00705     nh_priv.setParam(param_suffix + "orientation/w", t.getRotation().w());
00706     nh_priv.setParam(param_suffix + "orientation/x", t.getRotation().x());
00707     nh_priv.setParam(param_suffix + "orientation/y", t.getRotation().y());
00708     nh_priv.setParam(param_suffix + "orientation/z", t.getRotation().z());
00709 
00710     nh_priv.setParam(param_suffix + "position/x", t.getOrigin().x());
00711     nh_priv.setParam(param_suffix + "position/y", t.getOrigin().y());
00712     nh_priv.setParam(param_suffix + "position/z", t.getOrigin().z());
00713 
00714     ROS_INFO_STREAM("calibration completed");
00715     resp.pose = grab_resp.pose;
00716     resp.success = true;
00717     resp.status = "calibration successful";
00718     seg.calibrated = true;
00719 
00720     return true;
00721   }
00722 
00723 };
00724 
00725 int main(int argc, char** argv)
00726 {
00727   ros::init(argc, argv, "vicon");
00728 //  ViconReceiver vr;
00729 //  ros::spin();
00730 
00731   ros::AsyncSpinner aspin(1);
00732   aspin.start();
00733   ViconReceiver vr;
00734   aspin.stop();
00735   return 0;
00736 }


vicon_bridge
Author(s): Markus Achtelik
autogenerated on Sun Oct 5 2014 23:47:38