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 broadcast_tf_, publish_tf_, publish_markers_;
00187
00188 bool grab_frames_;
00189 boost::thread grab_frames_thread_;
00190 SegmentMap segment_publishers_;
00191 boost::mutex segments_mutex_;
00192 std::vector<std::string> time_log_;
00193
00194 public:
00195 void startGrabbing()
00196 {
00197 grab_frames_ = true;
00198
00199 grabThread();
00200
00201 }
00202
00203 void stopGrabbing()
00204 {
00205 grab_frames_ = false;
00206
00207 }
00208
00209 ViconReceiver() :
00210 nh_priv("~"), diag_updater(), min_freq_(0.1), max_freq_(1000),
00211 freq_status_(diagnostic_updater::FrequencyStatusParam(&min_freq_, &max_freq_)), stream_mode_("ClientPull"),
00212 host_name_(""), tf_ref_frame_id_("world"), tracked_frame_suffix_("vicon"),
00213 lastFrameNumber(0), frameCount(0), droppedFrameCount(0), frame_datum(0), n_markers(0), n_unlabeled_markers(0),
00214 marker_data_enabled(false), unlabeled_marker_data_enabled(false), grab_frames_(false)
00215
00216 {
00217
00218 diag_updater.add("ViconReceiver Status", this, &ViconReceiver::diagnostics);
00219 diag_updater.add(freq_status_);
00220 diag_updater.setHardwareID("none");
00221 diag_updater.force_update();
00222
00223 nh_priv.param("stream_mode", stream_mode_, stream_mode_);
00224 nh_priv.param("datastream_hostport", host_name_, host_name_);
00225 nh_priv.param("tf_ref_frame_id", tf_ref_frame_id_, tf_ref_frame_id_);
00226 nh_priv.param("broadcast_transform", broadcast_tf_, true);
00227 nh_priv.param("publish_transform", publish_tf_, true);
00228 nh_priv.param("publish_markers", publish_markers_, true);
00229 if (init_vicon() == false){
00230 ROS_ERROR("Error while connecting to Vicon. Exiting now.");
00231 return;
00232 }
00233
00234 ROS_INFO("setting up grab_vicon_pose service server ... ");
00235 m_grab_vicon_pose_service_server = nh_priv.advertiseService("grab_vicon_pose", &ViconReceiver::grabPoseCallback,
00236 this);
00237
00238 ROS_INFO("setting up segment calibration service server ... ");
00239 calibrate_segment_server_ = nh_priv.advertiseService("calibrate_segment", &ViconReceiver::calibrateSegmentCallback,
00240 this);
00241
00242
00243 if(publish_markers_)
00244 {
00245 marker_pub_ = nh.advertise<vicon_bridge::Markers>(tracked_frame_suffix_ + "/markers", 10);
00246 }
00247 startGrabbing();
00248 }
00249
00250 ~ViconReceiver()
00251 {
00252 for (size_t i = 0; i < time_log_.size(); i++)
00253 {
00254 std::cout << time_log_[i] << std::endl;
00255 }
00256 if (shutdown_vicon() == false){
00257 ROS_ERROR("Error while shutting down Vicon.");
00258 }
00259 }
00260
00261 private:
00262 void diagnostics(diagnostic_updater::DiagnosticStatusWrapper& stat)
00263 {
00264 stat.summary(diagnostic_msgs::DiagnosticStatus::OK, "OK");
00265 stat.add("latest VICON frame number", lastFrameNumber);
00266 stat.add("dropped frames", droppedFrameCount);
00267 stat.add("framecount", frameCount);
00268 stat.add("# markers", n_markers);
00269 stat.add("# unlabeled markers", n_unlabeled_markers);
00270 }
00271
00272 bool init_vicon()
00273 {
00274 ROS_INFO_STREAM("Connecting to Vicon DataStream SDK at " << host_name_ << " ...");
00275
00276 ros::Duration d(1);
00277 Result::Enum result(Result::Unknown);
00278
00279 while (!msvcbridge::IsConnected().Connected)
00280 {
00281 msvcbridge::Connect(host_name_);
00282 ROS_INFO(".");
00283 d.sleep();
00284 ros::spinOnce();
00285 if (!ros::ok())
00286 return false;
00287 }
00288 ROS_ASSERT(msvcbridge::IsConnected().Connected);
00289 ROS_INFO_STREAM("... connected!");
00290
00291
00292 if (stream_mode_ == "ServerPush")
00293 {
00294 result = msvcbridge::SetStreamMode(StreamMode::ServerPush).Result;
00295 }
00296 else if (stream_mode_ == "ClientPull")
00297 {
00298 result = msvcbridge::SetStreamMode(StreamMode::ClientPull).Result;
00299 }
00300 else
00301 {
00302 ROS_FATAL("Unknown stream mode -- options are ServerPush, ClientPull");
00303 ros::shutdown();
00304 }
00305
00306 ROS_INFO_STREAM("Setting Stream Mode to " << stream_mode_<< ": "<< Adapt(result));
00307
00308 msvcbridge::SetAxisMapping(Direction::Forward, Direction::Left, Direction::Up);
00309 Output_GetAxisMapping _Output_GetAxisMapping = msvcbridge::GetAxisMapping();
00310
00311 ROS_INFO_STREAM("Axis Mapping: X-" << Adapt(_Output_GetAxisMapping.XAxis) << " Y-"
00312 << Adapt(_Output_GetAxisMapping.YAxis) << " Z-" << Adapt(_Output_GetAxisMapping.ZAxis));
00313
00314 msvcbridge::EnableSegmentData();
00315 ROS_ASSERT(msvcbridge::IsSegmentDataEnabled().Enabled);
00316
00317 Output_GetVersion _Output_GetVersion = msvcbridge::GetVersion();
00318 ROS_INFO_STREAM("Version: " << _Output_GetVersion.Major << "." << _Output_GetVersion.Minor << "."
00319 << _Output_GetVersion.Point);
00320 return true;
00321 }
00322
00323 void createSegmentThread(const string subject_name, const string segment_name)
00324 {
00325 ROS_INFO("creating new object %s/%s ...",subject_name.c_str(), segment_name.c_str() );
00326 boost::mutex::scoped_lock lock(segments_mutex_);
00327 SegmentPublisher & spub = segment_publishers_[subject_name + "/" + segment_name];
00328
00329
00330 lock.unlock();
00331
00332 if(publish_tf_)
00333 {
00334 spub.pub = nh.advertise<geometry_msgs::TransformStamped>(tracked_frame_suffix_ + "/" + subject_name + "/"
00335 + segment_name, 10);
00336 }
00337
00338 string param_suffix(subject_name + "/" + segment_name + "/zero_pose/");
00339 double qw, qx, qy, qz, x, y, z;
00340 bool have_params = true;
00341 have_params = have_params && nh_priv.getParam(param_suffix + "orientation/w", qw);
00342 have_params = have_params && nh_priv.getParam(param_suffix + "orientation/x", qx);
00343 have_params = have_params && nh_priv.getParam(param_suffix + "orientation/y", qy);
00344 have_params = have_params && nh_priv.getParam(param_suffix + "orientation/z", qz);
00345 have_params = have_params && nh_priv.getParam(param_suffix + "position/x", x);
00346 have_params = have_params && nh_priv.getParam(param_suffix + "position/y", y);
00347 have_params = have_params && nh_priv.getParam(param_suffix + "position/z", z);
00348
00349 if (have_params)
00350 {
00351 ROS_INFO("loaded zero pose for %s/%s", subject_name.c_str(), segment_name.c_str());
00352 spub.calibration_pose.setRotation(tf::Quaternion(qx, qy, qz, qw));
00353 spub.calibration_pose.setOrigin(tf::Vector3(x, y, z));
00354 spub.calibration_pose = spub.calibration_pose.inverse();
00355 }
00356 else
00357 {
00358 ROS_WARN("unable to load zero pose for %s/%s", subject_name.c_str(), segment_name.c_str());
00359 spub.calibration_pose.setIdentity();
00360 }
00361
00362 spub.is_ready = true;
00363 ROS_INFO("... done, advertised as \" %s/%s/%s\" ", tracked_frame_suffix_.c_str(), subject_name.c_str(), segment_name.c_str());
00364
00365 }
00366
00367 void createSegment(const string subject_name, const string segment_name)
00368 {
00369 boost::thread(&ViconReceiver::createSegmentThread, this, subject_name, segment_name);
00370 }
00371
00372 void grabThread()
00373 {
00374 ros::Duration d(1.0 / 240.0);
00375
00376
00377
00378
00379 while (ros::ok() && grab_frames_)
00380 {
00381 while (msvcbridge::GetFrame().Result != Result::Success && ros::ok())
00382 {
00383 ROS_INFO("getFrame returned false");
00384 d.sleep();
00385 }
00386 now_time = ros::Time::now();
00387
00388
00389
00390
00391
00392
00393
00394
00395 bool was_new_frame = process_frame();
00396 ROS_WARN_COND(!was_new_frame, "grab frame returned false");
00397
00398 diag_updater.update();
00399 }
00400 }
00401
00402 bool shutdown_vicon()
00403 {
00404 ROS_INFO_STREAM("stopping grabbing thread");
00405 stopGrabbing();
00406 ROS_INFO_STREAM("Disconnecting from Vicon DataStream SDK");
00407 msvcbridge::Disconnect();
00408 ROS_ASSERT(!msvcbridge::IsConnected().Connected);
00409 ROS_INFO_STREAM("... disconnected.");
00410 return true;
00411 }
00412
00413 bool process_frame()
00414 {
00415 static ros::Time lastTime;
00416 Output_GetFrameNumber OutputFrameNum = msvcbridge::GetFrameNumber();
00417
00418
00419
00420 int frameDiff = 0;
00421 if (lastFrameNumber != 0)
00422 {
00423 frameDiff = OutputFrameNum.FrameNumber - lastFrameNumber;
00424 frameCount += frameDiff;
00425 if ((frameDiff) > 1)
00426 {
00427 droppedFrameCount += frameDiff;
00428 double droppedFramePct = (double)droppedFrameCount / frameCount * 100;
00429 ROS_DEBUG_STREAM(frameDiff << " more (total " << droppedFrameCount << "/" << frameCount << ", "
00430 << droppedFramePct << "%) frame(s) dropped. Consider adjusting rates.");
00431 }
00432 }
00433 lastFrameNumber = OutputFrameNum.FrameNumber;
00434
00435 if (frameDiff == 0)
00436 {
00437 return false;
00438 }
00439 else
00440 {
00441 freq_status_.tick();
00442 ros::Duration vicon_latency(msvcbridge::GetLatencyTotal().Total);
00443
00444 if(publish_tf_ || broadcast_tf_)
00445 {
00446 process_subjects(now_time - vicon_latency);
00447 }
00448
00449 if(publish_markers_)
00450 {
00451 process_markers(now_time - vicon_latency, lastFrameNumber);
00452 }
00453
00454 lastTime = now_time;
00455 return true;
00456 }
00457 }
00458
00459 void process_subjects(const ros::Time& frame_time)
00460 {
00461 string tracked_frame, subject_name, segment_name;
00462 unsigned int n_subjects = msvcbridge::GetSubjectCount().SubjectCount;
00463 SegmentMap::iterator pub_it;
00464 tf::Transform transform;
00465 std::vector<tf::StampedTransform, std::allocator<tf::StampedTransform> > transforms;
00466 geometry_msgs::TransformStampedPtr pose_msg(new geometry_msgs::TransformStamped);
00467 static unsigned int cnt = 0;
00468
00469 for (unsigned int i_subjects = 0; i_subjects < n_subjects; i_subjects++)
00470 {
00471
00472 subject_name = msvcbridge::GetSubjectName(i_subjects).SubjectName;
00473 unsigned int n_segments = msvcbridge::GetSegmentCount(subject_name).SegmentCount;
00474
00475 for (unsigned int i_segments = 0; i_segments < n_segments; i_segments++)
00476 {
00477 segment_name = msvcbridge::GetSegmentName(subject_name, i_segments).SegmentName;
00478
00479 Output_GetSegmentGlobalTranslation trans = msvcbridge::GetSegmentGlobalTranslation(subject_name, segment_name);
00480 Output_GetSegmentGlobalRotationQuaternion quat = msvcbridge::GetSegmentGlobalRotationQuaternion(subject_name,
00481 segment_name);
00482
00483 if (trans.Result == Result::Success && quat.Result == Result::Success)
00484 {
00485 if (!trans.Occluded && !quat.Occluded)
00486 {
00487 transform.setOrigin(tf::Vector3(trans.Translation[0] / 1000, trans.Translation[1] / 1000,
00488 trans.Translation[2] / 1000));
00489 transform.setRotation(tf::Quaternion(quat.Rotation[0], quat.Rotation[1], quat.Rotation[2],
00490 quat.Rotation[3]));
00491
00492 tracked_frame = tracked_frame_suffix_ + "/" + subject_name + "/" + segment_name;
00493
00494 boost::mutex::scoped_try_lock lock(segments_mutex_);
00495
00496 if (lock.owns_lock())
00497 {
00498 pub_it = segment_publishers_.find(subject_name + "/" + segment_name);
00499 if (pub_it != segment_publishers_.end())
00500 {
00501 SegmentPublisher & seg = pub_it->second;
00502
00503
00504 if (seg.is_ready)
00505 {
00506 transform = transform * seg.calibration_pose;
00507 transforms.push_back(tf::StampedTransform(transform, frame_time, tf_ref_frame_id_, tracked_frame));
00508
00509
00510
00511 if(publish_tf_)
00512 {
00513 tf::transformStampedTFToMsg(transforms.back(), *pose_msg);
00514 seg.pub.publish(pose_msg);
00515 }
00516 }
00517 }
00518 else
00519 {
00520 lock.unlock();
00521 createSegment(subject_name, segment_name);
00522 }
00523 }
00524 }
00525 else
00526 {
00527 if (cnt % 100 == 0)
00528 ROS_WARN_STREAM("" << subject_name <<" occluded, not publishing... " );
00529 }
00530 }
00531 else
00532 {
00533 ROS_WARN("GetSegmentGlobalTranslation/Rotation failed (result = %s, %s), not publishing...",
00534 Adapt(trans.Result).c_str(), Adapt(quat.Result).c_str());
00535 }
00536 }
00537 }
00538
00539 if(broadcast_tf_)
00540 {
00541 tf_broadcaster_.sendTransform(transforms);
00542 }
00543 cnt++;
00544 }
00545
00546 void process_markers(const ros::Time& frame_time, unsigned int vicon_frame_num)
00547 {
00548 if (marker_pub_.getNumSubscribers() > 0)
00549 {
00550 if (not marker_data_enabled)
00551 {
00552 msvcbridge::EnableMarkerData();
00553 ROS_ASSERT(msvcbridge::IsMarkerDataEnabled().Enabled);
00554 marker_data_enabled = true;
00555 }
00556 if (not unlabeled_marker_data_enabled)
00557 {
00558 msvcbridge::EnableUnlabeledMarkerData();
00559 ROS_ASSERT(msvcbridge::IsUnlabeledMarkerDataEnabled().Enabled);
00560 unlabeled_marker_data_enabled = true;
00561 }
00562 n_markers = 0;
00563 vicon_bridge::Markers markers_msg;
00564 markers_msg.header.stamp = frame_time;
00565 markers_msg.frame_number = vicon_frame_num;
00566
00567 unsigned int SubjectCount = msvcbridge::GetSubjectCount().SubjectCount;
00568
00569 for (unsigned int SubjectIndex = 0; SubjectIndex < SubjectCount; ++SubjectIndex)
00570 {
00571 std::string this_subject_name = msvcbridge::GetSubjectName(SubjectIndex).SubjectName;
00572
00573 unsigned int num_subject_markers = msvcbridge::GetMarkerCount(this_subject_name).MarkerCount;
00574 n_markers += num_subject_markers;
00575
00576 for (unsigned int MarkerIndex = 0; MarkerIndex < num_subject_markers; ++MarkerIndex)
00577 {
00578 vicon_bridge::Marker this_marker;
00579 this_marker.marker_name = msvcbridge::GetMarkerName(this_subject_name, MarkerIndex).MarkerName;
00580 this_marker.subject_name = this_subject_name;
00581 this_marker.segment_name
00582 = msvcbridge::GetMarkerParentName(this_subject_name, this_marker.marker_name).SegmentName;
00583
00584
00585 Output_GetMarkerGlobalTranslation _Output_GetMarkerGlobalTranslation =
00586 msvcbridge::GetMarkerGlobalTranslation(this_subject_name, this_marker.marker_name);
00587
00588 this_marker.translation.x = _Output_GetMarkerGlobalTranslation.Translation[0];
00589 this_marker.translation.y = _Output_GetMarkerGlobalTranslation.Translation[1];
00590 this_marker.translation.z = _Output_GetMarkerGlobalTranslation.Translation[2];
00591 this_marker.occluded = _Output_GetMarkerGlobalTranslation.Occluded;
00592
00593 markers_msg.markers.push_back(this_marker);
00594 }
00595 }
00596
00597 unsigned int UnlabeledMarkerCount = msvcbridge::GetUnlabeledMarkerCount().MarkerCount;
00598
00599 n_markers += UnlabeledMarkerCount;
00600 n_unlabeled_markers = UnlabeledMarkerCount;
00601 for (unsigned int UnlabeledMarkerIndex = 0; UnlabeledMarkerIndex < UnlabeledMarkerCount; ++UnlabeledMarkerIndex)
00602 {
00603
00604 Output_GetUnlabeledMarkerGlobalTranslation _Output_GetUnlabeledMarkerGlobalTranslation =
00605 msvcbridge::GetUnlabeledMarkerGlobalTranslation(UnlabeledMarkerIndex);
00606
00607 if (_Output_GetUnlabeledMarkerGlobalTranslation.Result == Result::Success)
00608 {
00609 vicon_bridge::Marker this_marker;
00610 this_marker.translation.x = _Output_GetUnlabeledMarkerGlobalTranslation.Translation[0];
00611 this_marker.translation.y = _Output_GetUnlabeledMarkerGlobalTranslation.Translation[1];
00612 this_marker.translation.z = _Output_GetUnlabeledMarkerGlobalTranslation.Translation[2];
00613 this_marker.occluded = false;
00614 markers_msg.markers.push_back(this_marker);
00615 }
00616 else
00617 {
00618 ROS_WARN("GetUnlabeledMarkerGlobalTranslation failed (result = %s)",
00619 Adapt(_Output_GetUnlabeledMarkerGlobalTranslation.Result).c_str());
00620
00621 }
00622 }
00623 marker_pub_.publish(markers_msg);
00624 }
00625 }
00626
00627 bool grabPoseCallback(vicon_bridge::viconGrabPose::Request& req, vicon_bridge::viconGrabPose::Response& resp)
00628 {
00629 ROS_INFO("Got request for a VICON pose");
00630 tf::TransformListener tf_listener;
00631 tf::StampedTransform transform;
00632 tf::Quaternion orientation(0, 0, 0, 0);
00633 tf::Vector3 position(0, 0, 0);
00634
00635 string tracked_segment = tracked_frame_suffix_ + "/" + req.subject_name + "/" + req.segment_name;
00636
00637
00638 int N = req.n_measurements;
00639 int n_success = 0;
00640 ros::Duration timeout(0.1);
00641 ros::Duration poll_period(1.0 / 240.0);
00642
00643 for (int k = 0; k < N; k++)
00644 {
00645 try
00646 {
00647 if (tf_listener.waitForTransform(tf_ref_frame_id_, tracked_segment, ros::Time::now(), timeout, poll_period))
00648 {
00649 tf_listener.lookupTransform(tf_ref_frame_id_, tracked_segment, ros::Time(0), transform);
00650 orientation += transform.getRotation();
00651 position += transform.getOrigin();
00652 n_success++;
00653 }
00654 }
00655 catch (tf::TransformException ex)
00656 {
00657 ROS_ERROR("%s", ex.what());
00658
00659
00660 }
00661 }
00662
00663
00664 orientation /= n_success;
00665 orientation.normalize();
00666 position /= n_success;
00667
00668
00669 resp.success = true;
00670 resp.pose.header.stamp = ros::Time::now();
00671 resp.pose.header.frame_id = tf_ref_frame_id_;
00672 resp.pose.pose.position.x = position.x();
00673 resp.pose.pose.position.y = position.y();
00674 resp.pose.pose.position.z = position.z();
00675 resp.pose.pose.orientation.w = orientation.w();
00676 resp.pose.pose.orientation.x = orientation.x();
00677 resp.pose.pose.orientation.y = orientation.y();
00678 resp.pose.pose.orientation.z = orientation.z();
00679
00680 return true;
00681 }
00682
00683 bool calibrateSegmentCallback(vicon_bridge::viconCalibrateSegment::Request& req,
00684 vicon_bridge::viconCalibrateSegment::Response& resp)
00685 {
00686
00687 std::string full_name = req.subject_name + "/" + req.segment_name;
00688 ROS_INFO("trying to calibrate %s", full_name.c_str());
00689
00690 SegmentMap::iterator seg_it = segment_publishers_.find(full_name);
00691
00692 if (seg_it == segment_publishers_.end())
00693 {
00694 ROS_WARN("frame %s not found --> not calibrating", full_name.c_str());
00695 resp.success = false;
00696 resp.status = "segment " + full_name + " not found";
00697 return false;
00698 }
00699
00700 SegmentPublisher & seg = seg_it->second;
00701
00702 if (seg.calibrated)
00703 {
00704 ROS_INFO("%s already calibrated, deleting old calibration", full_name.c_str());
00705 seg.calibration_pose.setIdentity();
00706 }
00707
00708 vicon_bridge::viconGrabPose::Request grab_req;
00709 vicon_bridge::viconGrabPose::Response grab_resp;
00710
00711 grab_req.n_measurements = req.n_measurements;
00712 grab_req.subject_name = req.subject_name;
00713 grab_req.segment_name = req.segment_name;
00714
00715 bool ret = grabPoseCallback(grab_req, grab_resp);
00716
00717 if (!ret)
00718 {
00719 resp.success = false;
00720 resp.status = "error while grabbing pose from Vicon";
00721 return false;
00722 }
00723
00724 tf::Transform t;
00725 t.setOrigin(tf::Vector3(grab_resp.pose.pose.position.x, grab_resp.pose.pose.position.y,
00726 grab_resp.pose.pose.position.z - req.z_offset));
00727 t.setRotation(tf::Quaternion(grab_resp.pose.pose.orientation.x, grab_resp.pose.pose.orientation.y,
00728 grab_resp.pose.pose.orientation.z, grab_resp.pose.pose.orientation.w));
00729
00730 seg.calibration_pose = t.inverse();
00731
00732
00733 string param_suffix(full_name + "/zero_pose/");
00734 nh_priv.setParam(param_suffix + "orientation/w", t.getRotation().w());
00735 nh_priv.setParam(param_suffix + "orientation/x", t.getRotation().x());
00736 nh_priv.setParam(param_suffix + "orientation/y", t.getRotation().y());
00737 nh_priv.setParam(param_suffix + "orientation/z", t.getRotation().z());
00738
00739 nh_priv.setParam(param_suffix + "position/x", t.getOrigin().x());
00740 nh_priv.setParam(param_suffix + "position/y", t.getOrigin().y());
00741 nh_priv.setParam(param_suffix + "position/z", t.getOrigin().z());
00742
00743 ROS_INFO_STREAM("calibration completed");
00744 resp.pose = grab_resp.pose;
00745 resp.success = true;
00746 resp.status = "calibration successful";
00747 seg.calibrated = true;
00748
00749 return true;
00750 }
00751
00752 };
00753
00754 int main(int argc, char** argv)
00755 {
00756 ros::init(argc, argv, "vicon");
00757
00758
00759
00760 ros::AsyncSpinner aspin(1);
00761 aspin.start();
00762 ViconReceiver vr;
00763 aspin.stop();
00764 return 0;
00765 }