$search
00001 #include <stdexcept> 00002 #include <string> 00003 00004 #include <boost/format.hpp> 00005 #include <boost/make_shared.hpp> 00006 00007 #include <LinearMath/btQuaternion.h> 00008 00009 #include <ros/ros.h> 00010 #include <geometry_msgs/TransformStamped.h> 00011 00012 #include <evart-client.h> 00013 00014 #include "tracker.hh" 00015 00016 namespace evart 00017 { 00018 static uint32_t 00019 getBodyIdFromName(const std::string& name) 00020 { 00021 const evas_body_list_t* bodyList = evas_body_list(); 00022 if(!bodyList) 00023 throw std::runtime_error("failed to retrieve body list"); 00024 00025 for(uint32_t i = 0; i < bodyList->nbodies; ++i) 00026 if(name == bodyList->bodies[i]) 00027 return i; 00028 00029 boost::format fmt("failed to retrieve the body id associated to '%1%'"); 00030 fmt % name; 00031 throw std::runtime_error(fmt.str()); 00032 } 00033 00034 static uint32_t 00035 getSegmentIdFromName(uint32_t bodyId, const std::string& name) 00036 { 00037 const evas_body_segments_list_t* segmentList = 00038 evas_body_segments_list(bodyId); 00039 if(!segmentList) 00040 throw std::runtime_error("failed to retrieve segment list"); 00041 00042 for(uint32_t i = 0; i < segmentList->nsegments; ++i) 00043 if (name == segmentList->hier[i].name) 00044 return i; 00045 00046 boost::format fmt 00047 ("failed to retrieve the segment id associated to '%1%' of body id '%2%'"); 00048 fmt % name % bodyId; 00049 throw std::runtime_error(fmt.str()); 00050 } 00051 00052 00053 Tracker::Tracker(ros::NodeHandle& nh, 00054 const std::string& objectName, 00055 const std::string& segmentName, 00056 const std::string& topicName, 00057 const std::string& referenceFrameName, 00058 const std::string& childFrameName, 00059 boost::optional<tf::TransformBroadcaster&> 00060 transformBroadcaster) 00061 : publisher_(), 00062 seq_(0), 00063 objectName_(objectName), 00064 segmentName_(segmentName), 00065 referenceFrameName_(referenceFrameName), 00066 childFrameName_(childFrameName), 00067 bodyId_(getBodyIdFromName(objectName)), 00068 segmentId_(getSegmentIdFromName (bodyId_, segmentName)), 00069 transformBroadcaster_ (transformBroadcaster) 00070 { 00071 publisher_ = 00072 nh.advertise<geometry_msgs::TransformStamped>(topicName, queueSize); 00073 00074 evas_body_segments(bodyId_, EVAS_ON); 00075 ROS_DEBUG_STREAM 00076 ("starting tracker for " << objectName_ << ":" << segmentName_); 00077 } 00078 00079 Tracker::~Tracker() 00080 { 00081 ROS_DEBUG_STREAM 00082 ("stopping tracker for " << objectName_ << ":" << segmentName_); 00083 evas_body_segments(bodyId_, EVAS_OFF); 00084 } 00085 00086 void 00087 Tracker::callback(const evas_body_segments_t& msg) 00088 { 00089 if (msg.segments[segmentId_].pos[0] == EVAS_EMPTY) 00090 { 00091 ROS_INFO_STREAM_THROTTLE 00092 (5, "no data for " << objectName_ << ":" << segmentName_); 00093 return; // No data. 00094 } 00095 if (msg.nsegments <= segmentId_) 00096 throw std::runtime_error("invalid segment id"); 00097 00098 boost::shared_ptr<geometry_msgs::TransformStamped> t 00099 (new geometry_msgs::TransformStamped()); 00100 00101 t->header.seq = seq_++; 00102 t->header.stamp.sec = msg.tv_sec; 00103 t->header.stamp.nsec = msg.tv_usec * 1000.; 00104 t->header.frame_id = referenceFrameName_; 00105 00106 t->child_frame_id = childFrameName_; 00107 00108 // Copy translation and convert to SI. 00109 t->transform.translation.x = msg.segments[segmentId_].pos[0] / 1000.; 00110 t->transform.translation.y = msg.segments[segmentId_].pos[1] / 1000.; 00111 t->transform.translation.z = msg.segments[segmentId_].pos[2] / 1000.; 00112 00113 // Convert euler angles to quaternion and convert to SI. 00114 // 00115 // WARNING: this makes the assumption that the rotation order is 00116 // the default one (i.e. XYX) in Cortex. If you change the 00117 // rotation order, this will not work. 00118 tf::Quaternion q; 00119 q.setRPY(msg.segments[segmentId_].rot[0] * M_PI / 180., 00120 msg.segments[segmentId_].rot[1] * M_PI / 180., 00121 msg.segments[segmentId_].rot[2] * M_PI / 180.); 00122 t->transform.rotation.x = q.x(); 00123 t->transform.rotation.y = q.y(); 00124 t->transform.rotation.z = q.z(); 00125 t->transform.rotation.w = q.w(); 00126 00127 // Tf 00128 if (transformBroadcaster_) 00129 { 00130 tf::Transform transform; 00131 transform.setOrigin 00132 (tf::Vector3(t->transform.translation.x, 00133 t->transform.translation.y, 00134 t->transform.translation.z)); 00135 transform.setRotation 00136 (tf::Quaternion 00137 (t->transform.rotation.x, 00138 t->transform.rotation.y, 00139 t->transform.rotation.z, 00140 t->transform.rotation.w)); 00141 transformBroadcaster_->sendTransform 00142 (tf::StampedTransform 00143 (transform, 00144 t->header.stamp, 00145 t->header.frame_id, 00146 childFrameName_)); 00147 } 00148 00149 publisher_.publish (t); 00150 } 00151 00152 } // end of namespace evart.