Note: This tutorial assumes that you have completed the previous tutorials: Inverse kinematics for the PR2 arms. |
Please ask about problems and questions regarding this tutorial on answers.ros.org. Don't forget to include in your question the link to this page, the versions of your OS & ROS, and also add appropriate tags. |
Collision free inverse kinematics for the PR2 arms
Description: This tutorial will show you how to use a kinematics node to get collision free inverse kinematics solutions for a desired cartesian position of the PR2 arms.Keywords: collision inverse kinematics cartesian
Tutorial Level: INTERMEDIATE
Contents
In this tutorial, you will learn how to use the PR2 kinematics node to compute collision free inverse kinematics for the tip link of the PR2 arm.
ROS Setup
To use this tutorial make sure that you've run the following:
sudo apt-get install ros-electric-pr2-arm-navigation
Also make sure that in each terminal you use you've run:
export ROBOT=sim
Running in simulation
To use the arm planning stack, we first need to launch the simulator.
roslaunch pr2_gazebo pr2_empty_world.launch
The simulator should come up.
Now, launch the arm navigation stack:
roslaunch pr2_3dnav right_arm_navigation.launch
Next, run this executable from the pr2_arm_navigation_tutorials stack:
rosrun pr2_arm_navigation_tutorials get_collision_free_ik
If it succeeds, you should see the following output
[ INFO] 0.000000000: Joint: r_shoulder_pan_joint -0.330230 [ INFO] 0.000000000: Joint: r_shoulder_lift_joint 0.008300 [ INFO] 0.000000000: Joint: r_upper_arm_roll_joint -1.550000 [ INFO] 0.000000000: Joint: r_elbow_flex_joint -0.859908 [ INFO] 0.000000000: Joint: r_forearm_roll_joint 3.139403 [ INFO] 0.000000000: Joint: r_wrist_flex_joint -0.529580 [ INFO] 0.000000000: Joint: r_wrist_roll_joint -1.591270
The code
The code for this example can be found in the package pr2_arm_navigation_tutorials in the file src/get_collision_free_ik.cpp.
The setup and code for this node are almost the same as the setup and code for using the base inverse kinematics solution. The key differences are the following:
Service call type: Instead of the GetPositionIK service from the kinematics_msgs package, we will use the GetConstraintAwarePositionIK service.
Service call name: The service call name is now get_collision_free_ik
Nodes: An additional set of nodes will have to be launched to setup the collision checking.
Kinematics solver: The IK solver will now need to be launched from a different package (pr2_arm_kinematics_constraint_aware).
Select one of the buttons below to show the code and explanation for your distribution:
This code is for the Electric distribution.
The code
1 #include <ros/ros.h>
2 #include <kinematics_msgs/GetKinematicSolverInfo.h>
3 #include <kinematics_msgs/GetConstraintAwarePositionIK.h>
4 #include <arm_navigation_msgs/SetPlanningSceneDiff.h>
5
6 static const std::string SET_PLANNING_SCENE_DIFF_NAME = "/environment_server/set_planning_scene_diff";
7
8 int main(int argc, char **argv){
9 ros::init (argc, argv, "get_fk");
10 ros::NodeHandle rh;
11
12 ros::service::waitForService("pr2_right_arm_kinematics/get_ik_solver_info");
13 ros::service::waitForService("pr2_right_arm_kinematics/get_constraint_aware_ik");
14
15 ros::ServiceClient query_client = rh.serviceClient<kinematics_msgs::GetKinematicSolverInfo>("pr2_right_arm_kinematics/get_ik_solver_info");
16 ros::ServiceClient ik_client = rh.serviceClient<kinematics_msgs::GetConstraintAwarePositionIK>("pr2_right_arm_kinematics/get_constraint_aware_ik");
17 ros::ServiceClient set_planning_scene_diff_client = rh.serviceClient<arm_navigation_msgs::SetPlanningSceneDiff>(SET_PLANNING_SCENE_DIFF_NAME);
18
19 arm_navigation_msgs::SetPlanningSceneDiff::Request planning_scene_req;
20 arm_navigation_msgs::SetPlanningSceneDiff::Response planning_scene_res;
21
22 if(!set_planning_scene_diff_client.call(planning_scene_req, planning_scene_res)) {
23 ROS_WARN("Can't get planning scene");
24 return -1;
25 }
26
27 // define the service messages
28 kinematics_msgs::GetKinematicSolverInfo::Request request;
29 kinematics_msgs::GetKinematicSolverInfo::Response response;
30
31 if(query_client.call(request,response))
32 {
33 for(unsigned int i=0; i< response.kinematic_solver_info.joint_names.size(); i++)
34 {
35 ROS_DEBUG("Joint: %d %s",i,response.kinematic_solver_info.joint_names[i].c_str());
36 }
37 }
38 else
39 {
40 ROS_ERROR("Could not call query service");
41 ros::shutdown();
42 exit(-1);
43 }
44
45 // define the service messages
46 kinematics_msgs::GetConstraintAwarePositionIK::Request gpik_req;
47 kinematics_msgs::GetConstraintAwarePositionIK::Response gpik_res;
48
49 gpik_req.timeout = ros::Duration(5.0);
50 gpik_req.ik_request.ik_link_name = "r_wrist_roll_link";
51
52 gpik_req.ik_request.pose_stamped.header.frame_id = "torso_lift_link";
53 gpik_req.ik_request.pose_stamped.pose.position.x = 0.75;
54 gpik_req.ik_request.pose_stamped.pose.position.y = -0.188;
55 gpik_req.ik_request.pose_stamped.pose.position.z = 0.0;
56
57 gpik_req.ik_request.pose_stamped.pose.orientation.x = 0.0;
58 gpik_req.ik_request.pose_stamped.pose.orientation.y = 0.0;
59 gpik_req.ik_request.pose_stamped.pose.orientation.z = 0.0;
60 gpik_req.ik_request.pose_stamped.pose.orientation.w = 1.0;
61 gpik_req.ik_request.ik_seed_state.joint_state.position.resize(response.kinematic_solver_info.joint_nam
62 es.size());
63 gpik_req.ik_request.ik_seed_state.joint_state.name = response.kinematic_solver_info.joint_names;
64
65 for(unsigned int i=0; i< response.kinematic_solver_info.joint_names.size(); i++)
66 { gpik_req.ik_request.ik_seed_state.joint_state.position[i] = (response.kinematic_solver_info.limits[i
67 ].min_position + response.kinematic_solver_info.limits[i].max_position)/2.0;
68 }
69 if(ik_client.call(gpik_req, gpik_res))
70 {
71 if(gpik_res.error_code.val == gpik_res.error_code.SUCCESS)
72 {
73 for(unsigned int i=0; i < gpik_res.solution.joint_state.name.size(); i ++)
74 { ROS_INFO("Joint: %s %f",gpik_res.solution.joint_state.name[i].c_str(),gpik_res.solution.joint_st
75 ate.position[i]);
76 }
77 }
78 else
79 {
80 ROS_ERROR("Inverse kinematics failed");
81 }
82 }
83 else
84 {
85 ROS_ERROR("Inverse kinematics service call failed");
86 }
87 ros::shutdown();
88 }
This code is for the Diamondback distribution.
1 #include <ros/ros.h>
2 #include <kinematics_msgs/GetKinematicSolverInfo.h>
3 #include <kinematics_msgs/GetConstraintAwarePositionIK.h>
4
5 int main(int argc, char **argv){
6 ros::init (argc, argv, "get_fk");
7 ros::NodeHandle rh;
8
9 ros::service::waitForService("pr2_right_arm_kinematics/get_ik_solver_info");
10 ros::service::waitForService("pr2_right_arm_kinematics/get_constraint_aware_ik");
11
12 ros::ServiceClient query_client = rh.serviceClient<kinematics_msgs::GetKinematicSolverInfo>("pr2_right_arm_kinematics/get_ik_solver_info");
13 ros::ServiceClient ik_client = rh.serviceClient<kinematics_msgs::GetConstraintAwarePositionIK>("pr2_right_arm_kinematics/get_constraint_aware_ik");
14
15 // define the service messages
16 kinematics_msgs::GetKinematicSolverInfo::Request request;
17 kinematics_msgs::GetKinematicSolverInfo::Response response;
18
19 if(query_client.call(request,response))
20 {
21 for(unsigned int i=0; i< response.kinematic_solver_info.joint_names.size(); i++)
22 {
23 ROS_DEBUG("Joint: %d %s",i,response.kinematic_solver_info.joint_names[i].c_str());
24 }
25 }
26 else
27 {
28 ROS_ERROR("Could not call query service");
29 ros::shutdown();
30 exit(-1);
31 }
32
33 // define the service messages
34 kinematics_msgs::GetConstraintAwarePositionIK::Request gpik_req;
35 kinematics_msgs::GetConstraintAwarePositionIK::Response gpik_res;
36
37 gpik_req.timeout = ros::Duration(5.0);
38 gpik_req.ik_request.ik_link_name = "r_wrist_roll_link";
39
40 gpik_req.ik_request.pose_stamped.header.frame_id = "torso_lift_link";
41 gpik_req.ik_request.pose_stamped.pose.position.x = 0.75;
42 gpik_req.ik_request.pose_stamped.pose.position.y = -0.188;
43 gpik_req.ik_request.pose_stamped.pose.position.z = 0.0;
44
45 gpik_req.ik_request.pose_stamped.pose.orientation.x = 0.0;
46 gpik_req.ik_request.pose_stamped.pose.orientation.y = 0.0;
47 gpik_req.ik_request.pose_stamped.pose.orientation.z = 0.0;
48 gpik_req.ik_request.pose_stamped.pose.orientation.w = 1.0;
49
50 gpik_req.ik_request.ik_seed_state.joint_state.position.resize(response.kinematic_solver_info.joint_names.size());
51 gpik_req.ik_request.ik_seed_state.joint_state.name = response.kinematic_solver_info.joint_names;
52
53 for(unsigned int i=0; i< response.kinematic_solver_info.joint_names.size(); i++)
54 {
55 gpik_req.ik_request.ik_seed_state.joint_state.position[i] = (response.kinematic_solver_info.limits[i].min_position + response.kinematic_solver_info.limits[i].max_position)/2.0;
56 }
57 if(ik_client.call(gpik_req, gpik_res))
58 {
59 if(gpik_res.error_code.val == gpik_res.error_code.SUCCESS)
60 {
61 for(unsigned int i=0; i < gpik_res.solution.joint_state.name.size(); i ++)
62 {
63 ROS_INFO("Joint: %s %f",gpik_res.solution.joint_state.name[i].c_str(),gpik_res.solution.joint_state.position[i]);
64 }
65 }
66 else
67 {
68 ROS_ERROR("Inverse kinematics failed");
69 }
70 }
71 else
72 {
73 ROS_ERROR("Inverse kinematics service call failed");
74 }
75 ros::shutdown();
76 }