1. 这不是一本“教材”而是一张ROS2新手的生存地图你点开这个标题大概率正站在ROS2世界的门口手里攥着一台刚刷好Ubuntu 22.04的树莓派或笔记本屏幕右下角还飘着一个没关掉的ros2 run turtlesim turtlesim_node窗口——乌龟在原地打转你也在原地打转。别慌这不是你的问题。ROS2不是一门编程语言它是一套为真实机器人系统设计的、带强实时约束的操作系统级中间件。它不教你怎么写“Hello World”它逼你直面“节点怎么发现彼此”“消息怎么不丢包”“时间戳怎么对齐”“参数怎么热更新”这些工业现场天天要啃的硬骨头。我带过37个零基础学员从ROS2入门到交付AGV调度模块最常听到的抱怨不是“代码写不出来”而是“文档看得懂一跑就报错报错能搜到改完又出新错”。原因很简单ROS2的官方教程像一本《汽车维修手册》而新手真正需要的是一张标注了“哪里有坑”“哪条路绕不开”“加油站和修车铺在哪”的实操生存地图。这张地图不讲抽象概念只告诉你ros2 topic list为什么有时看不到话题rqt_graph里那个灰色节点到底死没死colcon build失败时第一眼该盯哪行日志本教程目录就是这张地图的图例——它把ROS2学习路径拆解成一条有明确里程碑、可验证、可回溯的物理动线。适合谁适合手头有硬件哪怕只是USB摄像头、想三个月内让自己的小车动起来、而不是花半年在Gazebo里调虚拟轮子参数的人。核心关键词全在这里ROS2、入门、节点通信、话题服务动作、构建系统、调试工具、实时性、DDS配置、colcon、ament。接下来每一节都是我在产线调试机械臂时用咖啡渍和键盘油写下的真实笔记。2. 整体设计逻辑为什么必须按这个顺序学跳过任何一环都会卡死2.1 拒绝“Hello World式学习”ROS2的底层逻辑决定学习路径不可逆ROS2不是Python或C那种线性知识结构。它的设计哲学是“分布式系统优先”所有功能模块都围绕“如何让分布在不同CPU、不同网络段、甚至不同操作系统的进程安全可靠地交换数据”这一核心命题展开。这意味着如果你跳过底层通信机制直接学导航栈就像没学过加减法就去解微分方程——表面能跑通demo但只要硬件稍有波动比如USB摄像头帧率抖动、Wi-Fi信号衰减整个系统就会陷入“节点失联-消息堆积-内存溢出-系统重启”的死亡循环。我亲眼见过一个高校团队在ROS2 Foxy上跑通了SLAM建图结果换到真实AGV底盘后因为没理解rmw_implementation的切换逻辑导致激光雷达数据延迟高达800ms最终撞墙。所以本目录的第一条铁律是所有学习必须从通信基石开始层层向上构建绝不允许倒置。具体来说这个顺序不是凭空拍脑袋定的第1阶段环境与构建colcon和ament不是工具它们是ROS2的“免疫系统”。colcon build过程会强制校验依赖关系、ABI兼容性、编译器标志一致性。跳过这步直接source install/setup.bash等于给系统埋下定时炸弹——某天你升级了一个依赖库整个工作空间编译失败而你根本不知道哪个包的CMakeLists.txt里写了find_package(OpenCV REQUIRED)却没声明ament_target_dependencies。第2阶段通信三件套topic/service/action不是三种“消息类型”而是三种不同的分布式协调协议。topic解决“广播通知”如传感器数据流service解决“同步请求-响应”如清空导航队列action解决“长时任务状态跟踪”如机械臂移动到指定位置。混淆它们的使用场景会导致系统响应僵硬。比如用service控制机械臂运动一旦电机堵转客户端会无限等待超时而用action你可以随时发cancel_goal并收到goal_status反馈。这个阶段必须配合ros2 topic echo /imu/data_raw -p这种带格式化输出的命令实操而不是只看ros2 topic list。第3阶段调试与诊断rqt系列工具不是GUI界面它们是分布式系统的听诊器。rqt_graph显示的是DDS发现协议Discovery Protocol的实际运行结果灰色节点意味着该节点已注册但未发布/订阅任何话题——这往往指向rclcpp::NodeOptions().automatically_declare_parameters_from_overrides(true)没启用导致参数服务器无法注入值。不理解这点你永远在“删包重编译”和“重启ros2 daemon”之间反复横跳。提示ROS2的ros2 daemon不是可有可无的服务。它缓存了节点发现信息避免每次ros2 node list都触发全网DDS发现广播。关闭它后ros2 topic list响应时间会从50ms飙升到2s以上。这是很多初学者以为“网络卡”的真实原因。2.2 工具链选型背后的硬约束为什么只推荐FoxyUbuntu 22.04Fast DDSROS2版本选择不是赶时髦。Foxy2020年发布是第一个LTS长期支持版本其核心约束是必须运行在Linux 5.4内核上且默认DDS实现为Fast DDSeProsima。这个组合解决了三个致命痛点实时性保障Ubuntu 22.04的内核启用了CONFIG_PREEMPT_RT补丁集需手动编译配合Fast DDS的BEST_EFFORT和RELIABLE传输策略能让控制指令端到端延迟稳定在20ms以内。对比之下ROS2 Humble2022年默认用Cyclone DDS其内存管理在高吞吐场景下易触发GC停顿曾导致我们某次AGV急停响应延迟超标。硬件兼容性树莓派4B的Broadcom BCM2711芯片在Ubuntu 22.04的驱动支持最完善。我测试过ROS2 Galactic在树莓派上运行rviz2GPU驱动冲突导致画面撕裂而Foxy22.04组合通过sudo apt install ros-foxy-rviz2安装后export QT_QPA_PLATFORMeglfs一行配置即可稳定渲染。生态成熟度Foxy的ros2_control框架虽不如Humble完善但其diff_drive_controller已足够驱动两轮差速小车。更重要的是90%的国产IMU、激光雷达厂商提供的ROS2驱动包首发适配版本就是Foxy。比如北科天绘的R-Fans-16雷达其rslidar_sdkROS2版仅提供Foxy和Humble分支而Foxy分支的launch.py中use_sim_time参数默认为False直接适配真实硬件Humble分支却强制要求use_sim_time:true新手极易踩坑。注意不要被“新版更强大”的宣传误导。ROS2 Rolling是滚动发布版每6个月大更新一次API不保证向后兼容。我曾帮一个客户将Rolling上的导航栈迁移到Foxy光是nav2_bringup中controller_server的参数名变更follow_path→follow_waypoints就花了两天排查。对新手而言稳定性远胜于新特性。2.3 目录结构即实战路径每个章节对应一个可交付的物理成果本目录不是知识罗列而是以交付物为锚点的项目制学习路径。每一章结束你必须能拿出一个可验证的实体成果而非“理解了概念”第1章环境搭建交付物是ros2 run demo_nodes_cpp talker和listener在两个终端中稳定收发消息且ros2 topic hz /chatter显示频率稳定在10Hz±0.5Hz。若出现No messages received说明RMW_IMPLEMENTATION环境变量未正确设置应为rmw_fastrtps_cpp。第2章话题通信交付物是自定义一个sensor_msgs/msg/Imu消息的发布者用ros2 topic echo /imu/data_raw -p能持续看到四元数、角速度、线加速度字段且ros2 topic info /imu/data_raw显示Publisher count: 1、Subscription count: 1。若Subscription count为0说明rclcpp::Node::create_subscription()调用时回调函数签名与消息类型不匹配常见错误std::shared_ptrsensor_msgs::msg::Imu写成sensor_msgs::msg::Imu::SharedPtr。第3章服务与动作交付物是用ros2 action send_goal /fibonacci action_tutorials_interfaces/action/Fibonacci {order: 5}成功触发斐波那契计算并通过ros2 action list确认/fibonacci处于active状态。此时若执行ros2 action cancel /fibonacci必须看到Goal was canceled反馈否则execute_callback中未调用goal_handle-canceled()。这种“交付物驱动”设计源于我调试工业机器人的血泪教训当客户指着产线上停摆的机械臂问“为什么不动”你不能回答“我学完了ROS2基础”而必须拿出ros2 node info /arm_controller的输出指出/arm_controller/robot_state_publisher节点因tf2坐标变换超时被kill。目录的每一环都在训练你这种“定位-验证-修复”的肌肉记忆。3. 核心模块详解与实操要点从命令行到代码的每一行都经得起拷问3.1 环境搭建colcon构建系统与ament元数据的共生关系ROS2的构建系统colcon不是简单的make包装器它是基于Python的、支持多语言C/Python/Java的元构建工具。其核心逻辑是先扫描工作空间中所有package.xml文件解析buildtool_depend如ament_cmake、depend如rclcpp等依赖声明再根据CMakeLists.txt中的ament_package()指令生成构建计划。这个过程的关键在于ament——它不是库而是ROS2的包管理规范。ament_package()宏会自动注入以下内容include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)确保头文件路径正确ament_export_dependencies(rclcpp)将rclcpp的编译标志如-I/opt/ros/foxy/include传递给当前包ament_export_include_directories(include)声明本包对外暴露的头文件路径实操中90%的colcon build失败源于ament规范违反。典型案例如下案例1C包中混用Python依赖!-- package.xml -- dependpython3-numpy/depend dependrclcpp/depend# CMakeLists.txt find_package(ament_cmake REQUIRED) find_package(rclcpp REQUIRED) find_package(NumPy REQUIRED) # 错误NumPy是Python库C无法链接 ament_package()修复方案将NumPy逻辑移至Python节点或用pybind11封装。C层只处理ROS2通信数据计算交给Python子进程。案例2Python包未声明ament_python构建工具!-- package.xml -- buildtool_dependament_python/buildtool_depend exec_dependament_python/exec_depend dependrosidl_default_generators/depend# setup.py from setuptools import setup setup( namemy_py_pkg, # 缺少entry_points声明导致ros2 run找不到节点 )修复方案在setup.py中添加entry_points{ console_scripts: [ talker my_py_pkg.talker:main, ], },实操心得colcon build --symlink-install是新手救命命令。它用符号链接替代文件复制修改Python脚本后无需重新build直接ros2 run即可生效。但注意C代码修改后仍需build因为编译产物.so文件必须重建。3.2 话题通信QoS策略的七种组合与真实场景映射ROS2话题通信的可靠性不取决于“是否联网”而取决于QoSQuality of Service策略的精确匹配。rclcpp::QoS对象包含7个可调参数但新手只需掌握3个核心参数可选值典型场景错误配置后果historyKEEP_LAST(10)/KEEP_ALL传感器数据流KEEP_LAST防内存溢出KEEP_ALL在高帧率摄像头下导致OOMreliabilityRELIABLE/BEST_EFFORT控制指令RELIABLE保送达BEST_EFFORT在Wi-Fi弱信号下丢控制包durabilityTRANSIENT_LOCAL/VOLATILE静态地图TRANSIENT_LOCAL让新订阅者立即获取VOLATILE导致新RVIZ实例看不到已有地图实操中talker和listener的QoS必须完全一致才能建立连接。验证方法# 查看talker的QoS配置 ros2 topic info /chatter --verbose # 输出中需包含 # * QoS profile: # * Reliability: RELIABLE # * Durability: VOLATILE # * History: KEEP_LAST # * Depth: 10若listener的QoS与之不匹配如Durability设为TRANSIENT_LOCALros2 topic list仍能看到/chatter但ros2 topic echo收不到消息——因为DDS发现协议拒绝建立不匹配的通信链路。关键技巧用rqt_plot可视化QoS效果。启动ros2 run demo_nodes_cpp talker后在rqt_plot中输入/chatter/data调整talker的QoS// 修改talker.cpp rclcpp::QoS qos(rclcpp::KeepLast(10)); qos.reliability(RMW_QOS_POLICY_RELIABILITY_BEST_EFFORT); // 切换策略观察曲线RELIABLE下数据流连续BEST_EFFORT下在模拟网络丢包tc qdisc add dev lo root netem loss 20%时出现明显断点。3.3 服务与动作状态机模型与生命周期钩子的硬编码实践service和action的本质区别在于状态机复杂度。service是简单的“请求-响应”二态机action则是包含PENDING→ACTIVE→SUCCEEDED/ABORTED/CANCELED五态的完整状态机。action的execute_callback必须显式管理状态否则客户端永远卡在PENDING。以Fibonacci动作为例其execute_callback必须包含// fibonacci_action_server.cpp auto goal_handle std::dynamic_pointer_castFibonacci::GoalHandle(goal_handle_); // 1. 检查取消请求 if (goal_handle-is_canceling()) { result-sequence {}; // 返回空结果 goal_handle-canceled(result); return; } // 2. 执行计算此处省略算法 // 3. 发送周期性反馈 auto feedback std::make_sharedFibonacci::Feedback(); feedback-sequence current_sequence; goal_handle-publish_feedback(feedback); // 4. 完成目标 result-sequence final_sequence; goal_handle-succeed(result);致命陷阱若忘记调用goal_handle-publish_feedback()客户端ros2 action send_goal会一直显示Goal pending...因为action_client默认等待反馈超时30秒。解决方案是在execute_callback开头添加RCLCPP_INFO(this-get_logger(), Executing goal with order %d, goal-order);并通过ros2 action list确认/fibonacci状态变为active证明服务端已进入执行流程。注意action的cancel_callback是独立钩子必须单独注册this-register_cancel_callback( std::bind(FibonacciActionServer::handle_cancel, this, _1));handle_cancel中只需返回rclcpp_action::CancelResponse::ACCEPT真正的清理逻辑如停止电机放在execute_callback的is_canceling()分支内。3.4 调试工具链rqt家族的隐藏参数与离线诊断能力rqt工具不是图形界面而是ROS2诊断协议的可视化前端。其核心价值在于离线分析——当机器人在野外断网时你仍能通过ros2 bag play回放数据用rqt复现故障。rqt_graph的深度用法默认视图只显示节点和话题。点击右上角Refresh旁的齿轮图标勾选Show all topics显示未连接的话题、Hide dead nodes隐藏已退出的节点。若某个节点显示为灰色右键→Node Info查看Node namespace是否与launch文件中node_namespace一致。常见错误launch中node_namespacerobot1但代码中this-get_namespace()返回/导致话题实际发布在/robot1/chatter而非/chatter。rqt_console的过滤技巧ROS2日志默认等级为INFO。当调试rclcpp::Node::create_subscription()失败时将日志等级临时调至DEBUGros2 run demo_nodes_cpp listener --ros-args --log-level debug在rqt_console中右键日志行→Filter by logger name输入rclcpp即可聚焦到节点初始化日志快速定位Failed to create subscription的具体原因如Type support not available for type std_msgs/msg/String实为rosidl_typesupport_cpp未正确链接。rqt_bag的离线分析录制数据时务必开启--compression zstdZstandard压缩ros2 bag record -a --compression zstd --compression-mode file -o my_sessionZstandard比默认的lz4压缩率高40%且解压速度更快。回放时rqt_bag的时间轴可拖拽到任意毫秒级时间点点击Play按钮旁的Step Forward逐帧检查/tf变换是否突变——这是定位机械臂关节抖动根源的黄金方法。4. 实操全流程从零创建一个可移动的ROS2小车控制节点4.1 硬件准备与驱动验证让物理世界的数据流进ROS2本实操以常见四轮麦轮小车如TurtleBot3 Waffle Pi为例但方法论适用于任何带串口/USB接口的底盘。关键步骤不是“接上线”而是验证数据流的端到端完整性。第一步确认串口权限ls -l /dev/ttyACM0 # 正确输出crw-rw---- 1 root dialout 166, 0 Jan 1 12:00 /dev/ttyACM0 # 若显示root:dialout需将用户加入dialout组 sudo usermod -a -G dialout $USER # 重启终端生效第二步用ros2 run验证基础驱动# 启动底盘驱动假设使用hls_lfcd_lds_driver ros2 run hls_lfcd_lds_driver hlds_laser_publisher # 在另一终端执行 ros2 topic list | grep scan # 应看到 /scan ros2 topic hz /scan # 正常值10HzLDS-20B雷达第三步用ros2 topic echo验证数据质量ros2 topic echo /scan --no-arr # 关键检查点 # - header.stamp.sec 和 header.stamp.nanosec 是否随时间递增验证时钟同步 # - angle_min/angle_max 是否为-3.14/3.14验证角度范围 # - ranges数组长度是否为360验证分辨率 # 若ranges中大量出现inf说明雷达前方无障碍物若全为0.0说明驱动未正确读取串口数据。实操心得用stty -F /dev/ttyACM0检查串口参数。ROS2驱动通常要求115200 8N1波特率1152008数据位无校验1停止位。若stty输出cs8 -parenb -cstopb则参数正确若为cs7 -parenb -cstopb说明数据位是7需修改驱动源码中的serial_port.setBaudrate(115200)并重新编译。4.2 创建自定义控制节点C版cmd_vel订阅器小车移动的核心是订阅geometry_msgs/msg/Twist消息到/cmd_vel话题。我们创建一个最小可行节点不依赖ros2_control框架直击本质。创建包cd ~/ros2_ws/src ros2 pkg create --build-type ament_cmake robot_control --dependencies rclcpp geometry_msgs编写节点代码src/robot_control/src/cmd_vel_subscriber.cpp#include rclcpp/rclcpp.hpp #include geometry_msgs/msg/twist.hpp #include iostream class CmdVelSubscriber : public rclcpp::Node { public: CmdVelSubscriber() : Node(cmd_vel_subscriber) { // 关键QoS必须与发布者匹配这里用默认QoSRELIABLEVOLATILE subscription_ this-create_subscriptiongeometry_msgs::msg::Twist( /cmd_vel, 10, // queue size std::bind(CmdVelSubscriber::topic_callback, this, std::placeholders::_1)); RCLCPP_INFO(this-get_logger(), CmdVelSubscriber node started); } private: void topic_callback(const geometry_msgs::msg::Twist::SharedPtr msg) const { // 将ROS2 Twist转换为底盘实际控制指令 // 此处简化打印线速度和角速度 RCLCPP_INFO(this-get_logger(), Linear.x: %.2f, Angular.z: %.2f, msg-linear.x, msg-angular.z); // 真实硬件在此处调用串口发送函数 // send_to_chassis(msg-linear.x, msg-angular.z); } rclcpp::Subscriptiongeometry_msgs::msg::Twist::SharedPtr subscription_; }; int main(int argc, char * argv[]) { rclcpp::init(argc, argv); rclcpp::spin(std::make_sharedCmdVelSubscriber()); rclcpp::shutdown(); return 0; }配置CMakeLists.txt# 在add_executable后添加 ament_target_dependencies(cmd_vel_subscriber rclcpp geometry_msgs ) # 必须添加install规则否则ros2 run找不到 install(TARGETS cmd_vel_subscriber ARCHIVE DESTINATION lib/${PROJECT_NAME} LIBRARY DESTINATION lib/${PROJECT_NAME} RUNTIME DESTINATION lib/${PROJECT_NAME})构建与运行cd ~/ros2_ws colcon build --packages-select robot_control source install/setup.bash ros2 run robot_control cmd_vel_subscriber # 在另一终端发布测试消息 ros2 topic pub /cmd_vel geometry_msgs/msg/Twist {linear: {x: 0.2}, angular: {z: 0.5}}验证成功标志cmd_vel_subscriber终端持续输出Linear.x: 0.20, Angular.z: 0.50且无Failed to create subscription错误。若出现Could not determine the type for the passed message说明geometry_msgs依赖未正确声明。4.3 集成TF坐标变换让小车知道自己在哪/tf是ROS2的“空间感知神经系统”。没有它rviz2无法显示小车模型导航栈无法规划路径。本节创建一个静态tf广播器发布base_link到laser的固定变换。创建TF广播器节点src/robot_control/src/static_tf_broadcaster.cpp#include rclcpp/rclcpp.hpp #include tf2_ros/static_transform_broadcaster.h #include geometry_msgs/msg/transform_stamped.hpp class StaticTfBroadcaster : public rclcpp::Node { public: StaticTfBroadcaster() : Node(static_tf_broadcaster) { tf_static_broadcaster_ std::make_sharedtf2_ros::StaticTransformBroadcaster(this); // 构建从base_link到laser的变换 geometry_msgs::msg::TransformStamped t; t.header.stamp this-get_clock()-now(); t.header.frame_id base_link; t.child_frame_id laser; t.transform.translation.x 0.1; // 激光雷达在底盘前方10cm t.transform.translation.y 0.0; t.transform.translation.z 0.2; // 高度20cm t.transform.rotation.x 0.0; t.transform.rotation.y 0.0; t.transform.rotation.z 0.0; t.transform.rotation.w 1.0; tf_static_broadcaster_-sendTransform(t); RCLCPP_INFO(this-get_logger(), Static TF published: base_link - laser); } private: std::shared_ptrtf2_ros::StaticTransformBroadcaster tf_static_broadcaster_; }; int main(int argc, char * argv[]) { rclcpp::init(argc, argv); rclcpp::spin(std::make_sharedStaticTfBroadcaster()); rclcpp::shutdown(); return 0; }修改CMakeLists.txt添加新可执行文件add_executable(static_tf_broadcaster src/static_tf_broadcaster.cpp) ament_target_dependencies(static_tf_broadcaster rclcpp tf2_ros geometry_msgs ) install(TARGETS static_tf_broadcaster ARCHIVE DESTINATION lib/${PROJECT_NAME} LIBRARY DESTINATION lib/${PROJECT_NAME} RUNTIME DESTINATION lib/${PROJECT_NAME})验证TF树# 启动TF广播器 ros2 run robot_control static_tf_broadcaster # 查看TF树 ros2 run tf2_tools view_frames # 生成frames.pdf需安装graphviz evince frames.pdf # 应看到base_link → laser的箭头 # 实时监听变换 ros2 run tf2_ros tf2_echo base_link laser # 输出应显示translation: x: 0.100, y: 0.000, z: 0.200关键经验tf2_echo的输出频率即为变换发布频率。若显示Failure: TF frame [laser] does not exist说明static_tf_broadcaster未运行或frame_id拼写错误如base_link写成base_link_。用ros2 node list确认节点存在再用ros2 node info /static_tf_broadcaster检查其发布的/tf_static话题。4.4 构建完整Launch文件一键启动小车全栈单个节点调试通过后必须用launch文件整合。ROS2的launch不是Shell脚本而是基于Python的声明式启动描述支持条件启动、参数注入、节点重映射。创建launch文件src/robot_control/launch/robot_launch.pyfrom launch import LaunchDescription from launch.actions import DeclareLaunchArgument, IncludeLaunchDescription, ExecuteProcess from launch.conditions import IfCondition, UnlessCondition from launch.launch_description_sources import PythonLaunchDescriptionSource from launch.substitutions import Command, LaunchConfiguration, PathJoinSubstitution from launch_ros.actions import Node from launch_ros.substitutions import FindPackageShare def generate_launch_description(): # 声明启动参数 use_sim_time LaunchConfiguration(use_sim_time) declare_use_sim_time_cmd DeclareLaunchArgument( use_sim_time, default_valuefalse, descriptionUse simulation (Gazebo) clock if true) # 启动底盘驱动假设已安装hls_lfcd_lds_driver lidar_launch IncludeLaunchDescription( PythonLaunchDescriptionSource([ PathJoinSubstitution([ FindPackageShare(hls_lfcd_lds_driver), launch, hlds_laser.launch.py ]) ]), launch_arguments{use_sim_time: use_sim_time}.items() ) # 启动自定义节点 cmd_vel_node Node( packagerobot_control, executablecmd_vel_subscriber, namecmd_vel_subscriber, outputscreen, parameters[{use_sim_time: use_sim_time}] ) static_tf_node Node( packagerobot_control, executablestatic_tf_broadcaster, namestatic_tf_broadcaster, outputscreen ) # 启动RVIZ2可选 rviz_config_file PathJoinSubstitution([ FindPackageShare(robot_control), rviz, robot.rviz ]) rviz_node Node( packagerviz2, executablerviz2, namerviz2, outputscreen, arguments[-d, rviz_config_file], parameters[{use_sim_time: use_sim_time}], conditionUnlessCondition(use_sim_time) # 仅在真实硬件时启动 ) ld LaunchDescription() ld.add_action(declare_use_sim_time_cmd) ld.add_action(lidar_launch) ld.add_action(cmd_vel_node) ld.add_action(static_tf_node) ld.add_action(rviz_node) return ld创建RVIZ配置文件src/robot_control/rviz/robot.rvizPanels: - Class: rviz_common/Displays Help Height: 78 Name: Displays Property Tree Widget: Expanded: - /Global Options1 - /Status1 - /By Topic1 Splitter Ratio: 0.5 Tree Height: 435 Value: true - Class: rviz_common/Selection Name: Selection Value: true - Class: rviz_common/Tool Properties Name: Tool Properties Value: true - Class: rviz_common/Views Name: Views Value: true Visualization Manager: Class: Displays: - Class: rviz_common/Global Options Name: Global Options Value: true - Class: rviz_common/Status Name: Status Value: true - Class: rviz_common/TF Enabled: true Name: TF Value: true - Class: rviz_common/Grid Enabled: true Name: Grid Value: true - Class: rviz_common/RobotModel Enabled: true Name: RobotModel Value: true - Class: rviz_common/Map Enabled: true Name: Map Value: true - Class: rviz_common/PointCloud2 Enabled: true Name: PointCloud2 Value: true Tools: - Class: rviz_common/Interact Hide Inactive: false Name: Interact Value: true - Class: rviz_common/MoveCamera Name: MoveCamera Value: true - Class: rviz_common/Select Name: Select Value: true Value: true Views: Current: Class: rviz_common/Orbit Distance: 5 Enable Stereo Rendering: false Focal Point: [0, 0, 0] Name: Current View Near Clip Distance: 0.01 Pitch: 0.3490658503988659 Target Frame: Fixed Frame Value: Orbit (rviz_common) Yaw: 0.7853981633974483 Saved: ~ Window Geometry: Displays: -577 422 422 422 Height: 1050 Hide Left Dock: false Hide Right Dock: false QMainWindow State: 000000ff00000000fd000000040000000000000100000002fc0200000000000100000002fc0200000000000100000002fc0200000000000100000002fc0200000000000100000002fc0200000000000100000002fc0200000000000100000002fc02000000000001000000