差速机器人:从STM32到ROS,实现高精度导航
两轮/四轮差速机器人底层STM32源码与ROS端工程源码。可实现gmapping、cartographer建图算法与move_base导航算法配合实现高精度定位、定点导航、自主导航。已在实机完成测试,采用拓展卡尔曼滤波ekf融合imu与里程计进行数据融合,实现高精度定位导航。注:该工程是源码最近搞了个超有意思的项目——两轮/四轮差速机器人,今天就来跟大家唠唠这个项目里底层STM32源码与ROS端工
两轮/四轮差速机器人底层STM32源码与ROS端工程源码。 可实现gmapping、cartographer建图算法与move_base导航算法配合实现高精度定位、定点导航、自主导航。 已在实机完成测试,采用拓展卡尔曼滤波ekf融合imu与里程计进行数据融合,实现高精度定位导航。 注:该工程是源码
最近搞了个超有意思的项目——两轮/四轮差速机器人,今天就来跟大家唠唠这个项目里底层STM32源码与ROS端工程源码的事儿,这里面涉及到的建图和导航算法超酷炫!
底层STM32源码
STM32作为机器人的底层控制核心,负责接收各种传感器数据并驱动电机。在电机驱动这块,我们通过定时器产生PWM信号来控制电机的转速,代码如下:
// 初始化定时器,用于产生PWM信号
void TIM3_PWM_Init(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
// 使能TIM3和相关GPIO时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
// 配置PA6 (TIM3_CH1)为复用推挽输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_TIM3);
// 定时器基本配置
TIM_TimeBaseStructure.TIM_Period = 999;
TIM_TimeBaseStructure.TIM_Prescaler = 83;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
// PWM模式配置
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 0;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(TIM3, &TIM_OCInitStructure);
// 使能定时器
TIM_Cmd(TIM3, ENABLE);
}
这段代码里,先初始化了GPIO引脚,将PA6配置为复用推挽输出,以便连接电机驱动芯片。接着设置定时器TIM3的周期、预分频器等参数,最后配置为PWM1模式并使能定时器。这样就可以通过改变TIM3_CH1的占空比来控制电机转速啦。
ROS端工程源码
ROS端的代码可就更有意思了,这里涉及到gmapping、cartographer建图算法以及move_base导航算法。
gmapping建图算法
在ROS中使用gmapping,需要配置相应的launch文件。下面是一个简单的gmapping.launch文件示例:
<launch>
<node pkg="gmapping" type="slam_gmapping" name="slam_gmapping">
<param name="base_frame" value="base_link"/>
<param name="odom_frame" value="odom"/>
<param name="map_update_interval" value="5.0"/>
<param name="maxUrange" value="8.0"/>
<param name="sigma" value="0.05"/>
<param name="kernelSize" value="1"/>
<param name="lstep" value="0.05"/>
<param name="astep" value="0.05"/>
<param name="iterations" value="5"/>
<param name="lsigma" value="0.075"/>
<param name="ogain" value="3.0"/>
<param name="lskip" value="0"/>
<param name="askip" value="0"/>
<param name="srr" value="0.1"/>
<param name="srt" value="0.2"/>
<param name="str" value="0.1"/>
<param name="stt" value="0.2"/>
<param name="linearUpdate" value="0.5"/>
<param name="angularUpdate" value="0.4363323129985824"/>
<param name="temporalUpdate" value="3.0"/>
<param name="resampleThreshold" value="0.5"/>
<param name="particles" value="80"/>
<param name="xmin" value="-10.0"/>
<param name="ymin" value="-10.0"/>
<param name="xmax" value="10.0"/>
<param name="ymax" value="10.0"/>
<param name="delta" value="0.05"/>
<param name="llsamplerange" value="0.01"/>
<param name="llsamplestep" value="0.01"/>
<param name="lasamplerange" value="0.005"/>
<param name="lasamplestep" value="0.005"/>
</node>
</launch>
这个launch文件里,配置了gmapping算法所需的各种参数,比如基础坐标系、里程计坐标系、地图更新间隔等。通过这些参数的调整,可以优化建图效果。
cartographer建图算法
cartographer建图也很强大,以cartographer_ros的配置为例,在cartographer.launch文件中:
<launch>
<node name="cartographer_node" pkg="cartographer_ros" type="cartographer_node" args="
-configuration_directory $(find my_cartographer_config)/config
-configuration_basename my_configuration.lua" output="screen">
<remap from="scan" to="base_scan"/>
</node>
<node name="cartographer_occupancy_grid_node" pkg="cartographer_ros" type="cartographer_occupancy_grid_node" args="-resolution 0.05">
<remap from="map" to="cartographer_map"/>
</node>
</launch>
这里通过cartographernode节点运行cartographer算法,指定了配置文件的路径和名称,并且通过cartographeroccupancygridnode节点将生成的地图转换为ROS标准的Occupancy Grid格式。
move_base导航算法
movebase是ROS中经典的导航算法包,通过配置一系列参数来实现机器人的自主导航。在movebase.launch文件中:
<launch>
<node pkg="move_base" type="move_base" respawn="false" name="move_base" output="screen">
<rosparam file="$(find my_navigation_config)/costmap_common_params.yaml" command="load" ns="global_costmap"/>
<rosparam file="$(find my_navigation_config)/costmap_common_params.yaml" command="load" ns="local_costmap"/>
<rosparam file="$(find my_navigation_config)/local_costmap_params.yaml" command="load" ns="local_costmap"/>
<rosparam file="$(find my_navigation_config)/global_costmap_params.yaml" command="load" ns="global_costmap"/>
<rosparam file="$(find my_navigation_config)/base_local_planner_params.yaml" command="load"/>
</node>
</launch>
这里加载了全局和局部代价地图的配置文件,以及基础局部规划器的参数文件,move_base会根据这些配置来规划路径,实现机器人的定点导航和自主导航。
数据融合:拓展卡尔曼滤波(EKF)
为了实现高精度定位导航,我们采用了拓展卡尔曼滤波(EKF)来融合IMU与里程计的数据。在ROS中,有现成的EKF包可以使用,配置也相对简单。在ekf.launch文件中:
<launch>
<node pkg="robot_pose_ekf" type="robot_pose_ekf" name="robot_pose_ekf">
<param name="output_frame" value="odom_combined"/>
<param name="freq" value="30.0"/>
<param name="sensor_timeout" value="1.0"/>
<param name="imu0" value="/imu/data"/>
<param name="imu0_config" value="$(find my_ekf_config)/imu0.yaml"/>
<param name="odom0" value="/odom"/>
<param name="odom0_config" value="$(find my_ekf_config)/odom0.yaml"/>
</node>
</launch>
这里配置了EKF节点,指定了输出坐标系、频率、传感器超时时间等参数,同时加载了IMU和里程计对应的配置文件。通过这些配置,EKF能够有效地融合两种传感器的数据,提高定位精度。

两轮/四轮差速机器人底层STM32源码与ROS端工程源码。 可实现gmapping、cartographer建图算法与move_base导航算法配合实现高精度定位、定点导航、自主导航。 已在实机完成测试,采用拓展卡尔曼滤波ekf融合imu与里程计进行数据融合,实现高精度定位导航。 注:该工程是源码
这个两轮/四轮差速机器人项目,从底层的STM32控制到ROS端的复杂算法实现,经过实机测试,成功实现了高精度定位、定点导航和自主导航。感兴趣的小伙伴可以一起探讨呀!

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐


所有评论(0)