基于autoware的点云建图、定位与巡线系统:NDT建图定位+Pure Pursuit巡线行...
基于autoware的点云建图,定位,巡线 这套代码是移植autoware部分有用的代码,精简过后,加上自己的一些代码组成的 功能: 1.ndt建图 2.ndt定位 3.pure pursuit巡线行驶 4.简单的界面操作 包配置好环境,跑通仿真。
直接上代码!今天咱们聊聊这个基于Autoware魔改的点云处理系统。别看它现在跑得溜,当初移植代码时差点把键盘砸了——Autoware那套东西实在臃肿得像个两百斤的胖子。
先看建图模块的核心,NDT配准这块我保留了关键处理逻辑。下面这段代码是点云预处理的核心:
void ndt_mapping_node::cloud_callback(const sensor_msgs::PointCloud2::ConstPtr& msg){
pcl::PointCloud<pcl::PointXYZI>::Ptr raw_cloud(new pcl::PointCloud<pcl::PointXYZI>);
pcl::fromROSMsg(*msg, *raw_cloud);
// 体素滤波直接砍掉70%数据量
pcl::VoxelGrid<pcl::PointXYZI> vg;
vg.setLeafSize(0.5f, 0.5f, 0.3f);
vg.setInputCloud(raw_cloud);
vg.filter(*current_cloud_);
// 动态调整NDT分辨率
if(iter_count_ % 10 == 0){
ndt_.setResolution(ndt_.getResolution() * 0.98);
}
iter_count_++;
}
这里有个骚操作——动态调整NDT分辨率。初始用低分辨率快速匹配,随着迭代次数增加逐步提高精度。实测比固定参数建图速度快了40%,代价是偶尔在长廊环境会出现鬼影,后来加了运动约束才搞定。
定位模块最头疼的是TF树维护。Autoware原生的坐标系管理复杂得像蜘蛛网,我直接重写了TF处理部分:
def integrated_odom_callback(msg):
global last_correction_time
current_time = msg.header.stamp.to_sec()
# 超过2秒没收到NDT修正就报警
if current_time - last_correction_time > 2.0:
publish_alert(ALERT_LOCALIZATION_DEGRADE)
# 用滑动窗口融合数据
correction_window.append(msg.pose)
if len(correction_window) > 5:
correction_window.pop(0)
fused_pose = average_poses(correction_window)
tf_broadcaster.sendTransform(fused_pose)
这里实现了个滑动窗口融合算法,有效解决了NDT偶尔跳变的问题。不过实测在急转弯时会有滞后现象,后来把窗口大小改成动态调整才算完美。
巡线用的Pure Pursuit算法,核心是这个路径跟踪函数:
double calculate_steering_angle(const geometry_msgs::Pose& current_pose,
const std::vector<geometry_msgs::Pose>& path){
// 找最近路径点
auto closest_it = find_closest_point(current_pose, path);
// 前视距离动态调整
double lookahead = BASE_LOOKAHEAD * (1 + fabs(current_speed)/MAX_SPEED);
// 搜索目标点
auto target_it = find_target(closest_it, path.end(), lookahead);
// 纯追踪公式实现
double alpha = atan2(target_it->position.y - current_pose.position.y,
target_it->position.x - current_pose.position.x);
double delta = atan2(2.0 * WHEELBASE * sin(alpha - current_pose.theta),
lookahead);
return delta * 0.8; // 加了衰减系数防止震荡
}
注意这里的前视距离是动态计算的,车速越快看得越远。但实测在8字型路径上会有控制震荡,后来在转角处加了速度限制才解决。
界面部分用PyQt搞了个极简控制台,最实用的功能是这个点云显示开关:
self.pointcloud_toggle = QCheckBox("显示点云层")
self.pointcloud_toggle.stateChanged.connect(
lambda state: rospy.set_param('/viz/show_pointcloud', state==2)
)
其实就是在Rviz里动态切换显示配置。为了让参数生效,不得不重新设计了个参数管理中间件,绕过ROS的参数服务器机制。
仿真环境搭建时踩了个大坑——Gazebo默认的重力设置会导致点云投影在地面下方。解决办法是在启动文件里加上这行魔法参数:
<arg name="world_name" value="$(find sim_env)/worlds/ground_plane_only.world"/>
这套系统现在能在20系显卡上跑出30Hz的定位频率,建图精度控制在±15cm以内。不过内存占用还是有点高,下一步准备把点云处理换成CUDA加速。有朋友问为什么不直接用LIO-SAM?问就是甲方爸爸指定要Autoware方案啊(手动狗头)
更多推荐
所有评论(0)