欢迎光临
我们一直在努力

autoware-gazebo模型航迹点纯追踪导航

在上一篇文章中,构建了航迹点。使用autoware自带的模型、bag数据包回放的形式加载了纯追踪算法。为此在这里使用纯追踪算法使得gazebo中的模型进行路径跟踪,纯追踪算法代码已经按照车辆模型修改并编译。

参考链接

https://blog.csdn.net/weixin_45168199/article/details/123300238?fromshare=blogdetail&sharetype=blogdetail&sharerId=123300238&sharerefer=PC&sharesource=2201_76065173&sharefrom=from_link

https://blog.csdn.net/2201_76065173/article/details/157171135?fromshare=blogdetail&sharetype=blogdetail&sharerId=157171135&sharerefer=PC&sharesource=2201_76065173&sharefrom=from_link

一、加载gazebo模型

1.1、启动launch文件gazebo_tyut_jjc_model.launch

<launch>
<!– 设置使用仿真时间 –>
<param name="/use_sim_time" value="true"/>
<!– 启动Gazebo时确保时间同步 –>
<include file="$(find gazebo_ros)/launch/empty_world.launch">
<arg name="paused" value="false"/>
<arg name="use_sim_time" value="true"/>
<arg name="gui" value="true"/>
<arg name="headless" value="false"/>
<arg name="debug" value="false"/>
</include>
<!– ===== 加载地图环境 ===== –>
<group ns="environment">
<!– 生成地下环境模型 –>
<node name="spawn_underground_environment" pkg="gazebo_ros" type="spawn_model"
args="-file $(find underground_environment)/urdf/underground_environment.urdf
-urdf
-model underground_environment
-x 0.0 -y 0.0 -z 0.0
-R 0.0 -P 0.0 -Y 0.0"
output="screen" />
<!– 固定地图到世界坐标系 –>
<node name="world_to_environment_tf" pkg="tf" type="static_transform_publisher"
args="0 0 0 0 0 0 world underground_environment 100" />
</group>
<!– 将xacro先加载到robot_description,再加载到Gazebo仿真环境中 –>
<param
name="robot_description"
command="$(find xacro)/xacro $(find tyut_jjc)/urdf/tyut_jjc_model.xacro" />
<node
name="spawn_model"
pkg="gazebo_ros"
type="spawn_model"
args="-param robot_description -urdf -model tyut_jjc_model -x 2.4 -y 0 -z 0 -R 0 -P 0 -Y 0"
output="screen" />
<!– 加载控制启动文件 –>
<include file="$(find my_robot_control)/launch/my_robot_control.launch" />
<!– 发布机器人到world坐标TF –>
<node name="gazebo_robot_tf" pkg="my_robot_control" type="gazebo_robot_tf.py" output="screen"/>
<!– 启动RViz并加载预定义的配置文件urdf.rviz –>
<node name="rviz" pkg="rviz" type="rviz" args="-d $(find tyut_jjc)/config/tyut_jjc_model_rviz.rviz">
</node>

</launch>

  • 启用仿真时间
  • 加载环境地图
  • 加载gazebo车辆模型以及定义初始位姿
  • 加载控制文件(底盘控制、轮速提取)
  • 发布坐标变换和打开rviz配置
  • 其中gazebo模型加载文件以及控制文件如下:

    <robot name="tyut_jjc_model" xmlns:xacro="http://wiki.ros.org/xacro">
    <xacro:include filename="xacro/tyut_jjc.xacro" />
    <xacro:include filename="xacro/transmission.xacro" />
    <xacro:include filename="xacro/gazebo_ros_control.xacro" />
    <xacro:include filename="xacro/tyut_color.xacro" />
    <xacro:include filename="xacro/tyut_mu.xacro" />
    <xacro:include filename="xacro/laser.xacro" />
    <xacro:HDL-32E parent="base_link" name="velodyne" topic="/points_raw" hz="10" samples="1800" gpu="false">
    <origin xyz="0 0 1.0" rpy="0 0 0" />
    </xacro:HDL-32E>
    <xacro:include filename="xacro/imu.xacro" />
    <xacro:include filename="xacro/camera.xacro" />

    </robot>

    <launch>
    <!– 加载控制器、PID、控制频率、控制关节参数 –>
    <rosparam file="$(find my_robot_control)/config/control.yaml" command="load"/>
    <!– 启动控制器 (不包含oint_state_controller)–>
    <node name="controller_manager" pkg="controller_manager" type="controller_manager"
    respawn="false" output="screen"
    args="spawn
    joint_state_controller
    joint1_velocity_controller
    joint2_velocity_controller
    joint3_velocity_controller
    joint4_velocity_controller
    joint5_position_controller" />
    <!– 发布机器人各个Link之间的TF –>
    <node pkg="robot_state_publisher" type="robot_state_publisher" name="robot_state_publisher" output="screen" />
    <!– 启动底盘控制策略 –>
    <node name="cmdvel2gazebo" pkg="my_robot_control"
    type="cmdvel_to_gazebo.py" respawn="false" output="screen"/>
    <!– 轮速转化 –>
    <node name="wheel_velocity_converter" pkg="my_robot_control"
    type="wheel_to_velocity.py" respawn="false" output="screen"/>

    <!– 启动控制面板 –>
    <!– <node name="rqt_robot_steering" pkg="rqt_robot_steering" type="rqt_robot_steering" /> –>

    </launch>
    tyut@tyut-jjc:~$ cd ~/A_JJC_ws/
    tyut@tyut-jjc:~/A_JJC_ws$ source devel/setup.bash
    tyut@tyut-jjc:~/A_JJC_ws$ roslaunch tyut_jjc gazebo_tyut_jjc_model.launch

    二、启用gazebo位置读取到定位信息

    2.1、使用自己的py节点,读取gazebo的位姿作为定位

    tyut@tyut-jjc:~/A_JJC_ws/src/my_robot_control/scripts$ ./gazebo_pose_to_ndt.py

    2.2、启动Vel pose connect,关联位姿态和速度

    注意,如果使用角度控制需要开启publishes_for_steering_robot_=true

    才能发布/ctrl_raw,输出角度控制量

    2.3、启动ctrl_cmd_to_cmd_vel.py速度转换节点,转换到cmd_vel控制小车底盘

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-

    import rospy
    from geometry_msgs.msg import Twist
    from autoware_msgs.msg import ControlCommandStamped

    class CtrlCmdToCmdVel:
    def __init__(self):
    rospy.init_node('ctrl_cmd_to_cmd_vel')

    # 订阅 ctrl_cmd 话题
    rospy.Subscriber('ctrl_cmd', ControlCommandStamped, self.ctrl_cmd_callback)

    # 发布 cmd_vel 话题
    self.cmd_vel_pub = rospy.Publisher('cmd_vel', Twist, queue_size=10)

    def ctrl_cmd_callback(self, ctrl_cmd_msg):
    # 从 ctrl_cmd 消息中提取线速度和角速度
    linear_vel = ctrl_cmd_msg.cmd.linear_velocity
    angular_vel = ctrl_cmd_msg.cmd.steering_angle

    # 创建 Twist 消息
    cmd_vel_msg = Twist()
    cmd_vel_msg.linear.x = linear_vel
    cmd_vel_msg.angular.z = angular_vel

    # 发布转换后的消息到 cmd_vel 话题
    self.cmd_vel_pub.publish(cmd_vel_msg)

    if __name__ == '__main__':
    try:
    ctrl_cmd_to_cmd_vel = CtrlCmdToCmdVel()
    rospy.spin()
    except rospy.ROSInterruptException:
    pass

    注意:纯追踪算法输出两个控制话题twist_raw与/ctrl_raw,具体区别与使用如下:

    /twist_cmd与/ctrl_cmd是经过滤波器限制后的输出,节点对应 twist_raw与/ctrl_raw

    twist_raw输出角速度;/ctrl_raw输出角度

    // 代码中实际发布的话题(对应你的 twist_cmd/ctrl_cmd)
    pub1_ = nh_.advertise<geometry_msgs::TwistStamped>("twist_raw", 10); // 对应 twist_cmd
    pub2_ = nh_.advertise<autoware_msgs::ControlCommandStamped>("ctrl_raw", 10); // 对应 ctrl_cmd

    其中 twist_raw线速度来源,瞬时角速度—-角速度来源w=v/r

    2.3.1  twist_raw  输出角速度

    void PurePursuitNode::publishTwistStamped(
    const bool& can_get_curvature, const double& kappa) const
    {
    geometry_msgs::TwistStamped ts;
    ts.header.stamp = ros::Time::now();
    // ① 线速度(linear.x)来源
    ts.twist.linear.x = can_get_curvature ? computeCommandVelocity() : 0;
    // ② 角速度(angular.z)来源
    ts.twist.angular.z = can_get_curvature ? kappa * ts.twist.linear.x : 0;
    pub1_.publish(ts);
    }

    线速度 linear.x 来源:computeCommandVelocity() 函数
    根据 velocity_source_ 配置(从 config/waypoint_follower 话题读取)决定线速度

    double PurePursuitNode::computeCommandVelocity() const
    {
    // 情况1:velocity_source_ = 0(dialog模式)→ 使用配置文件的 const_velocity_(默认5.0 km/h)
    if (velocity_source_ == enumToInteger(Mode::dialog))
    {
    return getSgn() * kmph2mps(const_velocity_); // km/h 转 m/s,乘以方向(前进1/后退-1)
    }
    // 情况2:其他模式 → 使用全局路径点的速度指令(final_waypoints 话题的 waypoints[0].twist.linear.x)
    return command_linear_velocity_;
    }

    角速度 angular.z 来源:曲率 kappa × 线速度

    • kappa:纯追踪算法计算的路径曲率(单位:1/m),由 pp_.canGetCurvature(&kappa) 从 PurePursuitCore 核心类获取;
    • 曲率 kappa 的计算逻辑:基于「当前车辆位姿(current_pose)」+「全局路径点(final_waypoints)」+「预瞄距离(lookahead distance)」,通过纯追踪公式计算目标点,进而推导路径曲率;
    • 预瞄距离 lookahead distance 来源:computeLookaheadDistance() 函数,根据当前车速(current_velocity)动态计算:

    double PurePursuitNode::computeLookaheadDistance() const
    {
    if (velocity_source_ == enumToInteger(Mode::dialog))
    {
    return const_lookahead_distance_; // 固定值(默认4.0m)
    }
    // 动态值:当前车速 × 比例系数(默认2.0),且有最小/最大值限制
    double maximum_lookahead_distance = current_linear_velocity_ * 10;
    double ld = current_linear_velocity_ * lookahead_distance_ratio_;
    return ld < minimum_lookahead_distance_ ? minimum_lookahead_distance_ :
    ld > maximum_lookahead_distance ? maximum_lookahead_distance : ld;
    }

    2.3.2 ctrl_raw  输出角度

    ctrl_raw 是 autoware_msgs::ControlCommandStamped 类型,包含线速度、线加速度、转向角,仅当 publishes_for_steering_robot_=true 时发布(autoware设置),数值来自 publishControlCommandStamped() 函数:

    void PurePursuitNode::publishControlCommandStamped(
    const bool& can_get_curvature, const double& kappa) const
    {
    if (!publishes_for_steering_robot_)
    {
    return;
    }

    autoware_msgs::ControlCommandStamped ccs;
    ccs.header.stamp = ros::Time::now();
    // ① 线速度(linear_velocity):和 twist_raw 的 linear.x 完全相同
    ccs.cmd.linear_velocity = can_get_curvature ? computeCommandVelocity() : 0;
    // ② 线加速度(linear_acceleration):来自 computeCommandAccel() 函数
    ccs.cmd.linear_acceleration = can_get_curvature ? computeCommandAccel() : 0;
    // ③ 转向角(steering_angle):曲率 kappa 转换为阿克曼转向角
    ccs.cmd.steering_angle =
    can_get_curvature ? convertCurvatureToSteeringAngle(wheel_base_, kappa) : 0;

    pub2_.publish(ccs);
    }

    • 线速度(linear_velocity):和 twist_raw 的 linear.x 完全相同
    • 线加速度(linear_acceleration):来自 computeCommandAccel() 函数

    通过运动学公式 v² – v₀² = 2ax 计算(当前车速→目标点车速的加速度):

    double PurePursuitNode::computeCommandAccel() const
    {
    const geometry_msgs::Pose current_pose = pp_.getCurrentPose(); // 当前位姿(current_pose话题)
    const geometry_msgs::Pose target_pose =
    pp_.getCurrentWaypoints().at(1).pose.pose; // 下一个路径点位姿(final_waypoints话题)

    // x:当前位置到下一个路径点的平面距离
    const double x =
    std::hypot(current_pose.position.x – target_pose.position.x,
    current_pose.position.y – target_pose.position.y);
    const double v0 = current_linear_velocity_; // 当前车速(current_velocity话题)
    const double v = computeCommandVelocity(); // 目标车速(同twist_raw的线速度)
    const double a = getSgn() * (v * v – v0 * v0) / (2 * x); // 加速度公式
    return a;
    }

    • 转向角(steering_angle):曲率 kappa 转换为铰接转向角(适配自己模型)

    double convertCurvatureToSteeringAngle(
    const double& wheel_base, const double& kappa)
    {
    return 2*atan(wheel_base * kappa); // wheel_base:前后轴到铰接点的距离相等(默认1.2m,从参数服务器读取)
    }

    2.4、控制效果

    gazebo复现纯追踪航迹点导航

    赞(0)
    未经允许不得转载:171主机测评 » autoware-gazebo模型航迹点纯追踪导航
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址