├── README.md
├── launch
└── panda_kinematics_solver.launch
├── CMakeLists.txt
├── package.xml
├── include
└── panda_kinematics_solver
│ └── ik_fk_calculator.h
└── src
└── ik_fk_calculator.cpp
/README.md:
--------------------------------------------------------------------------------
1 | # panda_kinematics_solver
2 | Solving FK and IK for Franka-Emika panda robot in ROS
3 |
--------------------------------------------------------------------------------
/launch/panda_kinematics_solver.launch:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
11 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.0.2)
2 | project(panda_kinematics_solver)
3 |
4 | add_compile_options(-std=c++11)
5 |
6 | find_package(catkin REQUIRED
7 | roscpp
8 | moveit_ros_planning_interface
9 | sensor_msgs
10 | )
11 |
12 | find_package(Eigen3 REQUIRED)
13 | find_package(Boost REQUIRED system filesystem date_time thread)
14 |
15 | catkin_package(
16 | INCLUDE_DIRS include
17 | LIBRARIES
18 | CATKIN_DEPENDS
19 | moveit_core
20 | DEPENDS
21 | EIGEN3
22 | )
23 |
24 | include_directories(
25 | include
26 | ${catkin_INCLUDE_DIRS}
27 | ${EIGEN3_INCLUDE_DIRS}
28 | ${Boost_INCLUDE_DIR}
29 | )
30 |
31 | add_executable(ik_fk_calculator src/ik_fk_calculator.cpp)
32 | # add_dependencies(ik_fk_calculator panda_kinematics_solver_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
33 | target_link_libraries(ik_fk_calculator ${catkin_LIBRARIES} ${Boost_LIBRARIES})
34 |
--------------------------------------------------------------------------------
/package.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | panda_kinematics_solver
4 | 0.0.0
5 | The panda_kinematics_solver package
6 |
7 | kosmas
8 |
9 |
10 | TODO
11 |
12 |
13 |
14 |
15 |
16 |
17 | catkin
18 | roscpp
19 | eigen
20 | moveit_core
21 | sensor_msgs
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/include/panda_kinematics_solver/ik_fk_calculator.h:
--------------------------------------------------------------------------------
1 | #ifndef IK_FK_CALCULATOR
2 | #define IK_FK_CALCULATOR
3 |
4 | #include
5 | #include
6 |
7 | // MoveIt
8 | #include
9 | #include
10 | #include
11 | #include
12 |
13 | // Message types
14 | #include
15 | #include
16 |
17 |
18 | namespace panda_kinematics_solver{
19 | class IkFkCalculator
20 | {
21 | private:
22 | ros::NodeHandle _nh;
23 | robot_model::RobotModelPtr _kinematic_model;
24 | robot_state::RobotState* _kinematic_state;
25 | std::vector _joint_values;
26 | std::vector _goal_joint_values;
27 | std::vector _joint_names;
28 |
29 | robot_state::JointModelGroup* _joint_model_group;
30 |
31 | void jointCallback(const sensor_msgs::JointStateConstPtr &msg);
32 | void getJointValues();
33 | Eigen::Isometry3d calculateFK();
34 | void calculateIK(Eigen::Isometry3d end_effector_state);
35 | void calculateJacobian();
36 |
37 | public:
38 | IkFkCalculator();
39 | ~IkFkCalculator();
40 | };
41 | }
42 | #endif
--------------------------------------------------------------------------------
/src/ik_fk_calculator.cpp:
--------------------------------------------------------------------------------
1 | #include "panda_kinematics_solver/ik_fk_calculator.h"
2 |
3 | namespace panda_kinematics_solver{
4 |
5 | IkFkCalculator::IkFkCalculator(){
6 | // RobotModelLoader
7 | robot_model_loader::RobotModelLoader robot_model_loader("robot_description");
8 | _kinematic_model = robot_model_loader.getModel();
9 |
10 | ROS_INFO("Model frame: %s", _kinematic_model->getModelFrame().c_str());
11 |
12 | // We construct a RobotState that maintains the configuration of the robot
13 | // Joint states are set to default and then get a JointModelGroup, which represents the robot model for the panda_arm_hand group of the robot
14 | _kinematic_state = new robot_state::RobotState(_kinematic_model);
15 | _kinematic_state->setToDefaultValues(); // Set the joints in group to the position name defined in the SRDF
16 | _joint_model_group = _kinematic_model->getJointModelGroup("panda_arm");
17 |
18 | _joint_names = _joint_model_group->getVariableNames();
19 |
20 | getJointValues(); // from /joint_states ROS topic
21 |
22 | _kinematic_state->setJointGroupPositions(_joint_model_group, _joint_values);
23 |
24 | ROS_INFO_STREAM("Current state is " << (_kinematic_state->satisfiesBounds() ? "valid" : "not valid"));
25 |
26 | Eigen::Isometry3d end_effector_state = calculateFK();
27 |
28 | calculateIK(end_effector_state);
29 |
30 | calculateJacobian();
31 | }
32 |
33 | IkFkCalculator::~IkFkCalculator(){
34 | delete _kinematic_state;
35 | delete _joint_model_group;
36 | }
37 |
38 | void IkFkCalculator::getJointValues(){
39 | sensor_msgs::JointState js;
40 | try {
41 | js = *(ros::topic::waitForMessage("/joint_states", _nh));
42 | }
43 | catch(const std::exception& e){
44 | ROS_WARN("Message from /joint_states not received\n");
45 | }
46 |
47 | _joint_values.clear();
48 |
49 | _joint_values.push_back(js.position[2]); // panda_joint1
50 | _joint_values.push_back(js.position[3]); // panda_joint2
51 | _joint_values.push_back(js.position[4]); // panda_joint3
52 | _joint_values.push_back(js.position[5]); // panda_joint4
53 | _joint_values.push_back(js.position[6]); // panda_joint5
54 | _joint_values.push_back(js.position[7]); // panda_joint6
55 | _joint_values.push_back(js.position[8]); // panda_joint7
56 | _joint_values.push_back(js.position[0]); // panda_finger_joint1
57 | _joint_values.push_back(js.position[1]); // panda_finger_joint2
58 |
59 | ROS_INFO("\nCurrent set of joint values:");
60 |
61 | for (std::size_t i=0; i<_joint_names.size(); ++i){
62 | ROS_INFO("Joint %s: %f", _joint_names[i].c_str(), _joint_values[i]);
63 | }
64 | }
65 |
66 | Eigen::Isometry3d IkFkCalculator::calculateFK(){
67 | ROS_INFO_STREAM("\n\n**Solving forward kinematics**\n");
68 |
69 | // _kinematic_state->setToRandomPositions(_joint_model_group);
70 | Eigen::Isometry3d end_effector_state = _kinematic_state->getGlobalLinkTransform("panda_link8");
71 |
72 | ROS_INFO_STREAM("End-effector pose (in the model frame) : ");
73 | ROS_INFO_STREAM("Translation: \n" << end_effector_state.translation() << "\n");
74 | ROS_INFO_STREAM("Rotation: \n" << end_effector_state.rotation() << "\n");
75 |
76 | return end_effector_state;
77 | }
78 |
79 | void IkFkCalculator::calculateIK(Eigen::Isometry3d end_effector_state){
80 | ROS_INFO_STREAM("\n\n**Solving inverse kinematics**\n");
81 |
82 | double timeout = 0.1;
83 | bool found_ik = _kinematic_state->setFromIK(_joint_model_group, end_effector_state, timeout);
84 |
85 | if (found_ik){
86 | _kinematic_state->copyJointGroupPositions(_joint_model_group, _joint_values);
87 | for (std::size_t i=0; i<_joint_names.size(); ++i){
88 | ROS_INFO("Joint %s: %f", _joint_names[i].c_str(), _joint_values[i]);
89 | }
90 | }
91 | else{
92 | ROS_INFO("Did not find IK solution\n");
93 | }
94 | }
95 |
96 | void IkFkCalculator::calculateJacobian(){
97 | // Each column in the Jacobian matrix represents the effect on end-effector velocities due to variation in each joint velocity.
98 | Eigen::Vector3d reference_point_position(0.0, 0.0, 0.0);
99 | Eigen::MatrixXd jacobian;
100 | _kinematic_state->getJacobian(_joint_model_group, _kinematic_state->getLinkModel(_joint_model_group->getLinkModelNames().back()), reference_point_position, jacobian);
101 | ROS_INFO_STREAM("\n\n**Jacobian** \n" << jacobian << "\n");
102 | }
103 |
104 |
105 | } // namespace panda_kinematics_solver
106 |
107 | int main(int argc, char** argv)
108 | {
109 | ros::init(argc, argv, "ik_fk_calculator");
110 |
111 | panda_kinematics_solver::IkFkCalculator calc;
112 |
113 | ros::spin();
114 | return 0;
115 | }
116 |
--------------------------------------------------------------------------------