You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ROS中roslaunch启动节点报process has died但rosrun运行正常

问题根因

两个核心问题导致roslaunch启动节点时触发进程退出,rosrun单独启动可正常运行——本质是rosrun启动时通常会等所有依赖节点、话题、参数全部就绪再运行自定义节点,而roslaunch默认并行启动所有节点,叠加代码本身的执行顺序缺陷:

  • 参数获取顺序错误
    代码中调用rospy.get_param("~map_file")的位置在rospy.init_node('position_tracker')之前。roslaunch中在<node>标签下配置的<param>属于节点私有命名空间参数,必须等节点初始化完成、私有命名空间注册到ROS master之后才能正常读取,提前调用会直接抛出ParamNotFound异常导致进程退出。使用rosrun启动时,一般是提前启动了其他节点加载了全局同名参数,或是手动传入了参数,不会触发该报错。
  • odom话题频率获取逻辑无容错,和启动时序不匹配
    代码仅写死1秒的rospy.sleep(1)等待odom话题发布,但roslaunch并行启动gazebo仿真、turtlebot3驱动节点时,1秒内/odom话题大概率还没开始输出消息,此时r.get_hz('/odom')会返回None,直接对None做下标取[0]会抛出TypeError: 'NoneType' object is not subscriptable导致进程退出。用rosrun启动时,通常是等仿真、驱动完全运行、/odom正常输出之后才启动自定义节点,此时get_hz可以正常拿到频率值,不会触发报错。
修复方案

1. 调整代码执行顺序,增加必要容错

修改核心代码段如下:

if __name__=="__main__":
    global odom_hz
    # 必须先初始化节点,再读取私有参数
    rospy.init_node('position_tracker')
    map_file = rospy.get_param("~map_file")
    odom_topic_name = "odom"
    pub_point = rospy.Publisher('realpoints_marker', MarkerArray, queue_size=1)

    tf_sub=tf.TransformListener()
    # 主动等待odom话题出现,替代硬编码等待时长
    rospy.loginfo("Waiting for odom topic...")
    rospy.wait_for_message("/odom", Odometry, timeout=10)
    r = rostopic.ROSTopicHz(-1)
    s=rospy.Subscriber('/' + odom_topic_name, Odometry, r.callback_hz, callback_args='/odom')
    # 循环等待频率统计结果,避免空值报错
    odom_hz = None
    rate = rospy.Rate(10)
    while not rospy.is_shutdown() and odom_hz is None:
        hz_res = r.get_hz('/' + odom_topic_name)
        if hz_res is not None:
            odom_hz = int(hz_res[0])
            break
        rospy.loginfo("Waiting for odom frequency stat...")
        rate.sleep()
    s.unregister()
    if odom_hz is None:
        rospy.logerr("Cannot get odom topic frequency, exit")
        exit(1)
    rospy.Subscriber("/odom",Odometry, callback)
    rospy.spin()

2. (可选)优化launch文件启动逻辑

调整节点启动顺序,给自定义节点加适当延迟,同时开启屏幕日志输出方便调试:

<launch>
    <!-- 优先启动仿真、驱动、键盘控制节点 -->
    <include file="$(find turtlebot3_gazebo)/launch/turtlebot3_world.launch" />
    <include file="$(find turtlebot3_bringup)/launch/turtlebot3_model.launch"/>
    <node pkg="teleoperat1" type="key_to_twist.py" name="keys_to_twist" output="screen"/>
    <node pkg="teleoperat1" type="keyboard_drive.py" name="keyboard_driver" output="screen"/>
    <!-- 最后启动自定义定位节点,加3秒延迟等待所有依赖话题就绪 -->
    <node pkg="just_for_learning"  type="pointstamp.py" name="position_tracker" output="screen" launch-prefix="bash -c 'sleep 3; $0 $@'">
            <param name="map_file" value="$(find robot_laser_grid_mapping)/maps/map.yaml" />
    </node>
</launch>

调试节点时给对应<node>标签加output="screen"属性,可以直接在终端看到节点的报错日志,不用翻ROS日志文件,排查效率高很多。

内容的提问来源于stack exchange,提问作者peyman movlani

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 21:06:34