Franka Ros1 简介
Franka Ros 暂时在Windows上不受支持。
source /path/to/catkin_ws/devel/setup.sh
franka_description
该包包含我们的机器人和末端执行器在运动学,关节限制,视觉表现和碰撞空间方面的描述。碰撞空间是视觉描述的简化版本,用于提高碰撞检测的性能。根据URDF XML文档, 这些描述基于URDF格式。
如果你想模拟FR3机器人, 您可以参考参数传递gazebo给XACRO文件。 franka_description 包含所有Franka Robotics机器人模型的文件。
xacro $(rospack find franka_description)/robots/fr3/fr3.urdf.xacro gazebo:=true
<?xml version='1.0' encoding='utf-8'?> <robot xmlns:xacro="http://www.ros.org/wiki/xacro" name="fr3"> <xacro:include filename="$(find franka_description)/robots/common/franka_robot.xacro"/> <!-- Name for this robot --> <xacro:arg name="arm_id" default="fr3" /> <!-- Should a franka_gripper be mounted at the flange?" --> <xacro:arg name="hand" default="false" /> <!-- Positional offset between $(arm_id)_hand -> $(arm_id)_hand_tcp [m]. Only used when hand:=true --> <xacro:arg name="tcp_xyz" default="0 0 0.1034" /> <!-- Rotational offset between $(arm_id)_hand -> $(arm_id)_hand_tcp [rad]. Only used when hand:=true --> <xacro:arg name="tcp_rpy" default="0 0 0" /> <!-- Is the robot being simulated in gazebo?" --> <xacro:arg name="gazebo" default="false" /> <!-- If `gazebo` arg is set, to which frame shall $(arm_id)_link0 be parented. Empty string for not fixing at all --> <xacro:arg name="parent" default="world" /> <!-- If `gazebo` arg is set and `parent` not empty, what position offset between `parent` & $(arm_id)_link0 --> <xacro:arg name="xyz" default="0 0 0" /> <!-- If `gazebo` arg is set and `parent` not empty, what rotation offset between `parent` & $(arm_id)_link0 --> <xacro:arg name="rpy" default="0 0 0" /> <xacro:franka_robot arm_id="$(arg arm_id)" joint_limits="${xacro.load_yaml('$(find franka_description)/robots/fr3/joint_limits.yaml')}" hand="$(arg hand)" tcp_xyz="$(arg tcp_xyz)" tcp_rpy="$(arg tcp_rpy)" gazebo="$(arg gazebo)" parent="$(arg parent)" xyz="$(arg xyz)" rpy="$(arg rpy)"> </xacro:franka_robot> </robot>
主要包含以下内容:
-
根元素 <robot>定义了机器人的名称。
-
xacro:include引入了另一个URDF文件franka_robot.xacro,这个文件可能包含了Franka机器人的核心定义。
-
通过一系列 xacro:arg元素定义了一些参数,包括:
- arm_id: 机器人臂的ID
- hand: 是否安装了夹持器
- tcp_xyz和tcp_rpy: 夹持器TCP的位置和旋转角度偏移
- gazebo: 是否在Gazebo仿真环境中使用
- parent、xyz和rpy: Gazebo仿真中机器人基座的父坐标系及其位置和旋转偏移
-
xacro:franka_robot元素是Franka机器人的主要定义,它使用了前面定义的参数。
franka_robot.xacro
<?xml version='1.0' encoding='utf-8'?> <robot xmlns:xacro="http://www.ros.org/wiki/xacro"> <xacro:macro name="franka_robot" params="arm_id joint_limits parent:='world' xyz:='0 0 0' rpy:='0 0 0' hand:=false gazebo:=false tcp_xyz:='0 0 0.1034' tcp_rpy='0 0 0'"> <xacro:include filename="$(find franka_description)/robots/common/utils.xacro" /> <xacro:include filename="$(find franka_description)/robots/common/franka_arm.xacro" /> <xacro:franka_arm arm_id="${arm_id}" safety_distance="0.03" gazebo="${gazebo}" joint_limits="${joint_limits}"/> <xacro:if value="${hand}"> <xacro:include filename="$(find franka_description)/robots/common/franka_hand.xacro"/> <xacro:franka_hand arm_id="${arm_id}" rpy="0 0 ${-pi/4}" tcp_xyz="${tcp_xyz}" tcp_rpy="${tcp_rpy}" connected_to="${arm_id}_link8" safety_distance="0.03" gazebo="${gazebo}" /> </xacro:if> <!-- Define additional Gazebo tags --> <xacro:if value="${gazebo}"> <xacro:if value="${parent != ''}"> <!-- Gazebo requires a joint to a link called "world" for statically mounted robots --> <xacro:if value="${parent == 'world'}"> <link name="${parent}" /> </xacro:if> <joint name="${parent}_joint" type="fixed"> <origin xyz="${xyz}" rpy="${rpy}" /> <parent link="${parent}" /> <child link="${arm_id}_link0" /> </joint> </xacro:if> <xacro:gazebo-joint joint="${arm_id}_joint1" transmission="hardware_interface/PositionJointInterface" /> <xacro:gazebo-joint joint="${arm_id}_joint2" transmission="hardware_interface/PositionJointInterface" /> <xacro:gazebo-joint joint="${arm_id}_joint3" transmission="hardware_interface/PositionJointInterface" /> <xacro:gazebo-joint joint="${arm_id}_joint4" transmission="hardware_interface/PositionJointInterface" /> <xacro:gazebo-joint joint="${arm_id}_joint5" transmission="hardware_interface/PositionJointInterface" /> <xacro:gazebo-joint joint="${arm_id}_joint6" transmission="hardware_interface/PositionJointInterface" /> <xacro:gazebo-joint joint="${arm_id}_joint7" transmission="hardware_interface/PositionJointInterface" /> <xacro:gazebo-joint joint="${arm_id}_joint1" transmission="hardware_interface/VelocityJointInterface" /> <xacro:gazebo-joint joint="${arm_id}_joint2" transmission="hardware_interface/VelocityJointInterface" /> <xacro:gazebo-joint joint="${arm_id}_joint3" transmission="hardware_interface/VelocityJointInterface" /> <xacro:gazebo-joint joint="${arm_id}_joint4" transmission="hardware_interface/VelocityJointInterface" /> <xacro:gazebo-joint joint="${arm_id}_joint5" transmission="hardware_interface/VelocityJointInterface" /> <xacro:gazebo-joint joint="${arm_id}_joint6" transmission="hardware_interface/VelocityJointInterface" /> <xacro:gazebo-joint joint="${arm_id}_joint7" transmission="hardware_interface/VelocityJointInterface" /> <xacro:gazebo-joint joint="${arm_id}_joint1" transmission="hardware_interface/EffortJointInterface" /> <xacro:gazebo-joint joint="${arm_id}_joint2" transmission="hardware_interface/EffortJointInterface" /> <xacro:gazebo-joint joint="${arm_id}_joint3" transmission="hardware_interface/EffortJointInterface" /> <xacro:gazebo-joint joint="${arm_id}_joint4" transmission="hardware_interface/EffortJointInterface" /> <xacro:gazebo-joint joint="${arm_id}_joint5" transmission="hardware_interface/EffortJointInterface" /> <xacro:gazebo-joint joint="${arm_id}_joint6" transmission="hardware_interface/EffortJointInterface" /> <xacro:gazebo-joint joint="${arm_id}_joint7" transmission="hardware_interface/EffortJointInterface" /> <xacro:transmission-franka-state arm_id="${arm_id}" /> <xacro:transmission-franka-model arm_id="${arm_id}" root="${arm_id}_joint1" tip="${arm_id}_joint8" /> <xacro:if value="${hand}"> <xacro:gazebo-joint joint="${arm_id}_finger_joint1" transmission="hardware_interface/EffortJointInterface" /> <xacro:gazebo-joint joint="${arm_id}_finger_joint2" transmission="hardware_interface/EffortJointInterface" /> <!-- Friction specific material for Rubber/Rubber contact --> <xacro:gazebo-friction link="${arm_id}_leftfinger" mu="1.13" /> <xacro:gazebo-friction link="${arm_id}_rightfinger" mu="1.13" /> </xacro:if> <gazebo> <plugin name="gazebo_ros_control" filename="libgazebo_ros_control.so"> <controlPeriod>0.001</controlPeriod> <robotSimType>franka_gazebo/FrankaHWSim</robotSimType> </plugin> <self_collide>true</self_collide> </gazebo> </xacro:if> </xacro:macro> </robot>
这段代码是一个 ROS (Robot Operating System) 中的 URDF (统一机器人描述格式) 文件,用于定义 Franka 机器人的参数和属性。下面我对这段代码进行逐步解释:
-
这个 URDF 文件使用了 xacro 宏,可以通过参数化的方式定义机器人的属性。
-
franka_robot
宏定义了 Franka 机器人的整体结构,包括机械臂和可选的机械手。可以通过设置参数来决定是否包含机械手,以及机器人在 Gazebo 模拟器中的显示。 -
这个宏引用了另外两个 xacro 文件:
franka_arm.xacro
: 定义了 Franka 机械臂的结构和联动关系。franka_hand.xacro
: 定义了 Franka 机械手的结构和联动关系。
-
对于 Gazebo 模拟,这个宏定义了以下内容:
- 将机器人固定在世界坐标系或其他链接上。
- 为每个关节定义了三种不同的接口:位置、速度和力矩。
- 定义了 Gazebo 中的插件,用于控制机器人的仿真。
总的来说,这个 URDF 文件提供了一种灵活的方式来定义 Franka 机器人的结构和属性,方便在 ROS 和 Gazebo 中进行仿真和控制。通过设置不同的参数,可以快速生成各种不同配置的 Franka 机器人模型。
utils.xacro
<?xml version="1.0"?> <robot xmlns:xacro="http://www.ros.org/wiki/xacro"> <!-- Load inertial properties. Property is implicitly passed to macros. --> <xacro:property name="inertial_config" value="$(find franka_description)/robots/common/inertial.yaml"/> <xacro:property name="inertial" value="${xacro.load_yaml(inertial_config)}"/> <!-- ============================================================== --> <!-- Macro to add an <inertial> tag based on yaml-load properties --> <!-- --> <!-- name: Name of the robot link (without prefix) --> <!-- inertial: Dictionary of inertia properties (see inertial.yaml) --> <!-- ============================================================== --> <xacro:macro name="inertial_props" params="name inertial:=^"> <xacro:unless value="${name in inertial}">${xacro.warning('No inertia properties defined for: ' + name)}</xacro:unless> <xacro:if value="${name in inertial}"> <!-- Access inertia properties of link 'name' --> <xacro:property name="inertial" value="${inertial[name]}" lazy_eval="false" /> <inertial> <origin rpy="${inertial.origin.rpy}" xyz="${inertial.origin.xyz}" /> <mass value="${inertial.mass}" /> <xacro:property name="I" value="${inertial.inertia}" /> <inertia ixx="${I.xx}" ixy="${I.xy}" ixz="${I.xz}" iyy="${I.yy}" iyz="${I.yz}" izz="${I.zz}" /> </inertial> </xacro:if> </xacro:macro> <!-- ========================================================== --> <!-- Macro to add a single link, both with --> <!-- * detailed meshes for environmental collision checking --> <!-- * and coarse geometry models for self-collision checking --> <!-- (only if 'gazebo' param is set) --> <!-- --> <!-- name: Name of the robot link (without prefix) --> <!-- rpy: Rotation of the *_sc link relative to parent [rad] --> <!-- self_collision_geometries: self <collision> models --> <!-- ========================================================== --> <xacro:macro name="link_with_sc" params="name prefix=${arm_id}_ rpy:='0 0 0' **self_collision_geometries gazebo:=false"> <!-- sub-link defining detailed meshes for collision with environment --> <link name="${prefix}${name}"> <visual> <geometry> <mesh filename="package://${description_pkg}/meshes/visual/${name}.dae" /> </geometry> </visual> <collision> <geometry> <mesh filename="package://franka_description/meshes/collision/${name}.stl" /> </geometry> </collision> <xacro:if value="${gazebo}"> <xacro:inertial_props name="${name}" /> </xacro:if> </link> <!-- sub-link defining coarse geometries of real robot's internal self-collision --> <link name="${prefix}${name}_sc"> <xacro:unless value="${gazebo}"> <xacro:insert_block name="self_collision_geometries" /> </xacro:unless> </link> <!-- fixed joint between both sub-links --> <joint name="${prefix}${name}_sc_joint" type="fixed"> <origin rpy="${rpy}" /> <parent link="${prefix}${name}" /> <child link="${prefix}${name}_sc" /> </joint> </xacro:macro> <!-- =========================================================== --> <!-- Add a <collision> tag with a capsule, made from a cylinder --> <!-- with two spheres at its caps. The capsule will always be --> <!-- aligned with the axis of 'direction' you pass along. --> <!-- --> <!-- radius: Radii of both the cylinder and both spheres [m] --> <!-- length: Length of the cylinder/distance between the centers --> <!-- of the spheres. NOT overall length of capsule! --> <!-- xyz: Position of the center of the capsule/cylinder --> <!-- direction: One of { x, y, z, -x, -y, -z } --> <!-- =========================================================== -->
<!-- =========================================================== -->
<!-- 添加一个由圆柱和两个球体组成的胶囊型 <collision> 标签 -->
<!-- 胶囊将始终与您传入的 'direction' 轴向对齐。 --> <!-- -->
<!-- radius: 圆柱和两个球体的半径 [m] -->
<!-- length: 圆柱的长度/两个球体中心之间的距离。 -->
<!-- 不是胶囊的总长度! -->
<!-- xyz: 胶囊/圆柱中心的位置 -->
<!-- direction: 取值为 { x, y, z, -x, -y, -z } 之一 -->
<!-- =========================================================== -->
<xacro:macro name="collision_capsule" params="radius length xyz:='0 0 0' direction:='z'"> <xacro:property name="r" value="${pi/2.0 if 'y' in direction else 0}" /> <xacro:property name="p" value="${pi/2.0 if 'x' in direction else 0}" /> <xacro:property name="y" value="0" /> <xacro:property name="x" value="${xyz.split(' ')[0]}" /> <xacro:property name="y" value="${xyz.split(' ')[1]}" /> <xacro:property name="z" value="${xyz.split(' ')[2]}" /> <!-- Sphere center offsets from center of cylinder --> <xacro:property name="sx" value="${length / 2.0 if 'x' in direction else 0}" /> <xacro:property name="sy" value="${length / 2.0 if 'y' in direction else 0}" /> <xacro:property name="sz" value="${length / 2.0 if 'z' in direction else 0}" /> <collision> <origin xyz="${x} ${y} ${z}" rpy="${r} ${p} ${y}"/> <geometry> <cylinder radius="${radius}" length="${length}" /> </geometry> </collision> <collision> <origin xyz="${x+sx} ${y+sy} ${z+sz}" /> <geometry> <sphere radius="${radius}" /> </geometry> </collision> <collision> <origin xyz="${x-sx} ${y-sy} ${z-sz}" /> <geometry> <sphere radius="${radius}" /> </geometry> </collision> </xacro:macro> <!-- ========================================================== --> <!-- Adds the required tags to simulate one joint in gazebo --> <!-- --> <!-- joint - Name of the panda joint to simulate --> <!-- transmission - type of the transmission of the joint --> <!-- ========================================================== -->
<!-- ========================================================== -->
<!-- 添加所需的标签来在Gazebo中模拟一个关节 -->
<!-- -->
<!-- joint - 要模拟的Panda关节的名称 -->
<!-- transmission - 关节传动类型 -->
<!-- ========================================================== -->
<xacro:macro name="gazebo-joint" params="joint transmission:=hardware_interface/EffortJointInterface"> <gazebo reference="${joint}"> <!-- Needed for ODE to output external wrenches on joints --> <provideFeedback>true</provideFeedback> </gazebo> <transmission name="${joint}_transmission"> <type>transmission_interface/SimpleTransmission</type> <joint name="${joint}"> <hardwareInterface>${transmission}</hardwareInterface> </joint> <actuator name="${joint}_motor"> <hardwareInterface>${transmission}</hardwareInterface> </actuator> </transmission> </xacro:macro>
<!-- link: 要应用摩擦属性的链接名称。
mu1: 与地面接触时的摩擦系数。
mu2: 滑动接触时的摩擦系数。
kp: 滚动接触时的摩擦系数。
kd: 滚动接触时的阻尼系数。-->
<xacro:macro name="gazebo-friction" params="link mu"> <gazebo reference="${link}"> <collision> <max_contacts>10</max_contacts> <surface> <contact> <ode> <!-- These two parameter need application specific tuning. --> <!-- Usually you want no "snap out" velocity and a generous --> <!-- penetration depth to keep the grasping stable --> <max_vel>0</max_vel> <min_depth>0.001</min_depth> </ode> </contact> <friction> <ode> <mu>${mu}</mu> <mu2>${mu}</mu2> </ode> </friction> <bounce/> </surface> </collision> </gazebo> </xacro:macro> <!-- ========================================================== --> <!-- Adds the required tags to provide a `FrankaStateInterface` --> <!-- when simulating with franka_hw_sim plugin --> <!-- --> <!-- arm_id - Arm ID of the panda to simulate (default 'panda') --> <!-- ========================================================== -->
<!-- ========================================================== -->
<!-- 在使用 franka_hw_sim 插件进行仿真时,添加提供 FrankaStateInterface 所需的标签 -->
<!-- -->
<!-- arm_id - 要模拟的 Panda 机械臂的 ID (默认为 'panda') -->
<!-- ========================================================== -->
<xacro:macro name="transmission-franka-state" params="arm_id:=panda"> <transmission name="${arm_id}_franka_state"> <type>franka_hw/FrankaStateInterface</type> <joint name="${arm_id}_joint1"><hardwareInterface>franka_hw/FrankaStateInterface</hardwareInterface></joint> <joint name="${arm_id}_joint2"><hardwareInterface>franka_hw/FrankaStateInterface</hardwareInterface></joint> <joint name="${arm_id}_joint3"><hardwareInterface>franka_hw/FrankaStateInterface</hardwareInterface></joint> <joint name="${arm_id}_joint4"><hardwareInterface>franka_hw/FrankaStateInterface</hardwareInterface></joint> <joint name="${arm_id}_joint5"><hardwareInterface>franka_hw/FrankaStateInterface</hardwareInterface></joint> <joint name="${arm_id}_joint6"><hardwareInterface>franka_hw/FrankaStateInterface</hardwareInterface></joint> <joint name="${arm_id}_joint7"><hardwareInterface>franka_hw/FrankaStateInterface</hardwareInterface></joint> <actuator name="${arm_id}_motor1"><hardwareInterface>franka_hw/FrankaStateInterface</hardwareInterface></actuator> <actuator name="${arm_id}_motor2"><hardwareInterface>franka_hw/FrankaStateInterface</hardwareInterface></actuator> <actuator name="${arm_id}_motor3"><hardwareInterface>franka_hw/FrankaStateInterface</hardwareInterface></actuator> <actuator name="${arm_id}_motor4"><hardwareInterface>franka_hw/FrankaStateInterface</hardwareInterface></actuator> <actuator name="${arm_id}_motor5"><hardwareInterface>franka_hw/FrankaStateInterface</hardwareInterface></actuator> <actuator name="${arm_id}_motor6"><hardwareInterface>franka_hw/FrankaStateInterface</hardwareInterface></actuator> <actuator name="${arm_id}_motor7"><hardwareInterface>franka_hw/FrankaStateInterface</hardwareInterface></actuator> </transmission> </xacro:macro> <!-- ============================================================ --> <!-- Adds the required tags to provide a `FrankaModelInterface` --> <!-- when simulating with franka_hw_sim plugin --> <!-- --> <!-- arm_id - Arm ID of the panda to simulate (default 'panda') --> <!-- root - Joint name of the base of the robot --> <!-- tip - Joint name of the tip of the robot (flange or hand) --> <!-- ============================================================ --> <xacro:macro name="transmission-franka-model" params="arm_id:=panda root:=panda_joint1 tip:=panda_joint7"> <transmission name="${arm_id}_franka_model"> <type>franka_hw/FrankaModelInterface</type> <joint name="${root}"> <role>root</role> <hardwareInterface>franka_hw/FrankaModelInterface</hardwareInterface> </joint> <joint name="${tip}"> <role>tip</role> <hardwareInterface>franka_hw/FrankaModelInterface</hardwareInterface> </joint> <actuator name="${root}_motor_root"><hardwareInterface>franka_hw/FrankaModelInterface</hardwareInterface></actuator> <actuator name="${tip}_motor_tip" ><hardwareInterface>franka_hw/FrankaModelInterface</hardwareInterface></actuator> </transmission> </xacro:macro> <xacro:macro name="inertia-cylinder" params="mass radius h"> <inertial> <mass value="${mass}" /> <inertia ixx="${1./12 * mass * (3 * radius**2 + h**2)}" ixy = "0" ixz = "0" iyy="${1./12 * mass * (3 * radius**2 + h**2)}" iyz = "0" izz="${1./2 * mass * radius**2}" /> </inertial> </xacro:macro> <!-- ========================================================================= --> <!-- Adds the <limit ... /> & <safety_controller/> tags given a config file --> <!-- of joint limits --> <!-- --> <!-- config - YAML struct defining joint limits (e.g. panda/joint_limits.yaml) --> <!-- name - Name of the joint for which to add limits to --> <!-- ========================================================================= --> <xacro:macro name="franka-limits" params="config name"> <xacro:property name="limits" value="${config[name]['limit']}" lazy_eval="false" /> <limit lower="${limits.lower}" upper="${limits.upper}" effort="${limits.effort}" velocity="${limits.velocity}" /> <safety_controller k_position="100.0" k_velocity="40.0" soft_lower_limit="${limits.lower}" soft_upper_limit="${limits.upper}" /> </xacro:macro> </robot>
franka_arm.axcro
<?xml version='1.0' encoding='utf-8'?> <robot xmlns:xacro="http://www.ros.org/wiki/xacro" name="panda"> <xacro:include filename="$(find franka_description)/robots/common/utils.xacro" /> <!-- safety_distance: Minimum safety distance in [m] by which the collision volumes are expanded and which is enforced during robot motions --> <!-- arm_id: Namespace of the robot arm. Serves to differentiate between arms in case of multiple instances. --> <!-- joint_limits: description of the joint limits that comes from a YAML file. Example definition: ${xacro.load_yaml('$(find franka_description)/robots/fr3/joint_limits.yaml')} --> <xacro:macro name="franka_arm" params="arm_id:='panda' description_pkg:='franka_description' connected_to:='' xyz:='0 0 0' rpy:='0 0 0' gazebo:=false safety_distance:=0 joint_limits" > <xacro:unless value="${not connected_to}"> <joint name="${arm_id}_joint_${connected_to}" type="fixed"> <parent link="${connected_to}"/> <child link="${arm_id}_link0"/> <origin rpy="${rpy}" xyz="${xyz}"/> </joint> </xacro:unless> <xacro:link_with_sc name="link0" gazebo="${gazebo}"> <self_collision_geometries> <xacro:collision_capsule xyz="-0.075 0 0.06" direction="x" radius="${0.06+safety_distance}" length="0.03" /> </self_collision_geometries> </xacro:link_with_sc> <xacro:link_with_sc name="link1" gazebo="${gazebo}"> <self_collision_geometries> <xacro:collision_capsule xyz="0 0 -191.5e-3" radius="${0.06+safety_distance}" length="0.283" /> </self_collision_geometries> </xacro:link_with_sc> <joint name="${arm_id}_joint1" type="revolute"> <origin rpy="0 0 0" xyz="0 0 0.333" /> <parent link="${arm_id}_link0" /> <child link="${arm_id}_link1" /> <axis xyz="0 0 1" /> <xacro:franka-limits name="joint1" config="${joint_limits}" /> <dynamics D="1" K="7000" damping="0.003" friction="0.0" mu_coulomb="0" mu_viscous="16" /> </joint> <xacro:link_with_sc name="link2" gazebo="${gazebo}"> <self_collision_geometries> <xacro:collision_capsule xyz="0 0 0" radius="${0.06+safety_distance}" length="0.12" /> </self_collision_geometries> </xacro:link_with_sc> <joint name="${arm_id}_joint2" type="revolute"> <origin rpy="${-pi/2} 0 0" xyz="0 0 0" /> <parent link="${arm_id}_link1" /> <child link="${arm_id}_link2" /> <axis xyz="0 0 1" /> <xacro:franka-limits name="joint2" config="${joint_limits}" /> <dynamics D="1" K="7000" damping="0.003" friction="0.0" mu_coulomb="0" mu_viscous="16" /> </joint> <xacro:link_with_sc name="link3" gazebo="${gazebo}"> <self_collision_geometries> <xacro:collision_capsule xyz="0 0 -0.145" radius="${0.06+safety_distance}" length="0.15" /> </self_collision_geometries> </xacro:link_with_sc> <joint name="${arm_id}_joint3" type="revolute"> <origin rpy="${pi/2} 0 0" xyz="0 -0.316 0" /> <parent link="${arm_id}_link2" /> <child link="${arm_id}_link3" /> <axis xyz="0 0 1" /> <xacro:franka-limits name="joint3" config="${joint_limits}" /> <dynamics D="1" K="7000" damping="0.003" friction="0.0" mu_coulomb="0" mu_viscous="16" /> </joint> <xacro:link_with_sc name="link4" gazebo="${gazebo}"> <self_collision_geometries> <xacro:collision_capsule xyz="0 0 0" radius="${0.06+safety_distance}" length="0.12" /> </self_collision_geometries> </xacro:link_with_sc> <joint name="${arm_id}_joint4" type="revolute"> <origin rpy="${pi/2} 0 0" xyz="0.0825 0 0" /> <parent link="${arm_id}_link3" /> <child link="${arm_id}_link4" /> <axis xyz="0 0 1" /> <xacro:franka-limits name="joint4" config="${joint_limits}" /> <dynamics D="1" K="7000" damping="0.003" friction="0.0" mu_coulomb="0" mu_viscous="16" /> </joint> <xacro:link_with_sc name="link5" gazebo="${gazebo}"> <self_collision_geometries> <xacro:collision_capsule xyz="0 0 -0.26" radius="${0.060+safety_distance}" length="0.10" /> <xacro:collision_capsule xyz="0 0.08 -0.13" radius="${0.025+safety_distance}" length="0.14" /> </self_collision_geometries> </xacro:link_with_sc> <joint name="${arm_id}_joint5" type="revolute"> <origin rpy="${-pi/2} 0 0" xyz="-0.0825 0.384 0" /> <parent link="${arm_id}_link4" /> <child link="${arm_id}_link5" /> <axis xyz="0 0 1" /> <xacro:franka-limits name="joint5" config="${joint_limits}" /> <dynamics D="1" K="7000" damping="0.003" friction="0.0" mu_coulomb="0" mu_viscous="16" /> </joint> <xacro:link_with_sc name="link6" gazebo="${gazebo}"> <self_collision_geometries> <xacro:collision_capsule xyz="0 0 -0.03" radius="${0.05+safety_distance}" length="0.08" /> </self_collision_geometries> </xacro:link_with_sc> <joint name="${arm_id}_joint6" type="revolute"> <origin rpy="${pi/2} 0 0" xyz="0 0 0" /> <parent link="${arm_id}_link5" /> <child link="${arm_id}_link6" /> <axis xyz="0 0 1" /> <xacro:franka-limits name="joint6" config="${joint_limits}" /> <dynamics D="1" K="7000" damping="0.003" friction="0.0" mu_coulomb="0" mu_viscous="16" /> </joint> <xacro:link_with_sc name="link7" gazebo="${gazebo}" rpy="0 0 ${pi/4}"> <self_collision_geometries> <xacro:collision_capsule xyz="0 0 0.01" direction="z" radius="${0.04+safety_distance}" length="0.14" /> <xacro:collision_capsule xyz="0.06 0 0.082" direction="x" radius="${0.03+safety_distance}" length="0.01" /> </self_collision_geometries> </xacro:link_with_sc> <joint name="${arm_id}_joint7" type="revolute"> <origin rpy="${pi/2} 0 0" xyz="0.088 0 0"/> <parent link="${arm_id}_link6"/> <child link="${arm_id}_link7"/> <axis xyz="0 0 1"/> <xacro:franka-limits name="joint7" config="${joint_limits}" /> <dynamics D="1" K="7000" damping="0.003" friction="0.0" mu_coulomb="0" mu_viscous="16"/> </joint> <link name="${arm_id}_link8"/> <joint name="${arm_id}_joint8" type="fixed"> <origin rpy="0 0 0" xyz="0 0 0.107"/> <parent link="${arm_id}_link7"/> <child link="${arm_id}_link8"/> </joint> </xacro:macro> </robot>
franka_hand.xacro
<?xml version="1.0" encoding="utf-8"?> <robot xmlns:xacro="http://www.ros.org/wiki/xacro" name="hand"> <!-- safety_distance: Minimum safety distance in [m] by which the collision volumes are expanded and which is enforced during robot motions --> <xacro:macro name="franka_hand" params="connected_to:='' arm_id:='panda' rpy:='0 0 0' xyz:='0 0 0' tcp_xyz:='0 0 0.1034' tcp_rpy:='0 0 0' safety_distance:=0 gazebo:=false description_pkg:=franka_description"> <xacro:unless value="${connected_to == ''}"> <joint name="${arm_id}_hand_joint" type="fixed"> <parent link="${connected_to}" /> <child link="${arm_id}_hand" /> <origin xyz="${xyz}" rpy="${rpy}" /> </joint> </xacro:unless> <xacro:link_with_sc name="hand" gazebo="${gazebo}"> <self_collision_geometries> <xacro:collision_capsule xyz="0 0 0.04" direction="y" radius="${0.04+safety_distance}" length="0.1" /> <xacro:collision_capsule xyz="0 0 0.10" direction="y" radius="${0.02+safety_distance}" length="0.1" /> </self_collision_geometries> </xacro:link_with_sc> <!-- Define the hand_tcp frame --> <link name="${arm_id}_hand_tcp" /> <joint name="${arm_id}_hand_tcp_joint" type="fixed"> <origin xyz="${tcp_xyz}" rpy="${tcp_rpy}" /> <parent link="${arm_id}_hand" /> <child link="${arm_id}_hand_tcp" /> </joint> <link name="${arm_id}_leftfinger"> <visual> <geometry> <mesh filename="package://${description_pkg}/meshes/visual/finger.dae" /> </geometry> </visual> <!-- screw mount --> <collision> <origin xyz="0 18.5e-3 11e-3" rpy="0 0 0" /> <geometry> <box size="22e-3 15e-3 20e-3" /> </geometry> </collision> <!-- cartriage sledge --> <collision> <origin xyz="0 6.8e-3 2.2e-3" rpy="0 0 0" /> <geometry> <box size="22e-3 8.8e-3 3.8e-3" /> </geometry> </collision> <!-- diagonal finger --> <collision> <origin xyz="0 15.9e-3 28.35e-3" rpy="${pi/6} 0 0" /> <geometry> <box size="17.5e-3 7e-3 23.5e-3" /> </geometry> </collision> <!-- rubber tip with which to grasp --> <collision> <origin xyz="0 7.58e-3 45.25e-3" rpy="0 0 0" /> <geometry> <box size="17.5e-3 15.2e-3 18.5e-3" /> </geometry> </collision> <xacro:if value="${gazebo}"> <xacro:inertial_props name="leftfinger" /> </xacro:if> </link> <link name="${arm_id}_rightfinger"> <visual> <origin xyz="0 0 0" rpy="0 0 ${pi}" /> <geometry> <mesh filename="package://${description_pkg}/meshes/visual/finger.dae" /> </geometry> </visual> <!-- screw mount --> <collision> <origin xyz="0 -18.5e-3 11e-3" rpy="0 0 0" /> <geometry> <box size="22e-3 15e-3 20e-3" /> </geometry> </collision> <!-- cartriage sledge --> <collision> <origin xyz="0 -6.8e-3 2.2e-3" rpy="0 0 0" /> <geometry> <box size="22e-3 8.8e-3 3.8e-3" /> </geometry> </collision> <!-- diagonal finger --> <collision> <origin xyz="0 -15.9e-3 28.35e-3" rpy="${-pi/6} 0 0" /> <geometry> <box size="17.5e-3 7e-3 23.5e-3" /> </geometry> </collision> <!-- rubber tip with which to grasp --> <collision> <origin xyz="0 -7.58e-3 45.25e-3" rpy="0 0 0" /> <geometry> <box size="17.5e-3 15.2e-3 18.5e-3" /> </geometry> </collision> <xacro:if value="${gazebo}"> <xacro:inertial_props name="rightfinger" /> </xacro:if> </link> <joint name="${arm_id}_finger_joint1" type="prismatic"> <parent link="${arm_id}_hand" /> <child link="${arm_id}_leftfinger" /> <origin xyz="0 0 0.0584" rpy="0 0 0" /> <axis xyz="0 1 0" /> <limit effort="100" lower="0.0" upper="0.04" velocity="0.2" /> <dynamics damping="0.3" /> </joint> <joint name="${arm_id}_finger_joint2" type="prismatic"> <parent link="${arm_id}_hand" /> <child link="${arm_id}_rightfinger" /> <origin xyz="0 0 0.0584" rpy="0 0 0" /> <axis xyz="0 -1 0" /> <limit effort="100" lower="0.0" upper="0.04" velocity="0.2" /> <mimic joint="${arm_id}_finger_joint1" /> <dynamics damping="0.3" /> </joint> </xacro:macro> </robot>
hand.urdf.xacro
<?xml version="1.0" encoding="utf-8"?> <robot xmlns:xacro="http://www.ros.org/wiki/xacro" name="hand"> <xacro:include filename="$(find franka_description)/robots/common/utils.xacro" /> <xacro:include filename="franka_hand.xacro"/> <xacro:franka_hand arm_id="panda" safety_distance="0.03"/> </robot>
inertial.yam
# This file does not contain official inertial properties # of panda robot. The values are from the identification # results published in: Identification of the Franka Robotics # PandaRobot With Retrieval of Feasible Parameters Using # Penalty-Based Optimization # by: Claudio Gaz, Marco Cognetti, Alexander Oliva, # Paolo Robuffo Giordano, Alessandro de Luca link0: origin: xyz: -0.041018 -0.00014 0.049974 rpy: 0 0 0 mass: 0.629769 inertia: xx: 0.00315 yy: 0.00388 zz: 0.004285 xy: 8.2904E-07 xz: 0.00015 yz: 8.2299E-06 link1: origin: xyz: 0.003875 0.002081 -0.04762 rpy: 0 0 0 mass: 4.970684 inertia: xx: 0.70337 yy: 0.70661 zz: 0.0091170 xy: -0.00013900 xz: 0.0067720 yz: 0.019169 link2: origin: xyz: -0.003141 -0.02872 0.003495 rpy: 0 0 0 mass: 0.646926 inertia: xx: 0.0079620 yy: 2.8110e-02 zz: 2.5995e-02 xy: -3.9250e-3 xz: 1.0254e-02 yz: 7.0400e-04 link3: origin: xyz: 2.7518e-02 3.9252e-02 -6.6502e-02 rpy: 0 0 0 mass: 3.228604 inertia: xx: 3.7242e-02 yy: 3.6155e-02 zz: 1.0830e-02 xy: -4.7610e-03 xz: -1.1396e-02 yz: -1.2805e-02 link4: origin: xyz: -5.317e-02 1.04419e-01 2.7454e-02 rpy: 0 0 0 mass: 3.587895 inertia: xx: 2.5853e-02 yy: 1.9552e-02 zz: 2.8323e-02 xy: 7.7960e-03 xz: -1.3320e-03 yz: 8.6410e-03 link5: origin: xyz: -1.1953e-02 4.1065e-02 -3.8437e-02 rpy: 0 0 0 mass: 1.225946 inertia: xx: 3.5549e-02 yy: 2.9474e-02 zz: 8.6270e-03 xy: -2.1170e-03 xz: -4.0370e-03 yz: 2.2900e-04 link6: origin: xyz: 6.0149e-02 -1.4117e-02 -1.0517e-02 rpy: 0 0 0 mass: 1.666555 inertia: xx: 1.9640e-03 yy: 4.3540e-03 zz: 5.4330e-03 xy: 1.0900e-04 xz: -1.1580e-03 yz: 3.4100e-04 link7: origin: xyz: 1.0517e-02 -4.252e-03 6.1597e-02 rpy: 0 0 0 mass: 7.35522e-01 inertia: xx: 1.2516e-02 yy: 1.0027e-02 zz: 4.8150e-03 xy: -4.2800e-04 xz: -1.1960e-03 yz: -7.4100e-04 hand: origin: xyz: -0.01 0 0.03 rpy: 0 0 0 mass: 0.73 inertia: xx: 0.001 yy: 0.0025 zz: 0.0017 xy: 0 xz: 0 yz: 0 leftfinger: &finger origin: xyz: 0 0 0 rpy: 0 0 0 mass: 0.015 inertia: xx: 2.3749999999999997e-06 yy: 2.3749999999999997e-06 zz: 7.5e-07 xy: 0 xz: 0 yz: 0 rightfinger: *finger
FER(Panda)同样适用:
xacro $(rospack find franka_description)/robots/panda/panda.urdf.axcro gazebo:=true
<?xml version='1.0' encoding='utf-8'?> <robot xmlns:xacro="http://www.ros.org/wiki/xacro" name="panda"> <xacro:include filename="$(find franka_description)/robots/common/franka_robot.xacro"/> <!-- Name for this robot --> <xacro:arg name="arm_id" default="panda" /> <!-- Should a franka_gripper be mounted at the flange?" --> <xacro:arg name="hand" default="false" /> <!-- Positional offset between $(arm_id)_hand -> $(arm_id)_hand_tcp [m]. Only used when hand:=true --> <xacro:arg name="tcp_xyz" default="0 0 0.1034" /> <!-- Rotational offset between $(arm_id)_hand -> $(arm_id)_hand_tcp [rad]. Only used when hand:=true --> <xacro:arg name="tcp_rpy" default="0 0 0" /> <!-- Is the robot being simulated in gazebo?" --> <xacro:arg name="gazebo" default="false" /> <!-- If `gazebo` arg is set, to which frame shall $(arm_id)_link0 be parented. Empty string for not fixing at all --> <xacro:arg name="parent" default="world" /> <!-- If `gazebo` arg is set and `parent` not empty, what position offset between `parent` & $(arm_id)_link0 --> <xacro:arg name="xyz" default="0 0 0" /> <!-- If `gazebo` arg is set and `parent` not empty, what rotation offset between `parent` & $(arm_id)_link0 --> <xacro:arg name="rpy" default="0 0 0" /> <xacro:franka_robot arm_id="$(arg arm_id)" joint_limits="${xacro.load_yaml('$(find franka_description)/robots/panda/joint_limits.yaml')}" hand="$(arg hand)" tcp_xyz="$(arg tcp_xyz)" tcp_rpy="$(arg tcp_rpy)" gazebo="$(arg gazebo)" parent="$(arg parent)" xyz="$(arg xyz)" rpy="$(arg rpy)"> </xacro:franka_robot> </robot>
体积碰撞
URDF定义了两种类型的碰撞类型:
-
精细:这些碰撞体积由凸网格构成,这些凸网格是每个链接的视觉网格 (.dae) 的近似版本,并且经过了大幅简化。精细体积应用于在Gazebo中模拟机器人碰撞
-
粗略:这些碰撞体积只是胶囊(带有两个半球形端盖的圆柱体),附在每个连杆上,并充气一定的安全距离。这些体积计算起来更高效,并在机器人内部用于自我碰撞避免。当您计划运动时(例如使用MoveIt ) ,请使用这些几何体。
您可以通过 XACRO 参数控制将哪个碰撞模型加载到 URDF 中gazebo
:
-
xacro ... panda.urdf.xacro gazebo:=false
:这将使用精细和粗糙碰撞模型。如果您完全省略参数,这也是默认设置。当您想要使用 MoveIt 时,请使用此选项 -
xacro ... panda.urdf.xacro gazebo:=true
:这将仅使用精细碰撞模型。当您想要可模拟的 URDF(例如 Gazebo)时,请使用此选项。当使用粗略碰撞模型时,机器人当然会与下一个链接的胶囊不断发生碰撞。
franka_gripper
franka_gripper_node
从 ROS 连接夹钳的功能。节点发布夹钳的状态并提供以下操作服务:franka_gripper::MoveAction(width, speed)
width
:移动到具有定义的 目标speed。
- franka_gripper::MoveAction(width, speed):以定义的速度移动到目标宽度。
- franka_gripper::GraspAction(width, epsilon_inner, epsilon_outer, speed, force):尝试以给定的速度和所需的力在目标宽度处抓取。当夹爪指间的距离在
epsilon_inner
和epsilon_outer
之间时,操作成功。 - franka_gripper::HomingAction():复位夹爪并根据安装的指头更新最大宽度。
- franka_gripper::StopAction():中止正在运行的动作。可以在抓取后用来停止施加力量。
- control_msgs::GripperCommandAction(width, max_effort):一个由 MoveIt! 识别的标准夹爪动作。如果参数
max_effort
大于零,夹爪将尝试以所需的宽度抓取物体。另一方面,如果max_effort
为零,夹爪将移动到所需的宽度。
注意: 仅在抓取物体时使用参数 max_effort
,否则夹爪将会闭合而忽略宽度参数。
franka_gripper_node
方式启动:roslaunch franka_gripper franka_gripper.launch robot_ip:=<fci-ip>
注意: 从franka_ros
0.6.0 开始,指定load_gripper:=true
也将启动。
roslaunch franka_control franka_control.launch
franka_hw
此包包含基于 API 的 ROS 控制框架的机器人硬件抽象libfranka
。此包中实现了硬件类,franka_hw::FrankaHW
为控制器提供了以下接口:
接口 | 功能 | 资源句柄名称 |
hardware_interface::JointStateInterface | 读取关节状态。 | "<arm_id>_joint1" 至 "<arm_id>_joint7" |
hardware_interface::VelocityJointInterface | 控制关节速度,并读取关节状态。 | "<arm_id>_joint1" 至 "<arm_id>_joint7" |
hardware_interface::PositionJointInterface | 控制关节位置并读取关节状态。 | "<arm_id>_joint1" 至 "<arm_id>_joint7" |
hardware_interface::EffortJointInterface | 控制关节扭矩并读取关节状态。 | "<arm_id>_joint1" 至 "<arm_id>_joint7" |
franka_hw::FrankaStateInterface | 读取机器人完整状。 | “<arm_id>_robot” |
franka_hw::FrankaPoseCartesianInterface | 控制笛卡尔位姿并读取机器人完整状态。 | “<arm_id>_robot” |
franka_hw::FrankaVelocityCartesianInterface | 控制笛卡尔速度并读取机器人完整状态。 | “<arm_id>_robot” |
franka_hw::FrankaModelInterface | 读取机器人的运动学和动力学模型。 | “<arm_id>_robot” |
要使用 ROS 控制接口,您必须通过名称检索资源句柄。
默认情况下,<arm_id> 设置为“panda”。
该类franka_hw::FrankaHW
还实现控制器的启动,停止和切换。
FrankaHW 类也作为 FrankaCombinableHW 的基类,后者是一种可以与其他硬件类组合以从单个控制器控制多个机器人的硬件类。基于 FrankaCombinableHW 的 ROS 控制框架中任意数量的 Panda 机器人(数量由参数配置)的组合在 FrankaCombinedHW 中实现。FrankaHW 和 FrankaCombinedHW 之间的主要区别在于后者仅支持力矩控制。
FrankaCombinableHW 类从 0.7.0 版本开始提供,并且仅支持力矩/力控制。
Ros参数服务器被用来决定运行时加载了哪些机器人,有关如何在相应的硬件节点中配置 FrankaCombinedHW 的示例,请参见 franka_control。
FrankaHW的方法是控制单个机器人的最佳方法。因此,我们建议仅在控制多个机器人时使用FrankaCombinableHW
/FrankaCombinedHW
类。
FrankaCombinableHW
/FrankaCombinedHW提供的接口如下:
接口 | 功能 |
hardware_interface::EffortJointInterface | 关节级别扭矩控制,并读取关节状态。 |
hardware_interface::JointStateInterface | 读取关节状态。 |
franka_hw::FrankaStateInterface | 读取机器人整体状态。 |
franka_hw::FrankaModelInterface | 读取机器人运动学和动力学模型。 |
唯一允许的命令接口声明是 EffortJointInterface,它可以与任何一组只读接口(FrankaModelInterface、JointStateInterface、FrankaStateInterface)结合使用。所有接口提供的资源句柄按名称声明,并遵循与 FrankaHW 相同的命名约定。每个 FrankaCombinableHW 实例都提供完整的服务和动作接口集(参见 franka_control)。
FrankaCombinedHW 类在控制节点命名空间中提供了一个额外的动作服务器,用于恢复所有机器人。如果任何机器人发生反射或错误,所有机器人的控制循环将停止,直到它们被恢复。
FrankaHW 使用 ROS joint_limits_interface 来强制执行位置、速度和力的安全限制。使用的接口如下所示:
- joint_limits_interface::PositionJointSoftLimitsInterface
- joint_limits_interface::VelocityJointSoftLimitsInterface
- joint_limits_interface::EffortJointSoftLimitsInterface
接近限制将导致命令的(未通知的)修改。
franka_control:
ROS节点franka_control_node和franka_combined_control_node 是用于ROS控制的硬件节点, 使用franka_hw中相应硬件类。他们提供各种ROS服务, 以libfranka在ROS生态系统中公开完整的API。 提供以下服务:
-
franka_msgs::SetJointImpedance
指定内部控制器的关节刚度(阻尼自动从刚度得出)。 -
franka_msgs::SetCartesianImpedance
指定内部控制器的笛卡尔刚度(阻尼自动从刚度得出)。 -
franka_msgs::SetEEFrame
指定从 <arm_id>_EE(末端执行器)到 <arm_id>_NE(名义末端执行器)框架的转换。从法兰到末端执行器框架的转换分为两个转换:<arm_id>_EE 到 <arm_id>_NE 框架和 <arm_id>_NE 到 <arm_id>_link8 框架。从 <arm_id>_NE 到 <arm_id>_link8 框架的转换只能通过管理员界面进行设置。 -
franka_msgs::SetKFrame
指定从 <arm_id>_K 到 <arm_id>_EE 坐标的转换。 -
franka_msgs::SetForceTorqueCollisionBehavior
设置外部笛卡尔的外力阈值来配置碰撞反射。 -
franka_msgs::SetFullCollisionBehavior
设置笛卡尔和关节层面的外力阈值来配置碰撞反射。 -
franka_msgs::SetLoad
设置外部负载来补偿(例如,抓住的物体)。 -
std_srvs::Trigger
服务允许连接和断开硬件节点(从 0.8.0 开始可用)。当没有活动(命令)控制器运行时,您可以断开硬件节点,释放相应的机器人以用于非 fci 应用程序,例如基于Desk的操作。一旦您想要恢复 fci 操作,您可以调用 connect 并再次启动基于 ros_control 的控制器。
要在机器人处于反射模式时从错误和反射中恢复,可以利用 franka_msgs::ErrorRecoveryAction
。这可以通过使用动作客户端或发布动作目标主题来实现。
具体来说:
-
使用动作客户端:
- 创建一个动作客户端来调用
franka_msgs::ErrorRecoveryAction
。 - 发送目标请求来恢复错误和反射状态。
- 等待动作服务器完成并获取结果。
- 创建一个动作客户端来调用
-
发布到动作目标主题:
- 发布一条
franka_msgs::ErrorRecoveryActionGoal
消息到/franka_control/error_recovery/goal
主题。 - 这将触发错误恢复流程,使机器人从反射模式中恢复过来。
- 发布一条
rostopic pub -1 /franka_control/error_recovery/goal franka_msgs/ErrorRecoveryActionGoal "{}"
恢复后,franka_control_node
将重新启动正在运行的控制器。这是可能的,因为当触发机器人反射或发生错误时节点不会死亡。所有这些功能均由 franka_control_node 提供,可以使用以下命令启动:
roslaunch franka_control franka_control.launch \ robot_ip:=<fci-ip> # mandatory \ load_gripper:=<true|false> # default: true \ robot:=<panda|fr3> # default: panda
除了加载franka_control_node, 启动文件还启动了一个franka_control::FrankaStateController, 用来读取和发布机器人状态, 包括外部力矩, 可配置变换,和rviz可视化所需要的关节状态。 为了可视化目的,一个robot_state_publisher节点被启动。
该包还实现了基于类的franka_combined_control_node
硬件节点。加载的机器人集通过 ROS 参数服务器配置。这些参数必须位于硬件节点的命名空间中(请参阅franka_combined_control_node.yaml 作为参考)并如下所示:
robot_hardware:
- panda_1
- panda_2
# (...)
panda_1:
type: franka_hw/FrankaCombinableHW
arm_id: panda_1
joint_names:
- panda_1_joint1
- panda_1_joint2
- panda_1_joint3
- panda_1_joint4
- panda_1_joint5
- panda_1_joint6
- panda_1_joint7
# Configure the threshold angle for printing joint limit warnings.
joint_limit_warning_threshold: 0.1 # [rad]
# Activate rate limiter? [true|false]
rate_limiting: true
# Cutoff frequency of the low-pass filter. Set to >= 1000 to deactivate.
cutoff_frequency: 1000
# Internal controller for motion generators [joint_impedance|cartesian_impedance]
internal_controller: joint_impedance
# Configure the initial defaults for the collision behavior reflexes.
collision_config:
lower_torque_thresholds_acceleration: [20.0, 20.0, 18.0, 18.0, 16.0, 14.0, 12.0] # [Nm]
upper_torque_thresholds_acceleration: [20.0, 20.0, 18.0, 18.0, 16.0, 14.0, 12.0] # [Nm]
lower_torque_thresholds_nominal: [20.0, 20.0, 18.0, 18.0, 16.0, 14.0, 12.0] # [Nm]
upper_torque_thresholds_nominal: [20.0, 20.0, 18.0, 18.0, 16.0, 14.0, 12.0] # [Nm]
lower_force_thresholds_acceleration: [20.0, 20.0, 20.0, 25.0, 25.0, 25.0] # [N, N, N, Nm, Nm, Nm]
upper_force_thresholds_acceleration: [20.0, 20.0, 20.0, 25.0, 25.0, 25.0] # [N, N, N, Nm, Nm, Nm]
lower_force_thresholds_nominal: [20.0, 20.0, 20.0, 25.0, 25.0, 25.0] # [N, N, N, Nm, Nm, Nm]
upper_force_thresholds_nominal: [20.0, 20.0, 20.0, 25.0, 25.0, 25.0] # [N, N, N, Nm, Nm, Nm]
panda_2:
type: franka_hw/FrankaCombinableHW
arm_id: panda_2
joint_names:
- panda_2_joint1
- panda_2_joint2
- panda_2_joint3
- panda_2_joint4
- panda_2_joint5
- panda_2_joint6
- panda_2_joint7
# Configure the threshold angle for printing joint limit warnings.
joint_limit_warning_threshold: 0.1 # [rad]
# Activate rate limiter? [true|false]
rate_limiting: true
# Cutoff frequency of the low-pass filter. Set to >= 1000 to deactivate.
cutoff_frequency: 1000
# Internal controller for motion generators [joint_impedance|cartesian_impedance]
internal_controller: joint_impedance
# Configure the initial defaults for the collision behavior reflexes.
collision_config:
lower_torque_thresholds_acceleration: [20.0, 20.0, 18.0, 18.0, 16.0, 14.0, 12.0] # [Nm]
upper_torque_thresholds_acceleration: [20.0, 20.0, 18.0, 18.0, 16.0, 14.0, 12.0] # [Nm]
lower_torque_thresholds_nominal: [20.0, 20.0, 18.0, 18.0, 16.0, 14.0, 12.0] # [Nm]
upper_torque_thresholds_nominal: [20.0, 20.0, 18.0, 18.0, 16.0, 14.0, 12.0] # [Nm]
lower_force_thresholds_acceleration: [20.0, 20.0, 20.0, 25.0, 25.0, 25.0] # [N, N, N, Nm, Nm, Nm]
upper_force_thresholds_acceleration: [20.0, 20.0, 20.0, 25.0, 25.0, 25.0] # [N, N, N, Nm, Nm, Nm]
lower_force_thresholds_nominal: [20.0, 20.0, 20.0, 25.0, 25.0, 25.0] # [N, N, N, Nm, Nm, Nm]
upper_force_thresholds_nominal: [20.0, 20.0, 20.0, 25.0, 25.0, 25.0] # [N, N, N, Nm, Nm, Nm]
# (+ more robots ...)
确保选择唯一且一致的arm_id
参数。ID 必须与关节名称中的前缀匹配,并且应符合加载到控制节点命名空间的机器人描述。
有关基于参数加载硬件类的更多信息,请参阅https://github.com/ros-controls/ros_controlcombined_robot_hw::CombinedRobotHW
的 官方文档。
第二个重要参数文件(请参阅 franka_ros/franka_control/config/default_combined_controllers.yaml 作为参考)配置了一组可随硬件节点启动的默认控制器。控制器必须与启动的硬件匹配。提供的默认参数化(此处针对 2 个机器人)如下所示:
panda_1_state_controller:
type: franka_control/FrankaStateController
arm_id: panda_1
joint_names:
- panda_1_joint1
- panda_1_joint2
- panda_1_joint3
- panda_1_joint4
- panda_1_joint5
- panda_1_joint6
- panda_1_joint7
publish_rate: 30 # [Hz]
panda_2_state_controller:
type: franka_control/FrankaStateController
arm_id: panda_2
joint_names:
- panda_2_joint1
- panda_2_joint2
- panda_2_joint3
- panda_2_joint4
- panda_2_joint5
- panda_2_joint6
- panda_2_joint7
publish_rate: 30 # [Hz]
# (+ more controllers ...)
我们提供了一个启动文件来运行franka_combined_control_node
用户指定的硬件和控制器配置文件,这些配置文件默认为 2 个机器人的配置。使用以下命令启动它:
roslaunch franka_control franka_combined_control.launch \ robot_ips:=<your_robot_ips_as_a_map> # mandatory robot:=<path_to_your_robot_description> \ args:=<xacro_args_passed_to_the_robot_description> \ # if needed robot_id:=<name_of_your_multi_robot_setup> \ hw_config_file:=<path_to_your_hw_config_file>\ # includes the robot ips! controllers_file:=<path_to_your_default_controller_parameterization>\ controllers_to_start:=<list_of_default_controllers_to_start>\ joint_states_source_list:=<list_of_sources_to_fuse_a_complete_joint_states_topic>
此启动文件可以参数化以运行任意数量的机器人。为此,只需以 franka_control/config/franka_combined_control_node.yaml 和 franka_ros/franka_control/config/default_combined_controllers.yaml 的样式编写您自己的配置文件。
确保将机器人的正确 IP作为映射传递给franka_combined_control.launch 。这看起来像: {<arm_id_1>/robot_ip: <my_ip_1>, <arm_id_2>/robot_ip: <my_ip_2>, …}
franka_visualization
此软件包包含连接到机器人并发布机器人和夹持器关节状态以便在 RViz 中可视化的发布器。要运行此软件包,请启动:
roslaunch franka_visualization franka_visualization.launch robot_ip:=<fci-ip> \ load_gripper:=<true|false> robot:=<panda|fr3>
仿真机器人请执行以下命令:
roslaunch franka_gazebo fr3/panda.launch
roslaunch franka_visualization franka_visualization.launch robot_ip:=fake_robot \ load_gripper:=<true|false> robot:=<panda|fr3>
这纯粹是为了可视化 - 没有向机器人发送任何命令。它可以用来检查与机器人的连接。
franka::Robot
实例可以连接到机器人。这意味着,例如 franka_joint_state_publisher
不能与 franka_control_node
并行运行。这也意味着你不能在运行控制器的单独程序的同时执行可视化示例。franka_example_controllers
此包中实现了一组用于通过ROS控制机器人的示例控制器。 控制器描述了franka_hw::FrankaHW类提供的各种接口及其相应用途。 每个示例都附带了一个单独的独立启动文件, 用于启动机器人上的控制器并将其可视化。
要启动关节阻抗运动示例, 请执行以下命令:
roslaunch franka_example_controllers joint_impedance_example_controller.launch \ robot_ip:=<fci-ip> load_gripper:=<true|false> robot:=<panda|fr3>
仿真机器人请执行以下命令:
roslaunch franka_example_controllers joint_impedance_example_controller.launch \ robot_ip:=fake_robot load_gripper:=<true|false> robot:=<panda|fr3>
其他单个Panda示例以同样的方式启动。
展示了如何使用一个实时控制器dual_arm_cartesian_impedance_example_controller
通过基于阻抗的控制方法完成笛卡尔任务来控制两个 Panda 机器人FrankaCombinedHW
。示例控制器可以通过以下方式启动:
roslaunch franka_example_controllers \ dual_arm_cartesian_impedance_example_controller.launch \ robot_id:=<name_of_the_2_arm_setup> \ robot_ips:=<your_robot_ips_as_a_map> \ rviz:=<true/false> rqt:=<true/false>
该示例假设机器人配置符合dual_panda_example.urdf.xacro,其中两个 Panda 安装在一个箱子顶部,相距 1 米。您可以随意用与您的设置相匹配的机器人描述替换此机器人描述。选项rviz允许选择是否应启动可视化。使用rqt,用户可以选择启动 rqt-gui,它允许在运行时通过动态重新配置在线调整渲染的末端执行器阻抗。
franka_gazebo
此软件包允许您在Gazebo中模拟我们的机器人。这是可能的,因为 Gazebo 能够使用 gazebo_ros软件包集成到 ROS 控制框架中。
注 : 此软件包从 0.8.0 开始可用.
拾取和放置示例
让我们深入模拟将一块石头从 A 运送到 B。运行以下命令,使用 Panda 和示例世界启动 Gazebo。
roslaunch franka_gazebo panda.launch x:=-0.5 \ world:=$(rospack find franka_gazebo)/world/stone.sdf \ controller:=cartesian_impedance_example_controller \ rviz:=true
这将打开 Gazebo GUI,您可以在其中看到带有石头和 RViz 的环境,您可以使用它们来控制机器人的末端执行器姿势。
要打开夹持器,只需向move
动作发送一个目标,类似于真实franka_gripper
工作方式。让我们将夹持器手指之间宽度移动到8𝑐𝑚,速度10cm/s。
rostopic pub --once /franka_gripper/move/goal franka_gripper/MoveActionGoal "goal: { width: 0.08, speed: 0.1 }"
由于我们使用来自franka_example_controllers的笛卡尔阻抗控制器启动了机器人 ,因此我们可以使用 RViz 中的交互式标记小工具移动末端执行器,就像在现实中一样。移动机器人,使白色石头位于夹持器的手指之间,随时可以被拾起。
如果机器人用肘部做出奇怪的动作,这是因为笛卡尔阻抗示例控制器的默认零空间刚度设置为低。启动动态重新配置 并根据需要进行panda
调整。
cartesian_impedance_example_controller nullspace_stiffness
为了拿起物体,我们grasp
这次使用了动作,因为我们想在抓握后施加一个力,以免物体掉落。石头在3𝑐𝑚宽阔和50𝑔沉重。让我们抓住它5𝑁:
rostopic pub --once /franka_gripper/grasp/goal \ franka_gripper/GraspActionGoal \ "goal: { width: 0.03, epsilon:{ inner: 0.005, outer: 0.005 }, speed: 0.1, force: 5.0}"
在 Gazebo 的顶部菜单中,转到“View”->Contacts, 以可视化接触点和力。
如果抓取成功,手指现在会将石头固定在原位。如果没有,可能是目标公差(内和外 epsilon)太小,导致操作失败。现在将物体轻轻移到红色落下区域。
stop
将其轻轻地放在红色垫上后,通过夹持器的动作停止抓取:
rostopic pub --once /franka_gripper/stop/goal franka_gripper/StopActionGoal {}
注意,由于不再施加力,接触力现在消失了。或者,您也可以使用动作move
。