From e4b18b275f2299a898e15c8ee0a3a79eaf7037e2 Mon Sep 17 00:00:00 2001 From: Jennifer Buehler <jennifer.e.buehler@gmail.com> Date: Sun, 6 Mar 2016 23:28:20 +0100 Subject: [PATCH] added tf object broadcaster and generation of simple grasp message --- gazebo_state_plugins/CMakeLists.txt | 4 +- gazebo_state_plugins/package.xml | 2 + gazebo_state_plugins/src/GazeboObjectInfo.cpp | 33 +++++---- .../config/FakeObjectRecognizer.yaml | 5 +- .../config/ObjectTFBroadcaster.yaml | 9 +++ .../gazebo_test_tools/FakeObjectRecognizer.h | 22 +++++- .../launch/fake_object_recognizer.launch | 19 ++++- .../gazebo_fake_object_recognition.launch | 2 +- .../launch/object_tf_broadcaster.launch | 6 ++ .../launch/spawn_and_recognize_cube.launch | 5 ++ .../src/FakeObjectRecognizer.cpp | 72 +++++++++++++------ 11 files changed, 140 insertions(+), 39 deletions(-) create mode 100644 gazebo_test_tools/config/ObjectTFBroadcaster.yaml create mode 100644 gazebo_test_tools/launch/object_tf_broadcaster.launch create mode 100644 gazebo_test_tools/launch/spawn_and_recognize_cube.launch diff --git a/gazebo_state_plugins/CMakeLists.txt b/gazebo_state_plugins/CMakeLists.txt index 6557029..a03c3aa 100644 --- a/gazebo_state_plugins/CMakeLists.txt +++ b/gazebo_state_plugins/CMakeLists.txt @@ -14,6 +14,7 @@ find_package( std_msgs gazebo_ros object_msgs + object_msgs_tools eigen_conversions ) @@ -36,7 +37,8 @@ find_package(gazebo REQUIRED) catkin_package( # INCLUDE_DIRS include LIBRARIES gazebo_state_plugins gazebo_map_publisher - CATKIN_DEPENDS geometry_msgs roscpp shape_msgs std_msgs gazebo_ros + CATKIN_DEPENDS geometry_msgs roscpp shape_msgs std_msgs gazebo_world_plugin_loader + gazebo_ros object_msgs object_msgs_tools eigen_conversions # DEPENDS system_lib ) diff --git a/gazebo_state_plugins/package.xml b/gazebo_state_plugins/package.xml index 062325a..50c398a 100644 --- a/gazebo_state_plugins/package.xml +++ b/gazebo_state_plugins/package.xml @@ -48,9 +48,11 @@ <build_depend>shape_msgs</build_depend> <build_depend>std_msgs</build_depend> <build_depend>object_msgs</build_depend> + <build_depend>object_msgs_tools</build_depend> <build_depend>eigen_conversions</build_depend> <run_depend>gazebo_world_plugin_loader</run_depend> <run_depend>object_msgs</run_depend> + <run_depend>object_msgs_tools</run_depend> <run_depend>eigen_conversions</run_depend> <run_depend>geometry_msgs</run_depend> <run_depend>roscpp</run_depend> diff --git a/gazebo_state_plugins/src/GazeboObjectInfo.cpp b/gazebo_state_plugins/src/GazeboObjectInfo.cpp index f1eed13..5ce7730 100644 --- a/gazebo_state_plugins/src/GazeboObjectInfo.cpp +++ b/gazebo_state_plugins/src/GazeboObjectInfo.cpp @@ -1,5 +1,5 @@ #include <gazebo_state_plugins/GazeboObjectInfo.h> - +#include <object_msgs_tools/ObjectFunctions.h> #include <gazebo/physics/Link.hh> #include <gazebo/physics/BoxShape.hh> #include <gazebo/physics/SphereShape.hh> @@ -60,7 +60,7 @@ bool GazeboObjectInfo::requestObject(object_msgs::ObjectInfo::Request &req, obje physics::ModelPtr model=world->GetModel(modelName); if (!model.get()) { - ROS_ERROR("Model %s not found",modelName.c_str()); + // ROS_ERROR("Model %s not found",modelName.c_str()); res.success=false; return true; } @@ -164,8 +164,8 @@ shape_msgs::SolidPrimitive * GazeboObjectInfo::getSolidPrimitive(physics::Collis } -GazeboObjectInfo::ObjectMsg GazeboObjectInfo::createBoundingBoxObject(physics::ModelPtr& model, bool include_shape){ - +GazeboObjectInfo::ObjectMsg GazeboObjectInfo::createBoundingBoxObject(physics::ModelPtr& model, bool include_shape) +{ GazeboObjectInfo::ObjectMsg obj; physics::Link_V links=model->GetLinks(); @@ -174,21 +174,23 @@ GazeboObjectInfo::ObjectMsg GazeboObjectInfo::createBoundingBoxObject(physics::M obj.name=model->GetName(); obj.header.stamp=ros::Time::now(); obj.header.frame_id=ROOT_FRAME_ID; - - for (l_it=links.begin(); l_it!=links.end(); ++l_it){ - + // obj.type = no object type given + // the custum origin (Object::origin) is going to be set to the first link encountered + bool origin_init = false; + for (l_it=links.begin(); l_it!=links.end(); ++l_it) + { physics::LinkPtr link=*l_it; std::string linkName=link->GetName(); - math::Pose link_pose=link->GetWorldPose (); + math::Pose link_pose=link->GetWorldPose(); //ROS_INFO("Link for model %s: %s, pos %f %f %f",model->GetName().c_str(),link->GetName().c_str(),link_pose.pos.x,link_pose.pos.y,link_pose.pos.z); //ROS_INFO("Link found for model %s: %s",model->GetName().c_str(),link->GetName().c_str()); physics::Collision_V colls=link->GetCollisions(); physics::Collision_V::iterator cit; - for (cit=colls.begin(); cit!=colls.end(); ++cit) { - + for (cit=colls.begin(); cit!=colls.end(); ++cit) + { physics::CollisionPtr c=*cit; math::Pose rel_pose=c->GetRelativePose(); @@ -208,7 +210,11 @@ GazeboObjectInfo::ObjectMsg GazeboObjectInfo::createBoundingBoxObject(physics::M pose.orientation.w=coll_pose.rot.w; obj.primitive_poses.push_back(pose); - + + if (!origin_init) + { + obj.origin = pose; + } if (include_shape) { @@ -225,9 +231,12 @@ GazeboObjectInfo::ObjectMsg GazeboObjectInfo::createBoundingBoxObject(physics::M obj.content=GazeboObjectInfo::ObjectMsg::POSE; //ROS_INFO("Pub pose for %s (%s %s)",c->GetName().c_str(),link->GetName().c_str(),model->GetName().c_str()); } - } } + + obj.primitive_origin = GazeboObjectInfo::ObjectMsg::ORIGIN_AVERAGE; + obj.mesh_origin = GazeboObjectInfo::ObjectMsg::ORIGIN_UNDEFINED; + return obj; } diff --git a/gazebo_test_tools/config/FakeObjectRecognizer.yaml b/gazebo_test_tools/config/FakeObjectRecognizer.yaml index d0a5ff7..ee42bf6 100644 --- a/gazebo_test_tools/config/FakeObjectRecognizer.yaml +++ b/gazebo_test_tools/config/FakeObjectRecognizer.yaml @@ -13,4 +13,7 @@ publish_recognition_rate: 10 # can be requested. request_object_service: "/gazebo_objects/get_info" - +# service of under which a object_msgs_tools/RegisterObject can +# be sent in order to start publishing /tf information about an +# object. +register_object_tf_service: "/object_tf_broadcaster/register_object" diff --git a/gazebo_test_tools/config/ObjectTFBroadcaster.yaml b/gazebo_test_tools/config/ObjectTFBroadcaster.yaml new file mode 100644 index 0000000..03c9a57 --- /dev/null +++ b/gazebo_test_tools/config/ObjectTFBroadcaster.yaml @@ -0,0 +1,9 @@ +# configuration file for publishing object information to /tf, using the same +# topic names configured for the fake object recogniser. +# For documentation of the fileds see also $(find object_msgs_tools)/config/ObjectTFBroadcaster.yaml. + +object_topic: "" +register_object_service: "/object_tf_broadcaster/register_object" +object_service: "/gazebo_objects/get_info" +publish_tf_rate: 100 +query_object_info_rate: 1 diff --git a/gazebo_test_tools/include/gazebo_test_tools/FakeObjectRecognizer.h b/gazebo_test_tools/include/gazebo_test_tools/FakeObjectRecognizer.h index bc2889b..1774cff 100644 --- a/gazebo_test_tools/include/gazebo_test_tools/FakeObjectRecognizer.h +++ b/gazebo_test_tools/include/gazebo_test_tools/FakeObjectRecognizer.h @@ -55,7 +55,18 @@ private: void publishRecognitionEvent(const ros::TimerEvent& e); - bool getGazeboObject(const std::string& name, object_msgs::Object& object, bool include_geometry); + /** + * Like queryObjectInfo but waits a maximum of \e timeout and re-requests + * the information every \e checkStep seconds. + */ + bool waitForQueryObjectInfo(const std::string& name, object_msgs::Object& object, + bool include_geometry, float timeout, float checkStep, bool printErrors); + + /** + * Uses the object information service to request object information + */ + bool queryObjectInfo(const std::string& name, object_msgs::Object& object, + bool include_geometry, bool printErrors); std::string OBJECTS_TOPIC; @@ -67,12 +78,19 @@ private: // an object, of type gazebo_test_tools/TriggerRecognition.srv. std::string SERVICE_RECOGNISE_OBJECT_TOPIC; + + // service of under which a object_msgs_tools/RegisterObject can + // be sent in order to start publishing /tf information about an + // object. + std::string SERVICE_REGISTER_OBJECT_TF_TOPIC; + // Recognised objects which are to be continuously published // as recognised are published at this rate. float PUBLISH_RECOGNISED_OBJECT_RATE; ros::Publisher object_pub; ros::ServiceClient object_info_client; + ros::ServiceClient register_object_tf_client; ros::ServiceServer recognize_object_srv; @@ -83,6 +101,8 @@ private: boost::mutex addedObjectsMtx; ros::Timer publishTimer; + + ros::NodeHandle node; }; } // namespace gazebo_test_tools diff --git a/gazebo_test_tools/launch/fake_object_recognizer.launch b/gazebo_test_tools/launch/fake_object_recognizer.launch index 402a836..e7516c1 100644 --- a/gazebo_test_tools/launch/fake_object_recognizer.launch +++ b/gazebo_test_tools/launch/fake_object_recognizer.launch @@ -1,12 +1,27 @@ <launch> - + # configuration file for the fake object recogniser <arg name="config_file" default="$(find gazebo_test_tools)/config/FakeObjectRecognizer.yaml"/> + # load ROS parameters from configuratoin file <rosparam ns="gazebo_test_tools" file="$(arg config_file)"/> # name of the node <arg name="node_name" default="fake_object_recognizer"/> - + + ##################################### + # Lauch the fake object recogniser node + ##################################### <node name="$(arg node_name)" pkg="gazebo_test_tools" type="fake_object_recognizer_node" respawn="true" output="screen"/> + + ##################################### + # Load the object tf publisher along + # with the fake object detector so that + # recognised objects also can + # get published on tf + ##################################### + <include file="$(find gazebo_test_tools)/launch/object_tf_broadcaster.launch"> + # use the default config file profided in this package + <arg name="config_file" value="$(find gazebo_test_tools)/config/ObjectTFBroadcaster.yaml"/> + </include> </launch> diff --git a/gazebo_test_tools/launch/gazebo_fake_object_recognition.launch b/gazebo_test_tools/launch/gazebo_fake_object_recognition.launch index 8865f4c..1d1eb72 100644 --- a/gazebo_test_tools/launch/gazebo_fake_object_recognition.launch +++ b/gazebo_test_tools/launch/gazebo_fake_object_recognition.launch @@ -9,7 +9,7 @@ # Load Gazebo fake object detector ##################################### <include file="$(find gazebo_test_tools)/launch/fake_object_recognizer.launch"> - # use the default config file + # use the default config file profided in this package <arg name="config_file" value="$(find gazebo_test_tools)/config/FakeObjectRecognizer.yaml"/> </include> </launch> diff --git a/gazebo_test_tools/launch/object_tf_broadcaster.launch b/gazebo_test_tools/launch/object_tf_broadcaster.launch new file mode 100644 index 0000000..85ecf35 --- /dev/null +++ b/gazebo_test_tools/launch/object_tf_broadcaster.launch @@ -0,0 +1,6 @@ +<launch> + <arg name="config_file" default="$(find gazebo_test_tools)/config/ObjectTFBroadcaster.yaml"/> + <include file="$(find object_msgs_tools)/launch/object_tf_broadcaster.launch"> + <arg name="config_file" value="$(arg config_file)"/> + </include> +</launch> diff --git a/gazebo_test_tools/launch/spawn_and_recognize_cube.launch b/gazebo_test_tools/launch/spawn_and_recognize_cube.launch new file mode 100644 index 0000000..8a79ff3 --- /dev/null +++ b/gazebo_test_tools/launch/spawn_and_recognize_cube.launch @@ -0,0 +1,5 @@ +<launch> + <node name="test_cube_spawn" pkg="gazebo_test_tools" type="cube_spawner" respawn="false" output="screen" args="cube1 0 0 1"/> + <node name="test_recognise_cube" pkg="gazebo_test_tools" type="fake_object_recognizer_cmd" respawn="false" output="screen" args="cube1 1"/> +</launch> + diff --git a/gazebo_test_tools/src/FakeObjectRecognizer.cpp b/gazebo_test_tools/src/FakeObjectRecognizer.cpp index 4e3c964..3fec06a 100644 --- a/gazebo_test_tools/src/FakeObjectRecognizer.cpp +++ b/gazebo_test_tools/src/FakeObjectRecognizer.cpp @@ -1,4 +1,5 @@ #include <gazebo_test_tools/FakeObjectRecognizer.h> +#include <object_msgs/RegisterObject.h> #include <boost/thread.hpp> #include <iostream> @@ -6,6 +7,7 @@ #define DEFAULT_OBJECTS_TOPIC "world/objects" #define DEFAULT_SERVICE_REQUEST_OBJECT_TOPIC "world/request_object" #define DEFAULT_SERVICE_RECOGNISE_OBJECT_TOPIC "/recognize_object" +#define DEFAULT_SERVICE_REGISTER_OBJECT_TF_TOPIC "/register_object" #define DEFAULT_PUBLISH_RECOGNISED_OBJECT_RATE 1 using gazebo_test_tools::FakeObjectRecognizer; @@ -19,24 +21,23 @@ FakeObjectRecognizer::FakeObjectRecognizer() { _node.param<std::string>("request_object_service", SERVICE_REQUEST_OBJECT_TOPIC, DEFAULT_SERVICE_REQUEST_OBJECT_TOPIC); ROS_INFO("Got object service topic name: <%s>", SERVICE_REQUEST_OBJECT_TOPIC.c_str()); - SERVICE_RECOGNISE_OBJECT_TOPIC= DEFAULT_SERVICE_RECOGNISE_OBJECT_TOPIC; - _node.param<std::string>("recognize_object_service", SERVICE_RECOGNISE_OBJECT_TOPIC,SERVICE_RECOGNISE_OBJECT_TOPIC); + _node.param<std::string>("recognize_object_service", SERVICE_RECOGNISE_OBJECT_TOPIC, DEFAULT_SERVICE_RECOGNISE_OBJECT_TOPIC); + + _node.param<std::string>("register_object_tf_service", SERVICE_REGISTER_OBJECT_TF_TOPIC, DEFAULT_SERVICE_REGISTER_OBJECT_TF_TOPIC); + ROS_INFO("Got register object tf service topic name: <%s>", SERVICE_REGISTER_OBJECT_TF_TOPIC.c_str()); - std::stringstream def_coll_rate; - def_coll_rate<<DEFAULT_PUBLISH_RECOGNISED_OBJECT_RATE; - std::string _PUBLISH_RECOGNISED_OBJECT_RATE=def_coll_rate.str(); - _node.param<std::string>("publish_recognition_rate", _PUBLISH_RECOGNISED_OBJECT_RATE, _PUBLISH_RECOGNISED_OBJECT_RATE); - PUBLISH_RECOGNISED_OBJECT_RATE=atof(_PUBLISH_RECOGNISED_OBJECT_RATE.c_str()); + int PUBLISH_RECOGNISED_OBJECT_RATE; + _node.param<int>("publish_recognition_rate", PUBLISH_RECOGNISED_OBJECT_RATE, PUBLISH_RECOGNISED_OBJECT_RATE); - ros::NodeHandle nodePub(""); - if (SERVICE_REQUEST_OBJECT_TOPIC!="") object_info_client = nodePub.serviceClient<object_msgs::ObjectInfo>(SERVICE_REQUEST_OBJECT_TOPIC); + if (!SERVICE_REQUEST_OBJECT_TOPIC.empty()) object_info_client = node.serviceClient<object_msgs::ObjectInfo>(SERVICE_REQUEST_OBJECT_TOPIC); + if (!SERVICE_REGISTER_OBJECT_TF_TOPIC.empty()) register_object_tf_client = node.serviceClient<object_msgs::RegisterObject>(SERVICE_REGISTER_OBJECT_TF_TOPIC); - recognize_object_srv = nodePub.advertiseService(SERVICE_RECOGNISE_OBJECT_TOPIC, &FakeObjectRecognizer::recognizeObject,this); + recognize_object_srv = node.advertiseService(SERVICE_RECOGNISE_OBJECT_TOPIC, &FakeObjectRecognizer::recognizeObject,this); - object_pub = nodePub.advertise<object_msgs::Object>(OBJECTS_TOPIC, 100); + object_pub = node.advertise<object_msgs::Object>(OBJECTS_TOPIC, 100); ros::Rate rate(PUBLISH_RECOGNISED_OBJECT_RATE); - publishTimer=nodePub.createTimer(rate,&FakeObjectRecognizer::publishRecognitionEvent, this); + publishTimer=node.createTimer(rate,&FakeObjectRecognizer::publishRecognitionEvent, this); } FakeObjectRecognizer::~FakeObjectRecognizer() { @@ -53,9 +54,9 @@ void FakeObjectRecognizer::publishRecognitionEvent(const ros::TimerEvent& e) { // get the object information. Only the pose is required because // the shape has been published in recognizeObject() already and // it only needs to be published once when the object is first added. - if (!getGazeboObject(*it,object,false)) + if (!queryObjectInfo(*it,object,false, true)) { - ROS_ERROR_STREAM("Could not find Gazebo object "<<*it); + ROS_ERROR_STREAM("Could not find object "<<*it); continue; } object_pub.publish(object); @@ -65,7 +66,7 @@ void FakeObjectRecognizer::publishRecognitionEvent(const ros::TimerEvent& e) { bool FakeObjectRecognizer::recognizeObject(gazebo_test_tools::RecognizeGazeboObject::Request &req, gazebo_test_tools::RecognizeGazeboObject::Response &res) { - ROS_INFO_STREAM("Recognizing gazebo object "<<req.name); + ROS_INFO_STREAM("Recognizing object "<<req.name); res.success=true; boost::unique_lock<boost::mutex> lock(addedObjectsMtx); @@ -91,29 +92,58 @@ bool FakeObjectRecognizer::recognizeObject(gazebo_test_tools::RecognizeGazeboObj if (req.republish) addedObjects.insert(req.name); object_msgs::Object object; - if (!getGazeboObject(req.name,object,true)) + // try this for a while, because sometimes when an object has just been + // created / spawned, it may take a while for the service to return + // information about it (before that it can't find it, e.g. if an object + // is spawned in Gazebo and right after the recognition is triggered) + float timeout = 3; + float checkStep = 0.5; + if (!waitForQueryObjectInfo(req.name,object,true, timeout, checkStep, false)) { - ROS_ERROR_STREAM("Could not find Gazebo object "<<req.name); + ROS_ERROR_STREAM("Could not find object "<<req.name); res.success=false; return true; } - ROS_INFO_STREAM("Publishing object "<<object); + // ROS_INFO_STREAM("Publishing object "<<object); object_pub.publish(object); + + // now, also register this object to be broadcasted in tf: + object_msgs::RegisterObject srv; + srv.request.name = object.name; + if (register_object_tf_client.call(srv)) + { + ROS_INFO("FakeObjectRecogniser: Register tf result:"); + std::cout<<srv.response<<std::endl; + } return true; } +bool FakeObjectRecognizer::waitForQueryObjectInfo(const std::string& name, object_msgs::Object& object, + bool include_geometry, float timeout, float checkStep, bool printErrors) +{ + ros::Time startTime=ros::Time::now(); + float timeWaited = 0; + while (timeWaited < timeout) + { + if (queryObjectInfo(name, object, include_geometry, printErrors)) return true; + ros::Duration(checkStep).sleep(); + ros::Time currTime = ros::Time::now(); + timeWaited = (currTime-startTime).toSec(); + } + return false; +} -bool FakeObjectRecognizer::getGazeboObject(const std::string& name, object_msgs::Object& object, bool include_geometry){ +bool FakeObjectRecognizer::queryObjectInfo(const std::string& name, object_msgs::Object& object, bool include_geometry, bool printErrors){ object_msgs::ObjectInfo srv; srv.request.name=name; srv.request.get_geometry=include_geometry; if (!object_info_client.call(srv)){ - ROS_ERROR("Could not get object %s because service request failed.",name.c_str()); + if (printErrors) ROS_ERROR("Could not get object %s because service request failed.",name.c_str()); return false; } if (!srv.response.success) { - ROS_ERROR("Could not get object %s because it does not exist in Gazebo.",name.c_str()); + if (printErrors) ROS_ERROR("Could not get object %s because it does not exist.",name.c_str()); return false; } object=srv.response.object; -- GitLab