$search
00001 /********************************************************************* 00002 * Software License Agreement (BSD License) 00003 * 00004 * Copyright (c) 2008, Willow Garage, Inc. 00005 * All rights reserved. 00006 * 00007 * Redistribution and use in source and binary forms, with or without 00008 * modification, are permitted provided that the following conditions 00009 * are met: 00010 * 00011 * * Redistributions of source code must retain the above copyright 00012 * notice, this list of conditions and the following disclaimer. 00013 * * Redistributions in binary form must reproduce the above 00014 * copyright notice, this list of conditions and the following 00015 * disclaimer in the documentation and/or other materials provided 00016 * with the distribution. 00017 * * Neither the name of the Willow Garage nor the names of its 00018 * contributors may be used to endorse or promote products derived 00019 * from this software without specific prior written permission. 00020 * 00021 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00022 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00023 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00024 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 00025 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00026 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00027 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00028 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00029 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00030 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 00031 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00032 * POSSIBILITY OF SUCH DAMAGE. 00033 *********************************************************************/ 00034 00035 00039 00040 #include <ros/ros.h> 00041 #include <urdf/model.h> 00042 00043 #include <tinyxml.h> 00044 00045 #include "LinearMath/btTransform.h" 00046 #include "LinearMath/btVector3.h" 00047 00048 #include <std_srvs/Empty.h> 00049 #include <gazebo_msgs/GetModelProperties.h> 00050 #include <gazebo_msgs/GetModelState.h> 00051 #include <gazebo_msgs/GetLinkState.h> 00052 #include <gazebo_msgs/SetLinkState.h> 00053 #include <gazebo_msgs/LinkState.h> 00054 #include <geometry_msgs/Pose.h> 00055 #include <gazebo/World.hh> 00056 #include <gazebo/Model.hh> 00057 #include <gazebo/Entity.hh> 00058 #include <gazebo/Body.hh> 00059 00060 #include <boost/shared_ptr.hpp> 00061 00062 void setup_transform(btTransform &transform, urdf::Pose pose) 00063 { 00064 btMatrix3x3 mat; 00065 mat.setRotation(btQuaternion(pose.rotation.x,pose.rotation.y,pose.rotation.z,pose.rotation.w)); 00066 transform = btTransform(mat,btVector3(pose.position.x,pose.position.y,pose.position.z)); 00067 } 00068 void setup_transform(btTransform &transform, geometry_msgs::Pose pose) 00069 { 00070 btMatrix3x3 mat; 00071 mat.setRotation(btQuaternion(pose.orientation.x,pose.orientation.y,pose.orientation.z,pose.orientation.w)); 00072 transform = btTransform(mat,btVector3(pose.position.x,pose.position.y,pose.position.z)); 00073 } 00074 00075 00076 void traverse_tree(boost::shared_ptr<const urdf::Link> link, const btTransform &transform, ros::ServiceClient set_link_state_client, std::string gazebo_model_name, int level = 0) 00077 { 00078 // keep track of local transform for recursion 00079 btTransform currentTransform = transform; 00080 00081 /* compute global transform */ 00082 btTransform localTransform; 00083 // this is the transform from parent link to current link 00084 // this transform does not exist for the root link 00085 if (link->parent_joint) 00086 { 00087 ROS_DEBUG("%s has a parent joint",link->name.c_str()); 00088 setup_transform(localTransform, link->parent_joint->parent_to_joint_origin_transform); 00089 currentTransform *= localTransform; 00090 00091 // get position 00092 btVector3 pz = currentTransform.getOrigin(); 00093 //double cpos[3] = { pz.x(), pz.y(), pz.z() }; 00094 // get rotation 00095 btMatrix3x3 mat = currentTransform.getBasis(); 00096 // mat.getRPY is broken, get back quaternion, use urdf::Rotation to get from quaternion to rpy 00097 btQuaternion btq; 00098 mat.getRotation(btq); 00099 //urdf::Rotation q(btq.x(),btq.y(),btq.z(),btq.w()); 00100 00101 // massless bodies are not simulated 00102 if (link->inertial && link->inertial->mass != 0) 00103 { 00104 if (link->parent_joint->type == urdf::Joint::PRISMATIC) 00105 { 00106 double joint_position = 0.5; 00107 btVector3 axis( link->parent_joint->axis.x,link->parent_joint->axis.y,link->parent_joint->axis.z ); 00108 pz += joint_position * axis; 00109 00110 } 00111 else if (link->parent_joint->type == urdf::Joint::REVOLUTE || 00112 link->parent_joint->type == urdf::Joint::CONTINUOUS) 00113 { 00114 // rotate joint by some angle about joint axis 00115 btVector3 axis( link->parent_joint->axis.x,link->parent_joint->axis.y,link->parent_joint->axis.z ); 00116 double test_joint_angle = -0.5; 00117 btQuaternion joint_rot(axis,test_joint_angle); // TEST! try .1 radians for all joints 00118 // update currentTransform by additional joint rotation 00119 btq *= joint_rot; 00120 mat.setRotation(btq); 00121 } 00122 00123 // update currentTransform 00124 currentTransform.setOrigin(pz); 00125 currentTransform.setBasis(mat); 00126 00127 // display result 00128 ROS_DEBUG("%s has currentTransform: [%f %f %f, %f %f %f %f]",link->name.c_str(),pz.x(), pz.y(), pz.z(),btq.x(),btq.y(),btq.z(),btq.w()); 00129 00130 // just for testing, go through and set each link state 00131 gazebo_msgs::SetLinkState set_link_state; 00132 set_link_state.request.link_state.link_name = gazebo_model_name + std::string("::") + link->name; 00133 set_link_state.request.link_state.reference_frame = "world"; 00134 set_link_state.request.link_state.pose.position.x = pz.x(); 00135 set_link_state.request.link_state.pose.position.y = pz.y(); 00136 set_link_state.request.link_state.pose.position.z = pz.z(); 00137 set_link_state.request.link_state.pose.orientation.x = btq.x(); 00138 set_link_state.request.link_state.pose.orientation.y = btq.y(); 00139 set_link_state.request.link_state.pose.orientation.z = btq.z(); 00140 set_link_state.request.link_state.pose.orientation.w = btq.w(); 00141 if (!set_link_state_client.call(set_link_state)) 00142 ROS_ERROR("unable to sete link [%s] state",set_link_state.request.link_state.link_name.c_str()); 00143 } 00144 00145 } 00146 else 00147 ROS_DEBUG("%s has no parent joint, is a root link?",link->name.c_str()); 00148 00149 level+=2; 00150 for (std::vector<boost::shared_ptr<urdf::Link> >::const_iterator child = link->child_links.begin(); child != link->child_links.end(); child++) 00151 { 00152 if (*child) 00153 { 00154 // first grandchild 00155 traverse_tree(*child,currentTransform,set_link_state_client,gazebo_model_name,level); 00156 } 00157 else 00158 ROS_ERROR("link: %s has a null child",link->name.c_str()); 00159 } 00160 00161 } 00162 00163 00164 int main(int argc, char **argv) 00165 { 00166 // start a gazebo ros node 00167 ros::init(argc,argv,"gazebo_model_pose_setter"); 00168 ros::NodeHandle nh(""); 00169 00170 std::string gazebo_model_name = "pr2"; //FIXME: Hardcoded model name 00171 std::string urdf_param_name = "robot_description"; //FIXME: Hardcoded param name 00172 00173 // we need the urdf to do the transforms 00174 // search and wait for robot_description on param server 00175 urdf::Model urdf_model; 00176 if (!urdf_model.initParam(urdf_param_name)) 00177 ROS_ERROR("unable to get urdf xml from param %s",urdf_param_name.c_str()); 00178 // get gazebo model from urdf model name 00179 ROS_INFO("urdf model name [%s]",urdf_model.getName().c_str()); 00180 00181 00182 // this will work only in a plugin 00183 //gazebo::Model* gazebo_model = dynamic_cast<gazebo::Model*>(gazebo::World::Instance()->GetEntityByName(urdf_model.getName())); 00184 //if (gazebo_model == NULL) 00185 // ROS_ERROR("unable to get gazebo model with name [%s]",urdf_model.getName().c_str()); 00186 // check to make sure that root_link is the canonicalBody of the Gazebo::Model 00187 //if (root_link->name != gazebo_model->GetCanonicalBody()->GetName()) 00188 // ROS_ERROR("gazebo_model canonical body is not the root link!"); 00189 00190 00191 // get root link 00192 boost::shared_ptr<const urdf::Link> root_link = urdf_model.getRoot(); 00193 if (!root_link) 00194 ROS_ERROR("urdf has no root"); 00195 00196 // make the service call to pause gazebo 00197 ros::ServiceClient pause_client = nh.serviceClient<std_srvs::Empty>("gazebo/pause_physics"); 00198 pause_client.waitForExistence(); 00199 std_srvs::Empty empty_pause; 00200 if (!pause_client.call(empty_pause)) 00201 ROS_ERROR("unable to pause physics engine"); 00202 00203 // make the service call to get model properties for list of joints 00204 ros::ServiceClient model_properties_client = nh.serviceClient<gazebo_msgs::GetModelProperties>("gazebo/get_model_properties"); 00205 gazebo_msgs::GetModelProperties model_properties; 00206 model_properties.request.model_name = urdf_model.getName(); 00207 if (!model_properties_client.call(model_properties)) 00208 ROS_ERROR("unable to get model properties"); 00209 00210 // make the service call to get pr2 model pose 00211 ros::ServiceClient model_state_client = nh.serviceClient<gazebo_msgs::GetModelState>("gazebo/get_model_state"); 00212 model_state_client.waitForExistence(); 00213 gazebo_msgs::GetModelState model_state; 00214 model_state.request.model_name = gazebo_model_name; 00215 model_state.request.relative_entity_name = "world"; 00216 if (!model_state_client.call(model_state)) 00217 ROS_ERROR("unable to get model state"); 00218 00219 // make the service call to get root link pose 00220 ros::ServiceClient root_link_state_client = nh.serviceClient<gazebo_msgs::GetLinkState>("gazebo/get_link_state"); 00221 root_link_state_client.waitForExistence(); 00222 gazebo_msgs::GetLinkState root_link_state; 00223 //root_link_state.request.link_name = gazebo_model->GetCanonicalBody()->GetScopedName(); // if we were in a plugin 00224 root_link_state.request.link_name = gazebo_model_name + std::string("::") + root_link->name; // scope name for gazebo 00225 root_link_state.request.reference_frame = "world"; 00226 if (!root_link_state_client.call(root_link_state)) 00227 ROS_ERROR("unable to get root link state"); 00228 00229 // setup transform, using root link pose 00230 btTransform transform; 00231 setup_transform(transform,root_link_state.response.link_state.pose); 00232 00233 // testing 00234 ros::ServiceClient set_link_state_client = nh.serviceClient<gazebo_msgs::SetLinkState>("gazebo/set_link_state"); 00235 set_link_state_client.waitForExistence(); 00236 00237 // traverse through urdf and get link poses based on new joint angles 00238 traverse_tree(root_link, transform, set_link_state_client, gazebo_model_name); 00239 00240 // set individual body poses from the new transforms 00241 00242 00243 // make the service call to unpause gazebo 00244 ros::ServiceClient unpause_client = nh.serviceClient<std_srvs::Empty>("gazebo/unpause_physics"); 00245 unpause_client.waitForExistence(); 00246 std_srvs::Empty empty_unpause; 00247 if (!unpause_client.call(empty_unpause)) 00248 ROS_ERROR("unable to unpause physics engine"); 00249 00250 return 0; 00251 } 00252