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 
00029 
00030 
00031 
00032 
00033 
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   
00155   diagnostic_updater::Updater diag_updater;
00156   double min_freq_;
00157   double max_freq_;
00158   diagnostic_updater::FrequencyStatus freq_status_;
00159   
00160   string stream_mode_;
00161   string host_name_;
00162   string tf_ref_frame_id_;
00163   string tracked_frame_suffix_;
00164   
00165   ros::Publisher marker_pub_;
00166   
00167   tf::TransformBroadcaster tf_broadcaster_;
00168   
00169   tf::Transform flyer_transform;
00170   ros::Time now_time;
00171   
00172   ros::ServiceServer m_grab_vicon_pose_service_server;
00173   ros::ServiceServer calibrate_segment_server_;
00174   
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     
00197     grabThread();
00198     
00199   }
00200 
00201   void stopGrabbing()
00202   {
00203     grab_frames_ = false;
00204     
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     
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     
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     
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     
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     
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); 
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     
00317     lock.unlock();
00318 
00319     spub.pub = nh.advertise<geometry_msgs::TransformStamped> (tracked_frame_suffix_ + "/" + subject_name + "/"
00320         + segment_name, 10);
00321 
00322     
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 
00361 
00362 
00363 
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 
00373 
00374 
00375 
00376 
00377 
00378 
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     
00404     
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                 
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 
00487 
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       
00538       unsigned int SubjectCount = msvcbridge::GetSubjectCount().SubjectCount;
00539       
00540       for (unsigned int SubjectIndex = 0; SubjectIndex < SubjectCount; ++SubjectIndex)
00541       {
00542         std::string this_subject_name = msvcbridge::GetSubjectName(SubjectIndex).SubjectName;
00543         
00544         unsigned int num_subject_markers = msvcbridge::GetMarkerCount(this_subject_name).MarkerCount;
00545         n_markers += num_subject_markers;
00546         
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           
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       
00568       unsigned int UnlabeledMarkerCount = msvcbridge::GetUnlabeledMarkerCount().MarkerCount;
00569       
00570       n_markers += UnlabeledMarkerCount;
00571       n_unlabeled_markers = UnlabeledMarkerCount;
00572       for (unsigned int UnlabeledMarkerIndex = 0; UnlabeledMarkerIndex < UnlabeledMarkerCount; ++UnlabeledMarkerIndex)
00573       {
00574         
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; 
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     
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         
00630         
00631       }
00632     }
00633 
00634     
00635     orientation /= n_success;
00636     orientation.normalize();
00637     position /= n_success;
00638 
00639     
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     
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 
00729 
00730 
00731   ros::AsyncSpinner aspin(1);
00732   aspin.start();
00733   ViconReceiver vr;
00734   aspin.stop();
00735   return 0;
00736 }