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 #ifndef ROS_BINDINGS_PROBLEM
00027 #define ROS_BINDINGS_PROBLEM
00028
00029 #include "plugindefs.h"
00030 #include <tf/transform_listener.h>
00031 #include <posedetection_msgs/ObjectDetection.h>
00032 #include <ros/package.h>
00033 #include <boost/filesystem/operations.hpp>
00034
00035 #include <ros/ros.h>
00036
00037 #include <actionlib/client/simple_action_client.h>
00038
00039
00040
00041 class ROSBindings : public ProblemInstance
00042 {
00043 public:
00044 ROSBindings(EnvironmentBasePtr penv) : ProblemInstance(penv), _bDestroyThread(true) {
00045 __description = ":Interface Author: Rosen Diankov\n\nBindings Simplifying integration with ROS";
00046 RegisterCommand("SetLocalizationFromTF",boost::bind(&ROSBindings::SetLocalizationFromTF,this,_1,_2),
00047 "Set a robot's navigation from a published tf frame");
00048 RegisterCommand("SetLocalizationFromDetection",boost::bind(&ROSBindings::SetLocalizationFromDetection,this,_1,_2),
00049 "Set a robot's navigation from a published object");
00050
00051
00052
00053
00054 }
00055 virtual ~ROSBindings() {
00056 Destroy();
00057 }
00058
00059 virtual void Destroy()
00060 {
00061 _bDestroyThread = true;
00062 _localizingrobots.clear();
00063 _tflistener.reset();
00064 _ros.reset();
00065 _threadros.join();
00066 {
00067 boost::mutex::scoped_lock lock(_mutexrobots);
00068 _listUpdatedRobots.clear();
00069 }
00070 ProblemInstance::Destroy();
00071 }
00072
00073 virtual void Reset()
00074 {
00075 _localizingrobots.clear();
00076 {
00077 boost::mutex::scoped_lock lock(_mutexrobots);
00078 _listUpdatedRobots.clear();
00079 }
00080 ProblemInstance::Reset();
00081 }
00082
00083 virtual int main(const std::string& args)
00084 {
00085 stringstream ss(args);
00086
00087 _bDestroyThread = false;
00088
00089 int argc=0;
00090 ros::init(argc,NULL,"openrave", ros::init_options::NoSigintHandler|ros::init_options::AnonymousName);
00091
00092 if( !ros::master::check() ) {
00093 RAVELOG_WARN("failed to create ros\n");
00094 return -1;
00095 }
00096 _ros.reset(new ros::NodeHandle());
00097 _threadros = boost::thread(boost::bind(&ROSBindings::_threadrosfn, this));
00098 _tflistener.reset(new tf::TransformListener(*_ros));
00099 return 0;
00100 }
00101
00102 virtual bool SimulationStep(dReal fElapsedTime)
00103 {
00104 boost::mutex::scoped_lock lock(_mutexrobots);
00105 FOREACH(it,_listUpdatedRobots)
00106 it->first->SetTransform(it->second);
00107 _listUpdatedRobots.clear();
00108 return false;
00109 }
00110
00111 virtual bool SendCommand(std::ostream& sout, std::istream& sinput)
00112 {
00113 EnvironmentMutex::scoped_lock lock(GetEnv()->GetMutex());
00114 return ProblemInstance::SendCommand(sout,sinput);
00115 }
00116 protected:
00117 inline boost::shared_ptr<ROSBindings> shared_problem() {
00118 return boost::static_pointer_cast<ROSBindings>(shared_from_this());
00119 }
00120 inline boost::shared_ptr<ROSBindings const> shared_problem_const() const {
00121 return boost::static_pointer_cast<ROSBindings const>(shared_from_this());
00122 }
00123
00124 virtual void _threadrosfn()
00125 {
00126 while(!_bDestroyThread && ros::ok()) {
00127 ros::spinOnce();
00128 usleep(1000);
00129 }
00130 }
00131
00132 void UpdateRobotFromTF(const ros::WallTimerEvent& event, RobotBasePtr probot, string mapframe, geometry_msgs::PoseStamped posestamped)
00133 {
00134
00135 geometry_msgs::PoseStamped poseout;
00136 try {
00137
00138 _tflistener->transformPose(mapframe, posestamped, poseout);
00139 boost::mutex::scoped_lock lock(_mutexrobots);
00140 _listUpdatedRobots.push_back(make_pair(probot,GetTransform(poseout.pose)));
00141 }
00142 catch(std::runtime_error& ex) {
00143 RAVELOG_DEBUG(str(boost::format("failed to get tf frames %s robot %s: %s\n")%posestamped.header.frame_id%probot->GetName()%ex.what()));
00144 }
00145 }
00146
00147 bool SetLocalizationFromTF(ostream& sout, istream& sinput)
00148 {
00149 string cmd, mapframe="/map";
00150 RobotBasePtr probot;
00151 geometry_msgs::PoseStamped posestamped; posestamped.pose = GetPose(Transform());
00152 while(!sinput.eof()) {
00153 sinput >> cmd;
00154 if( !sinput )
00155 break;
00156 std::transform(cmd.begin(), cmd.end(), cmd.begin(), ::tolower);
00157
00158 if( cmd == "robot" ) {
00159 string robotname;
00160 sinput >> robotname;
00161 probot = GetEnv()->GetRobot(robotname);
00162 }
00163 else if( cmd == "map" )
00164 sinput >> mapframe;
00165 else if( cmd == "offset" ) {
00166 Transform toffset;
00167 sinput >> toffset;
00168 posestamped.pose = GetPose(toffset);
00169 }
00170 else {
00171 RAVELOG_WARNA(str(boost::format("unrecognized command: %s\n")%cmd));
00172 break;
00173 }
00174
00175 if( !sinput ) {
00176 RAVELOG_ERRORA(str(boost::format("failed processing command %s\n")%cmd));
00177 return false;
00178 }
00179 }
00180
00181 BOOST_ASSERT(!!probot);
00182 posestamped.header.frame_id = probot->GetLinks().at(0)->GetName();
00183 _localizingrobots[probot] = boost::shared_ptr<ros::WallTimer>(new ros::WallTimer(_ros->createWallTimer(ros::WallDuration(0.01), boost::bind(&ROSBindings::UpdateRobotFromTF,this,_1,probot,mapframe,posestamped))));
00184 return true;
00185 }
00186
00187 virtual void UpdateRobotFromDetection(const boost::shared_ptr<posedetection_msgs::ObjectDetection const>& topicmsg, RobotBasePtr probot, bool b2DLocalization)
00188 {
00189 if( topicmsg->objects.size() == 0 )
00190 return;
00191
00192 boost::mutex::scoped_lock lock(_mutexrobots);
00193 geometry_msgs::PoseStamped posestamped, poseout;
00194 Transform tnew;
00195 string strrobotbaselink = probot->GetLinks().at(0)->GetName();
00196 vector<KinBodyPtr> vbodies;
00197 GetEnv()->GetBodies(vbodies);
00198 FOREACHC(itobj,topicmsg->objects) {
00199 string objfilename = resolveName(itobj->type);
00200 if( objfilename.size() > 0 ) {
00201 boost::filesystem::path absfilename = boost::filesystem::path(objfilename);
00202 FOREACH(itbody,vbodies) {
00203 if( boost::filesystem::equivalent(absfilename, boost::filesystem::path((*itbody)->GetXMLFilename())) ) {
00204 posestamped.pose = GetPose(GetTransform(itobj->pose));
00205 posestamped.header = topicmsg->header;
00206
00207 try {
00208 _tflistener->transformPose(strrobotbaselink, posestamped, poseout);
00209 tnew = GetTransform(poseout.pose).inverse() * (*itbody)->GetTransform();
00210 }
00211 catch(std::runtime_error& ex) {
00212 try {
00213
00214 posestamped.header.stamp = ros::Time();
00215 _tflistener->transformPose(strrobotbaselink, posestamped, poseout);
00216 tnew = GetTransform(poseout.pose).inverse() * (*itbody)->GetTransform();
00217 }
00218 catch(std::runtime_error& ex) {
00219 RAVELOG_WARNA("failed to get tf frames %s (body link:%s) for object %s\n",posestamped.header.frame_id.c_str(), strrobotbaselink.c_str(), itobj->type.c_str());
00220 continue;
00221 }
00222 }
00223
00224 if( b2DLocalization ) {
00225 Transform trobot = probot->GetTransform();
00226 dReal zanglediffd2 = RaveAtan2(tnew.rot.w,tnew.rot.x) - RaveAtan2(trobot.rot.w,trobot.rot.x);
00227 trobot.rot = quatMultiply(Vector(RaveCos(zanglediffd2),0,0,RaveSin(zanglediffd2)),trobot.rot);
00228 trobot.trans.x = tnew.trans.x;
00229 trobot.trans.y = tnew.trans.y;
00230 _listUpdatedRobots.push_back(make_pair(probot,trobot));
00231 }
00232 else
00233 _listUpdatedRobots.push_back(make_pair(probot,tnew));
00234 return;
00235 }
00236 }
00237 }
00238 }
00239 }
00240
00241 bool SetLocalizationFromDetection(ostream& sout, istream& sinput)
00242 {
00243 string cmd, topic;
00244 RobotBasePtr probot;
00245 uint32_t queuesize = 1;
00246 bool b2DLocalization=true;
00247 geometry_msgs::PoseStamped posestamped; posestamped.pose = GetPose(Transform());
00248 while(!sinput.eof()) {
00249 sinput >> cmd;
00250 if( !sinput )
00251 break;
00252 std::transform(cmd.begin(), cmd.end(), cmd.begin(), ::tolower);
00253
00254 if( cmd == "robot" ) {
00255 string robotname;
00256 sinput >> robotname;
00257 probot = GetEnv()->GetRobot(robotname);
00258 }
00259 else if( cmd == "topic" )
00260 sinput >> topic;
00261 else if( cmd == "queuesize" )
00262 sinput >> queuesize;
00263 else if( cmd == "6dlocalization" )
00264 b2DLocalization = false;
00265 else {
00266 RAVELOG_WARNA(str(boost::format("unrecognized command: %s\n")%cmd));
00267 break;
00268 }
00269
00270 if( !sinput ) {
00271 RAVELOG_ERRORA(str(boost::format("failed processing command %s\n")%cmd));
00272 return false;
00273 }
00274 }
00275
00276 if( !probot )
00277 return false;
00278 ros::Subscriber sub = _ros->subscribe<posedetection_msgs::ObjectDetection>(topic,queuesize,boost::bind(&ROSBindings::UpdateRobotFromDetection,this,_1,probot, b2DLocalization));
00279 if( !sub )
00280 return false;
00281 _localizingrobots[probot] = boost::shared_ptr<ros::Subscriber>(new ros::Subscriber(sub));
00282 return true;
00283 }
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355 boost::shared_ptr<tf::TransformListener> _tflistener;
00356 boost::shared_ptr<ros::NodeHandle> _ros;
00357 map<RobotBasePtr,boost::shared_ptr<void> > _localizingrobots;
00358 list<pair<RobotBasePtr,Transform> > _listUpdatedRobots;
00359 boost::thread _threadros;
00360 boost::mutex _mutexrobots;
00361 bool _bDestroyThread;
00362 };
00363
00364 #endif