rosbindings.h
Go to the documentation of this file.
00001 // Software License Agreement (BSD License)
00002 // Copyright (c) 2010, Rosen Diankov
00003 // Redistribution and use in source and binary forms, with or without
00004 // modification, are permitted provided that the following conditions are met:
00005 //   * Redistributions of source code must retain the above copyright notice,
00006 //     this list of conditions and the following disclaimer.
00007 //   * Redistributions in binary form must reproduce the above copyright
00008 //     notice, this list of conditions and the following disclaimer in the
00009 //     documentation and/or other materials provided with the distribution.
00010 //   * The name of the author may not be used to endorse or promote products
00011 //     derived from this software without specific prior written permission.
00012 //
00013 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00014 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00015 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00016 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00017 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00018 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00019 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00020 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00021 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00022 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00023 // POSSIBILITY OF SUCH DAMAGE.
00024 //
00025 // \author Rosen Diankov
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 //#include <move_base_msgs/MoveBaseAction.h>
00037 #include <actionlib/client/simple_action_client.h>
00038 
00039 //typedef actionlib::SimpleActionClient<move_base_msgs::MoveBaseAction> MoveBaseClient;
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 //        RegisterCommand("MoveBase",boost::bind(&ROSBindings::MoveBase,this,_1,_2),
00051 //                        "Uses ROS's navigation stack to move the base");
00052 //        RegisterCommand("MoveBase",boost::bind(&ROSBindings::ShowPointCloud,this,_1,_2),
00053 //                        "Uses ROS's navigation stack to move the base");
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); // query every 1ms?
00129         }
00130     }
00131 
00132     void UpdateRobotFromTF(const ros::WallTimerEvent& event, RobotBasePtr probot, string mapframe, geometry_msgs::PoseStamped posestamped)
00133     {
00134         //RAVELOG_INFO(str(boost::format("updating robot %s\n")%probot->GetName()));
00135         geometry_msgs::PoseStamped poseout;
00136         try {
00137             //posestamped.header.stamp = ros::Time();
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                                 // try getting the latest value by passing a 0 timestamp
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; //tnew = GetTransform(itobj->pose);
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     /*    bool MoveBase(ostream& sout, istream& sinput)
00286     {
00287         string cmd;
00288         string action="move_base";
00289         move_base_msgs::MoveBaseGoal goal;
00290         goal.target_pose.header.frame_id = "map";
00291         bool bHasGoal=false;
00292         while(!sinput.eof()) {
00293             sinput >> cmd;
00294             if( !sinput )
00295                 break;
00296             std::transform(cmd.begin(), cmd.end(), cmd.begin(), ::tolower);
00297 
00298             if( cmd == "frame_id" )
00299                 sinput >> goal.target_pose.header.frame_id;
00300             else if( cmd == "action" )
00301                 sinput >> action;
00302             else if( cmd == "goal" ) {
00303                 Transform t;
00304                 sinput >> t;
00305                 goal.target_pose.pose.position.x = t.trans.x;
00306                 goal.target_pose.pose.position.y = t.trans.y;
00307                 goal.target_pose.pose.position.z = t.trans.z;
00308                 goal.target_pose.pose.orientation.x = t.rot.y;
00309                 goal.target_pose.pose.orientation.y = t.rot.z;
00310                 goal.target_pose.pose.orientation.z = t.rot.w;
00311                 goal.target_pose.pose.orientation.w = t.rot.x;
00312                 bHasGoal = true;
00313             }
00314             else {
00315                 RAVELOG_WARNA(str(boost::format("unrecognized command: %s\n")%cmd));
00316                 break;
00317             }
00318 
00319             if( !sinput ) {
00320                 RAVELOG_ERRORA(str(boost::format("failed processing command %s\n")%cmd));
00321                 return false;
00322             }
00323         }
00324 
00325         if( !bHasGoal ) {
00326             RAVELOG_WARN("no goal specified\n");
00327             return false;
00328         }
00329         MoveBaseClient ac(action, true);
00330 
00331         //wait for the action server to come up
00332         if(!ac.waitForServer(ros::Duration(5.0))) {
00333             ROS_INFO("could not start action server");
00334             return false;
00335         }
00336 
00337         goal.target_pose.header.stamp = ros::Time::now();
00338 
00339         RAVELOG_INFO("Sending goal, press 'c' to cancel\n");
00340         ac.sendGoal(goal);
00341         while(!ac.waitForResult(ros::Duration(1.0)) ) {
00342             GetEnv()->UpdatePublishedBodies();
00343             // check for some non-blocking method
00344 //            if( getchar() == 'c' ) {
00345 //                RAVELOG_WARN("canceling goal\n");
00346 //                ac.cancelGoal();
00347 //                return false;
00348 //            }
00349         }
00350         actionlib::SimpleClientGoalState state = ac.getState();
00351         RAVELOG_INFO(str(boost::format("goal status %s: %s\n")%state.toString()%state.getText()));
00352         return state == actionlib::SimpleClientGoalState::SUCCEEDED;
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines


orrosplanning
Author(s): Rosen Diankov (rosen.diankov@gmail.com)
autogenerated on Sat Mar 23 2013 22:32:59