sudo apt-get install ros-melodic-ros-control ros-melodic-ros-controllers
https://github.com/ros-controls/ros_controllers
不同的controller可以完成对不同模块的控制。例如完成对关节力的控制、速度控制等等。请求下层的硬件资源,并提供PID控制器,读取底层硬件资源的状态,发送控制指令。
可根据自己的需求,创建需要的controller,并通过Controller Manager来管理自己创建的controller,具体参考:https://github.com/ros-controls/ros_control/wiki/controller_interface
具体API参考http://docs.ros.org/melodic/api/hardware_interface/html/c++/namespacehardware__interface.html
ROS control 将硬件接口与ros_controller中的一个结合使用,以向硬件发送和接受命令。
Joint Command Interface - 支持命令关节阵列的硬件接口。请注意,这些命令可以具有任何语义含义,只要它们每个都可以由单个double表示即可,它们不一定是省力命令。要指定此命令的含义,请参见派生类:
Joint State Interfaces - 用于支持读取命名关节数组的状态,每个关节都有一些位置,速度和作用力(力或扭矩)。
Actuator State Interfaces - 用于支持读取命名的执行器阵列的状态,每个执行器都有一定的位置,速度和作用力(力或扭矩)。
Actuator Command Interfaces
Force-torque sensor Interface
IMU sensor Interface
http://docs.ros.org/melodic/api/hardware_interface/html/c++/annotated.html
创建自己的硬件接口可参考:https://github.com/ros-controls/ros_control/wiki/hardware_interface
加载、运行、停止等操作:
rosrun controller_manager controller_manager <command> <controller_name>
where,
为:
一次操作多个控制器:
# 加载控制器,但不运行
rosrun controller_manager spawner [--stopped] name1 name2 name3
# 加载控制器,并运行
rosrun controller_manager spawner name1 name2 name3
# 停止控制器,但不卸载
rosrun controller_manager unspawner name1 name2 name3
查看某个控制器状态:
rosrun controller_manager controller_manager <command>
where,
包括:
launch操作:
<launch>
<node pkg="controller_manager"
type="spawner"
args="controller_name1 controller_name2" />
launch>
<launch>
<node pkg="controller_manager"
type="spawner"
args="--stopped controller_name1 controller_name2" />
launch>
管理器可视化:
rosrun rqt_controller_manager rqt_controller_manager
机器人每个需要运动的关节都需要配置相应的Transmission,可通过代码完成,但多数情况下会在URDF文件中直接添加
<transmission name="simple_trans">
<type>transmission_interface/SimpleTransmissiontype>
<joint name="foo_joint">
<hardwareInterface>EffortJointInterfacehardwareInterface>
joint>
<actuator name="foo_motor">
<mechanicalReduction>50mechanicalReduction>
<hardwareInterface>EffortJointInterfacehardwareInterface>
actuator>
transmission>
Joint Limits
是硬件抽象层中的一块,维护一个关节限位的数据结构,这些限位数据可以从机器人的URDF文件中加载,也可以ROS的参数服务器上加载(先用YAML配置文件导入ROS parameter server).
限位数据包括:关节速度、位置、加速度、加加速度、力矩等方面的限位;
还包含安全作用的位置软限位、速度边界(k_v
)和位置边界(k_p
)等等。
URDF文件:
<joint name="$foo_joint" type="revolute">
<limit lower="0.0"
upper="1.0"
effort="10.0"
velocity="5.0" />
<safety_controller k_position="100"
k_velocity="10"
soft_lower_limit="0.1"
soft_upper_limit="0.9" />
joint>
YAML文件:
joints_limits:
foo_joint:
has_position_limits: true
min_position: 0.0
max_position: 1.0
has_velocity_limits: true
max_velocity: 2.0
has_acceleration_limits: true
max_acceleration: 5.0
has_jerk_limits: true
max_jerk: 100.0
has_effort_limits: true
max_effort: 5.0
bar_joint:
has_position_limits: false
has_velocity_limits: true
max_velocity: 4.0
URDF和YAML两种描述方式的区别:
① 目前只能通过URDF来指定软限位,URDF不支持加速度和加加速度限制,这些可通过YAML提供。
② YAML可覆盖URDF中描述的值
③ PID增益和控制器设置必须保存在yaml文件中,该文件通过roslaunch文件加载到参数服务器中
加载Joint limits配置代码:
#include
#include
#include
#include
int main(int argc, char** argv)
{
// Init node handle and URDF model
ros::NodeHandle nh;
boost::shared_ptr<urdf::ModelInterface> urdf;
// ...initialize contents of urdf
// Data structures
joint_limits_interface::JointLimits limits;
joint_limits_interface::SoftJointLimits soft_limits;
// Manual value setting
limits.has_velocity_limits = true;
limits.max_velocity = 2.0;
// Populate (soft) joint limits from URDF
// Limits specified in URDF overwrite existing values in 'limits' and 'soft_limits'
// Limits not specified in URDF preserve their existing values
boost::shared_ptr<const urdf::Joint> urdf_joint = urdf->getJoint("foo_joint");
const bool urdf_limits_ok = getJointLimits(urdf_joint, limits);
const bool urdf_soft_limits_ok = getSoftJointLimits(urdf_joint, soft_limits);
// Populate (soft) joint limits from the ros parameter server
// Limits specified in the parameter server overwrite existing values in 'limits' and 'soft_limits'
// Limits not specified in the parameter server preserve their existing values
const bool rosparam_limits_ok = getJointLimits("foo_joint", nh, limits);
}
配置joint limits接口
#include
using namespace hardware_interface;
using joint_limits_interface::JointLimits;
using joint_limits_interface::SoftJointLimits;
using joint_limits_interface::PositionJointSoftLimitsHandle;
using joint_limits_interface::PositionJointSoftLimitsInterface;
class MyRobot
{
public:
MyRobot() {}
bool init()
{
// Populate pos_cmd_interface_ with joint handles...
// Get joint handle of interest
JointHandle joint_handle = pos_cmd_interface_.getHandle("foo_joint");
JointLimits limits;
SoftJointLimits soft_limits;
// Populate with any of the methods presented in the previous example...
// Register handle in joint limits interface
PositionJointSoftLimitsHandle handle(joint_handle, // We read the state and read/write the command
limits, // Limits spec
soft_limits) // Soft limits spec
jnt_limits_interface_.registerHandle(handle);
}
void read(ros::Time time, ros::Duration period)
{
// Read actuator state from hardware...
// Propagate current actuator state to joints...
}
void write(ros::Time time, ros::Duration period)
{
// Enforce joint limits for all registered handles
// Note: one can also enforce limits on a per-handle basis: handle.enforceLimits(period)
jnt_limits_interface_.enforceLimits(period);
// Porpagate joint commands to actuators...
// Send actuator command to hardware...
}
private:
PositionJointInterface pos_cmd_interface_;
PositionJointSoftLimitsInterface jnt_limits_interface_;
};
<transmission name="simple_trans">
<type>transmission_interface/SimpleTransmissiontype>
<joint name="foo_joint">
<hardwareInterface>EffortJointInterfacehardwareInterface>
joint>
<actuator name="foo_motor">
<mechanicalReduction>50mechanicalReduction>
<hardwareInterface>EffortJointInterfacehardwareInterface>
actuator>
transmission>
注意:
:必须对应URDF中定义的关节名称
:传输类型,当前仅实现transmission_interface /SimpleTransmission
:在
和
标签中的,告诉gazebo_ros_control
插件要加载的硬件接口(位置,速度或力矩接口)。当前仅实现了EffortJointInterface
这一功能,当前仅支持Effort
接口<gazebo>
<plugin name="gazebo_ros_control" filename="libgazebo_ros_control.so">
<robotNamespace>/MYROBOTrobotNamespace>
plugin>
gazebo>
gazebo_ros_control
标签还有以下可选元素:
:用于此插件实例化的ROS命名空间,默认为URDF / SDF中机器人的名称
:控制器的更新周期(以秒为单位),默认为gazebo的周期
:URDF文件在参数服务器上的位置,默认为/ robot_description
:要使用的自定义机器人仿真接口的pluginlib名称,默认为DefaultRobotHWSim
默认情况下,如果没有
标签,gazebo_ros_control
将尝试从URDF中获取与基于ros_control的控制器接口所需的所有信息。
默认行为提供以下ros_control接口:
hardware_interface::JointStateInterface
hardware_interface::EffortJointInterface
hardware_interface::VelocityJointInterface
(未全实现)gazebo_ros_control
插件还提供了一个基于pluginlib
的接口,用于实现Gazebo
和ros_control
之间的自定义接口,以模拟更复杂的机制(非线性弹簧,连杆等)。
这些插件必须继承gazebo_ros_control :: RobotHWSim
,该插件实现了模拟的ros_control ``hardware_interface :: RobotHW
。RobotHWSim
提供API级访问,以在Gazebo
仿真器中读取和命令关节属性。
相应的RobotHWSim
子类在URDF模型中指定,并在加载机器人模型时加载。例如,以下XML将加载默认插件(与不使用
标签时的行为相同):
<gazebo>
<plugin name="gazebo_ros_control" filename="libgazebo_ros_control.so">
<robotNamespace>/MYROBOTrobotNamespace>
<robotSimType>gazebo_ros_control/DefaultRobotHWSimrobotSimType>
plugin>
gazebo>
参考文献: