tracker.cpp
Go to the documentation of this file.
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.


evart_bridge
Author(s): Thomas Moulard/thomas.moulard@gmail.com
autogenerated on Fri Jan 3 2014 11:30:22