在本节中,将了解在MoveIt中使用kinematics的C++ API。
一.The RobotModel and RobotState Classes
RobotModel和RobotState类是允许访问rebot kinematics的核心类。
RobotModel类包含所有links和joints之间的关系,包括从URDF加载的joint限制属性。RobotModel还将robot的links和joints分成SRDF中定义的planning groups。在这里可以找到关于URDF和SRDF的单独教程:URDF和SRDF教程 RobotState包含关于robot的实时快照信息,存储joint位置和可选的速度和加速度向量,可用于获得关于robot的运动学信息,这些信息取决于robot的当前状态,比如末端执行器的雅可比矩阵。
RobotState还包含辅助功能,用于基于末端执行器位置[笛卡尔位姿]设置手臂位置和计算笛卡尔轨迹。
在本例中,将遍历使用Panda使用这些类的过程。
二.Running the Code
本教程中的所有代码都可以从moveit_tutorials包[MoveIt的一部分]编译并运行设置。
Roslaunch启动文件运行代码直接从moveit_tutorials:
roslaunch moveit_tutorials robot_model_and_robot_state_tutorial.launch
三.Expected Output
预期的输出形式如下。这些数字将不匹配,因为使用随机joint值:
ros.moveit_tutorials: Model frame: /panda_link0
ros.moveit_tutorials: Joint panda_joint1: 0.000000
ros.moveit_tutorials: Joint panda_joint2: 0.000000
ros.moveit_tutorials: Joint panda_joint3: 0.000000
ros.moveit_tutorials: Joint panda_joint4: 0.000000
ros.moveit_tutorials: Joint panda_joint5: 0.000000
ros.moveit_tutorials: Joint panda_joint6: 0.000000
ros.moveit_tutorials: Joint panda_joint7: 0.000000
ros.moveit_tutorials: Current state is not valid
ros.moveit_tutorials: Current state is valid
ros.moveit_tutorials: Translation:
-0.541498
-0.592805
0.400443
ros.moveit_tutorials: Rotation:
-0.395039 0.600666 -0.695086
0.299981 -0.630807 -0.715607
-0.868306 -0.491205 0.0690048
ros.moveit_tutorials: Joint panda_joint1: -2.407308
ros.moveit_tutorials: Joint panda_joint2: 1.555370
ros.moveit_tutorials: Joint panda_joint3: -2.102171
ros.moveit_tutorials: Joint panda_joint4: -0.011156
ros.moveit_tutorials: Joint panda_joint5: 1.100545
ros.moveit_tutorials: Joint panda_joint6: 3.230793
ros.moveit_tutorials: Joint panda_joint7: -2.651568
ros.moveit_tutorials: Jacobian:
0.592805 -0.0500638 -0.036041 0.366761 -0.0334361 0.128712 -4.33681e-18
-0.541498 -0.0451907 0.0417049 -0.231187 0.0403683 0.00288573 3.46945e-18
0 -0.799172 0.0772022 -0.247151 0.0818336 0.0511662 0
0 0.670056 -0.742222 0.349402 -0.748556 -0.344057 -0.695086
0 -0.74231 -0.669976 -0.367232 -0.662737 0.415389 -0.715607
1 4.89669e-12 0.0154256 0.862009 0.021077 0.842067 0.0690048
注意:如果输出具有不同的ROS控制台格式,请不要担心。可以通过阅读这篇博客文章来定制ROS控制台日志记录器。
四.The Entire Code
全部代码参考文献[2]。
1.Start
设置开始使用RobotModel类非常简单。通常,会发现大多数高级组件将返回一个指向RobotModel的共享指针。应该尽可能地使用它。在本例中,将从这样一个共享指针开始,只讨论基本API。可以查看这些类的实际代码API,以获得关于如何使用这些类提供的更多特性的更多信息。
将从实例化一个RobotModelLoader对象开始,该对象将在ROS参数服务器上查找robot描述,并构造一个供使用的RobotModel。
robot_model_loader::RobotModelLoader robot_model_loader("robot_description");
robot_model::RobotModelPtr kinematic_model = robot_model_loader.getModel();
ROS_INFO("Model frame: %s", kinematic_model->getModelFrame().c_str());
使用RobotModel,可以构建一个RobotState来维持robot的配置。将把状态中的所有joints设置为它们的默认值。然后可以得到一个JointModelGroup,它代表一个特定组的robot模型,例如,Panda robot的panda_arm。
robot_state::RobotStatePtr kinematic_state(new robot_state::RobotState(kinematic_model));
kinematic_state->setToDefaultValues();
const robot_state::JointModelGroup* joint_model_group = kinematic_model->getJointModelGroup("panda_arm");
const std::vector<std::string>& joint_names = joint_model_group->getVariableNames();
2.Get Joint Values
可以为Panda arm检索存储在状态中的当前joint值集。
std::vector<double> joint_values;
kinematic_state->copyJointGroupPositions(joint_model_group, joint_values);
for (std::size_t i = 0; i < joint_names.size(); ++i)
{
ROS_INFO("Joint %s: %f", joint_names[i].c_str(), joint_values[i]);
}
3.Joint Limits
setJointGroupPositions()本身不执行joint限制,但调用enforceBounds()将执行它。
/* Set one joint in the Panda arm outside its joint limit */
joint_values[0] = 5.57;
kinematic_state->setJointGroupPositions(joint_model_group, joint_values);
/* Check whether any joint is outside its joint limits */
ROS_INFO_STREAM("Current state is " << (kinematic_state->satisfiesBounds() ? "valid" : "not valid"));
/* Enforce the joint limits for this state and check again*/
kinematic_state->enforceBounds();
ROS_INFO_STREAM("Current state is " << (kinematic_state->satisfiesBounds() ? "valid" : "not valid"));
4.Forward Kinematics
现在,可以计算一组随机joint值的正运动学。请注意,希望找到panda_link8的位置,它是机器人panda_arm组中最远端的链接。
kinematic_state->setToRandomPositions(joint_model_group);
const Eigen::Affine3d& end_effector_state = kinematic_state->getGlobalLinkTransform("panda_link8");
/* Print end-effector pose. Remember that this is in the model frame */
ROS_INFO_STREAM("Translation: \n" << end_effector_state.translation() << "\n");
ROS_INFO_STREAM("Rotation: \n" << end_effector_state.rotation() << "\n");
5.Inverse Kinematics
现在可以求解Panda robot的逆运动学。要解决IK,需要以下几点:
[1]所需的末端执行器姿态[默认情况下,这是panda_arm链中的最后一个链接]:end_effector_state,在上面的步骤中计算过。
[2]解决IK的尝试次数:10
[3]每次尝试的超时时间:0.1秒
std::size_t attempts = 10;
double timeout = 0.1;
bool found_ik = kinematic_state->setFromIK(joint_model_group, end_effector_state, attempts, timeout);
现在,可以打印出IK解决方案[如果找到]:
if (found_ik)
{
kinematic_state->copyJointGroupPositions(joint_model_group, joint_values);
for (std::size_t i = 0; i < joint_names.size(); ++i)
{
ROS_INFO("Joint %s: %f", joint_names[i].c_str(), joint_values[i]);
}
}
else
{
ROS_INFO("Did not find IK solution");
}
6.Get the Jacobian
还可以从RobotState得到雅可比矩阵。
Eigen::Vector3d reference_point_position(0.0, 0.0, 0.0);
Eigen::MatrixXd jacobian;
kinematic_state->getJacobian(joint_model_group,
kinematic_state->getLinkModel(joint_model_group->getLinkModelNames().back()),
reference_point_position, jacobian);
ROS_INFO_STREAM("Jacobian: \n" << jacobian << "\n");
7.The Launch File
运行代码,需要一个launch文件做两件事:
[1]将Panda URDF和SRDF加载到参数服务器中
[2]放置由MoveIt生成的kinematics_solver配置,Setup Assistant到ROS参数服务器,该服务器位于本教程中实例化类的节点的名称空间中。
<launch>
<include file="$(find panda_moveit_config)/launch/planning_context.launch">
<arg name="load_robot_description" value="true"/>
</include>
<node name="robot_model_and_robot_state_tutorial"
pkg="moveit_tutorials"
type="robot_model_and_robot_state_tutorial"
respawn="false" output="screen">
<rosparam command="load"
file="$(find panda_moveit_config)/config/kinematics.yaml"/>
</node>
</launch>
参考文献:
[1]Robot Model and Robot State:http://docs.ros.org/kinetic/api/moveit_tutorials/html/doc/robot_model_and_robot_state/robot_model_and_robot_state_tutorial.html
[2]robot_model_and_robot_state_tutorial:https://github.com/ros-planning/moveit_tutorials/tree/kinetic-devel/doc/robot_model_and_robot_state/src/robot_model_and_robot_state_tutorial.cpp
[3]MoveIt!入门教程-目录:https://www.ncnynl.com/archives/201610/947.html