初步总结一下自己对ros的认识,遇到的坑以及相应的解决办法。
首先介绍一下我的电脑配置,win10系统,装虚拟机Ubuntu16.04,ros版本kinetic.
我的学习资料主要来源:创客智造网站,ros官网,mooc网上面的ros课程(有的时候自己会遗漏一些点,上面可以了解到)
第一步是Ubuntu的使用,如果不熟悉Ubuntu的话,可以去一个叫 实验楼的网站上学习Ubuntu的基本操作,命令。
第二部ros的安装,按照创客智造上面的操作步骤就可以完成安装了,但是使用过程中遇到了两个问题,都是和gazebo有关,
export SVGA_VGPU10=0
export LIBGL_ ALWAYS_SOFTWARE=0
加上第二行代码可以减小 coreDump发生的概率。
第三 使用的IDE是roboware,关于roboware的教程很多,但是有几个注意的点,
这个小按钮可以record topic.
这两个按钮可以切换活动包
这里可以安装包以及对没有安装的包进行安装。之前从github上面克隆的代码在本地一直编译不过去,很久找不到原因,后来才发现自己克隆错了,在git clone 的时候,加上-b 参数克隆正确的分支,我的就是 git clone -b branch gitsource.
第四部分,ros的基本概念是运行单元是node,通过topic,service,actonlib等进行通信。
rviz只是ros的一个展示数据的一个工具,仅仅用来展示二维或者三维数据。
gazebo是一个仿真环境,用来模拟真实的环境。
学习ros一定想要创建一个模型,并且在ros中控制它。首先学习urdf来创建机器人模型,urdf主要包括两部分,一个是link(肢体),另外一个是joint(关节),link通过joint链接在一起,joint有一些固定的类型,不同的类型就不同的参数配置。这里需要注意的是link之间的相关位置计算。 每个link对应一个坐标系,不同的link的坐标系的转换通过joint,joint不仅定义了关节的类型,还有joint 的parent和children 之间的坐标系转换, gazebo里面简单的shape存在固定的中心,link有一个origin属性,像这样
<origin xyz="1 2 1" rpy="0 0 0" />
这个属性定义了关节在自己的坐标中的偏移和转向。r代表绕X轴旋转的弧度,p代表绕Y轴旋转的弧度,y代表绕Z轴旋转的弧度。
joint中也存在这个属性,
<joint name="base_to_child" type="continuous">
<parent link="base_link"/>
<child link="child"/>
<origin xyz="1 1 1" rpy="0 0 0" />
</joint>
像这样。
rviz中存在一个插件叫robotModel,他会从 rosparams中获得robotdescption(urdf文本)参数,进行展示,并且监听不同link之间的tf转换消息,你可以启动joint_state_publisher,robot_state_publisher节点,他也会去读取robotdescption参数,然后展现出一个界面,来发布tf变换到rviz的robotModel插件中进行展示,rviz中就可以展示出相应的效果出来。
gazebo中渲染机器人并且控制它,
<gazebo>
<plugin name="gazebo_ros_control" filename="libgazebo_ros_control.so">
</plugin>
</gazebo>
模型中一定要存在这个插件,这件插件的作用官网上写的是链接ros和gazebo,
class GazeboRosControlPlugin : public gazebo::ModelPlugin
{
public:
virtual ~GazeboRosControlPlugin();
// Overloaded Gazebo entry point
virtual void Load(gazebo::physics::ModelPtr parent, sdf::ElementPtr sdf);
// Called by the world update start event
void Update();
// Called on world reset
virtual void Reset();
// Get the URDF XML from the parameter server
std::string getURDF(std::string param_name) const;
// Get Transmissions from the URDF
bool parseTransmissionsFromURDF(const std::string& urdf_string);
这个是libgazebo_ros_control.so中插件的头文件,GazeboRosControlPlugin 是一个gazebo的model插件,可以看到gazebo和ros链接的过程是,gazebo启动gazebo插件:GazeboRosControlPlugin ,这个插件再负责其他的工作,比如说初始化controllermanager来管理不同的控制器,下面就是初始化控制器的代码。
robot_hw_sim_loader_.reset
(new pluginlib::ClassLoader<gazebo_ros_control::RobotHWSim>
("gazebo_ros_control",
"gazebo_ros_control::RobotHWSim"));
robot_hw_sim_ = robot_hw_sim_loader_->createInstance(robot_hw_sim_type_str_);
urdf::Model urdf_model;
const urdf::Model *const urdf_model_ptr = urdf_model.initString(urdf_string) ? &urdf_model : NULL;
if(!robot_hw_sim_->initSim(robot_ns, model_nh_, parent_model_, urdf_model_ptr, transmissions_))
{
ROS_FATAL_NAMED("gazebo_ros_control","Could not initialize robot simulation interface");
return;
}
// Create the controller manager
ROS_DEBUG_STREAM_NAMED("ros_control_plugin","Loading controller_manager");
controller_manager_.reset
(new controller_manager::ControllerManager(robot_hw_sim_.get(), model_nh_));
// Listen to the update event. This event is broadcast every simulation iteration.
update_connection_ =
gazebo::event::Events::ConnectWorldUpdateBegin
(boost::bind(&GazeboRosControlPlugin::Update, this));
关于控制器更新的细节,我也有待更加深入的学习,
控制gazebo中一个关节的过程是,首先有一个urdf文件,配置好关节的物理参数,配置好关节的transmission信息,
类似
<transmission name="trans_${linkName}">
<type>transmission_interface/SimpleTransmission</type>
<actuator name="actuator_${linkName}">
<mechanicalReduction>1</mechanicalReduction>
</actuator>
<joint name="base_to_${linkName}">
<hardwareInterface>hardware_interface/EffortJointInterface</hardwareInterface>
</joint>
</transmission>
关节主要是配置hardwareInterface接口,接口类型主要有三种,力接口,速度接口,位置接口,分别控制关节的力,速度,位置。然后加载实现指定接口的控制器信息到ros的参数服务器中,gazebo节点就会监听相应关节的command话题,就可以发布参数到指定话题来达到控制关节的目的。
学会控制关节之后就是slam,建图算法订阅/scan话题等后发布map话题,表达算法建的图,move_base得到map信息,然后根据acml算法等进行定位,然后告诉move_base一个目标点,move_base就会构建一个通向目标的路径,并且发布控制速度和转向信息,根据速度,转向信息就可以达到设定的目标点了,大致过程就是这样的。