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 }