恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
OpenBot开源导航机器人:SLAM建图+路径规划+ROS控制全链路实现
首页
资讯中心
/
OpenBot开源导航机器人:SLAM建图+路径规划+ROS控制全链路实现
OpenBot开源导航机器人:SLAM建图+路径规划+ROS控制全链路实现
发布时间:2026/10/14 18:19:19
简介本资源是Intel实验室开源的低成本自主导航机器人OpenBot完整实现方案面向嵌入式开发、移动机器人与边缘AI初学者及实践者解决视觉导航系统从算法部署到硬件集成的一站式学习需求。压缩包共233个文件涵盖Arduino控制程序ino、安卓端APP源码java/xml与预编译APK、SSDMobileNet轻量模型tflite、3D机械结构文件stl/step、训练与标定数据csv、环境搭建说明md及实验演示素材gif/mp3/jpg整体62.83MB结构清晰便于分模块研读与复现。已有2259人学习下载读者可直接获取可运行的安卓APP、全链路代码含手机端视觉推理与Arduino底层运动控制、BOM清单、装配指南及服务器通信示例快速构建具备目标检测与路径规划能力的实体导航机器人。1. OpenBot 不是玩具车一套能跑通 SLAM路径规划ROS 控制闭环的轻量级自主导航机器人源码包你手头那台树莓派 4B 加一个 USB 摄像头真能跑出像扫地机器人那样“自己看路、自己绕障、自己去目标点”的完整导航流程OpenBot 这套 20201203 版本的全部源代码就是为这个问题交出的一份可复现、可调试、不依赖定制硬件的答案。它不是教学 Demo也不是只跑通 Gazebo 仿真的空架子——从 ROS Melodic 下的slam_gmapping实时建图到move_base的全局/局部路径规划器联动再到基于twist指令驱动差速轮底盘的底层控制逻辑整条链路全开源、全注释、全实机验证过。适合刚啃完《ROS 机器人编程》前六章、手里有块 Jetson Nano 或树莓派 4B 电机驱动板 编码器或视觉里程计替代方案的工程师也适合高校某实验室想快速搭一个低成本导航验证平台而不是花三个月调通 ROS2 的nav2插件兼容性。它不承诺“开箱即用”但承诺“每一步失败都有日志可查、每一行参数都有注释说明”。这不是自动驾驶但它是你理解自主导航机器人如何从‘看到’走向‘走到’最扎实的起点。2. 源码结构拆解五个核心模块如何协同完成一次真实建图与导航任务OpenBot 的源码不是一锅炖而是按功能边界清晰切分的五个 ROS 功能包ROS package每个包解决一个确定性问题。我第一次部署时就是靠逐个rosrun启动、观察rostopic list和rqt_graph才真正理清数据流怎么穿起来的。下面按执行顺序讲透每个包干了什么、为什么这么设计、以及你改哪几行就能适配自己的底盘。2.1openbot_bringup硬件抽象层把你的电机驱动板变成 ROS 可控的/cmd_vel这是整个系统和物理世界握手的第一道门。它不处理算法只做一件事把 ROS 的标准geometry_msgs/Twist消息翻译成你电机驱动板能听懂的 PWM 占空比或串口指令。源码里默认适配的是基于 TB6612FNG 驱动芯片的双路直流电机方案常见于某宝 99 元底盘套件核心逻辑在src/driver_node.py# openbot_bringup/src/driver_node.py import rospy from geometry_msgs.msg import Twist import RPi.GPIO as GPIO from time import sleep class MotorDriver: def __init__(self): # 初始化 GPIO 引脚IN1/IN2 控制左轮方向PWM_A 控制左轮速度 self.IN1 17; self.IN2 27; self.PWM_A 18 GPIO.setup([self.IN1, self.IN2, self.PWM_A], GPIO.OUT) self.pwm_a GPIO.PWM(self.PWM_A, 1000) # 1kHz PWM 频率 self.pwm_a.start(0) def cmd_callback(self, msg): # 将线速度 vx 和角速度 wz 映射为左右轮速 v_left/v_right v_left msg.linear.x - msg.angular.z * 0.12 # 0.12 是轮距一半单位米 v_right msg.linear.x msg.angular.z * 0.12 # 限幅避免超速导致电机堵转 v_left max(-1.0, min(1.0, v_left)) v_right max(-1.0, min(1.0, v_right)) # 转换为 PWM 占空比0~100 pwm_left int(abs(v_left) * 100) pwm_right int(abs(v_right) * 100) # 设置方向引脚 GPIO.output(self.IN1, v_left 0) GPIO.output(self.IN2, v_left 0) self.pwm_a.ChangeDutyCycle(pwm_left)关键参数说明0.12是轮距wheel base的一半单位必须是米。如果你用的是 25cm 轮距底盘这里得改成0.1251000HzPWM 频率是 TB6612FNG 推荐值低于 500Hz 会听到明显啸叫高于 2kHz 可能导致驱动芯片发热max/min限幅不是保守而是防止move_base在局部规划失败时输出极大angular.z直接烧毁电机驱动板——这是我翻车三次后加的后悔药。2.2openbot_descriptionURDF 模型定义让 ROS “知道”你的机器人长什么样没有这个包rviz里连个机器人的影子都看不到更别说做坐标变换。它包含两个核心文件urdf/openbot.urdf.xacro主模型和launch/display.launch启动 rviz 查看。xacro 文件里定义了所有刚体链接chassis、wheel_left、wheel_right、camera_link和关节continuous 类型的轮子旋转、fixed 类型的摄像头安装。重点看这段摄像头位姿定义!-- openbot_description/urdf/openbot.urdf.xacro -- joint namecamera_joint typefixed parent linkchassis/ child linkcamera_link/ origin xyz0.12 0 0.15 rpy0 0 0/ !-- 摄像头中心距底盘中心前0.12m上0.15m -- /joint link namecamera_link visual geometry box size0.04 0.04 0.06/ !-- 简化为长方体实际尺寸按你摄像头外壳填 -- /geometry /visual /link为什么xyz0.12 0 0.15很关键因为slam_gmapping建图时激光雷达或深度相机模拟的 2D 扫描数据必须通过tf变换到base_link坐标系下。如果这里写错 5cm建出来的地图就会整体偏移路径规划永远“差一点够到目标”。我建议你用卷尺实测后再用rosrun tf static_transform_publisher 0.12 0 0.15 0 0 0 chassis camera_link 100临时发布rviz里加TF显示层确认绿色坐标轴是否对准摄像头光心。2.3openbot_slam基于 gmapping 的实时建图不是“拍照存档”而是持续优化的地图这个包封装了slam_gmapping的完整 launch 流程但它真正的价值在于config/slam.yaml里的 7 个关键调参项——它们决定了你的机器人在走廊、拐角、玻璃门场景下建图是否稳定参数名默认值推荐调整场景作用原理linearUpdate1.0地面摩擦大地毯、编码器易打滑机器人直线移动超过该值米才触发一次扫描匹配防误更新angularUpdate0.5狭窄空间频繁转向转向超过该弧度才更新避免小角度抖动污染地图temporalUpdate3.0需要快速建图如应急勘察强制每 3 秒更新一次牺牲精度换速度resampleInterval1长时间运行30分钟粒子滤波重采样频率太低会导致粒子退化particles30内存受限树莓派粒子数越少越快但定位漂移越大Jetson Nano 可设为 80xmin/xmax/ymin/ymax-10/10/-10/10已知场地大小限定地图边界避免无限扩张吃光内存启动命令很简单roslaunch openbot_slam slam.launch但启动后必须立刻做三件事rostopic pub /initialpose geometry_msgs/PoseWithCovarianceStamped header: {frame_id: map} pose: {pose: {position: {x: 0.0, y: 0.0, z: 0.0}, orientation: {x: 0.0, y: 0.0, z: 0.0, w: 1.0}}}—— 给初始位姿否则amcl无法启动rostopic echo /slam_out_pose确认位姿在跳变而非发散rosrun map_server map_saver -f ~/my_map在认为地图质量达标时保存生成my_map.pgm和my_map.yaml。2.4openbot_navigationmove_base 核心配置让机器人“思考”怎么走而不是“瞎走”move_base是 ROS 导航栈的决策中枢而openbot_navigation包把它拆成了可插拔的四层Global Planner全局规划器navfn/NavfnROS用 Dijkstra 算法在静态地图上算最优路径Local Planner局部规划器dwa_local_planner/DWAPlannerROS实时计算带速度约束的短时轨迹Recovery Behaviors恢复行为clear_costmap_recovery/ClearCostmapRecoveryrotate_recovery/RotateRecovery卡住时先清障碍再原地转圈Costmap代价地图costmap_2d/Costmap2DROS融合激光、IMU、膨胀层生成动态避障依据。最关键的配置在config/costmap_common_params.yamlobstacle_range: 2.5 # 激光最大有效距离超过此值不视为障碍 raytrace_range: 3.0 # 清除障碍时的射线追踪距离必须 obstacle_range inflation_radius: 0.55 # 膨胀半径确保机器人不会擦着墙走0.55m ≈ 机器人半宽安全余量 transform_tolerance: 0.2 # tf 变换最大延迟树莓派上建议设为 0.3 防丢帧血泪经验inflation_radius设为0.3看似保守但在狭窄走廊会让机器人反复“蹭墙”触发恢复行为。我最终定为0.55配合dwa_local_planner中的min_trans_vel: 0.1最低前进速度既保证不撞墙又避免因速度过低被判定为“停滞”。2.5openbot_teleop键盘遥控节点不是摆设而是调试导航的“方向盘”别跳过这个包它用teleop_twist_keyboard改写但增加了两处硬核改进按q/e键可切换linear/angular速度档位低/中/高避免新手一上来就冲进墙里按space键发送Twist(linear.x0, angular.z0)实现“急停”这在实机测试时救了我三次电机。启动后终端会提示Reading from keyboard --------------------------- Moving around: u i o j k l m , .其中i是前进,是后退j/l是原地左/右转。注意所有按键操作都通过/cmd_vel发布和move_base完全同源——这意味着你可以先用键盘把机器人开到目标点附近再roslaunch openbot_navigation move_base.launch让它自动完成最后 2 米的精准停靠。这才是工程调试的正确姿势。3. 从零部署树莓派 4B ROS Melodic 完整环境搭建与实机验证步骤别被“ROS”吓住。OpenBot 对系统要求极低我用一张 32GB SD 卡、官方 Raspberry Pi OS Buster2020-08-20 版本从零开始3 小时内完成全部部署并跑通建图。以下步骤经我实测跳过任何“可能需要”的环节只留必要动作。3.1 系统初始化精简桌面、启用串口、配置 WiFi树莓派默认桌面环境会吃掉 300MB 内存而slam_gmapping在建图时峰值内存占用达 800MB。必须精简# 1. 禁用图形界面保留 SSH 远程访问 sudo systemctl set-default multi-user.target sudo reboot # 2. 启用硬件串口用于连接激光雷达或调试 echo enable_uart1 | sudo tee -a /boot/config.txt sudo sed -i s/consoleserial0,// /boot/cmdline.txt # 3. 配置 WiFi避免后续 ROS 节点因网络中断失联 echo -e countryCN\nctrl_interfaceDIR/var/run/wpa_supplicant GROUPnetdev\nupdate_config1 | sudo tee /etc/wpa_supplicant/wpa_supplicant.conf sudo wpa_cli -i wlan0 reconfigure提示wpa_cli reconfigure后需等待 10 秒用ping -c 3 google.com确认网络通了再继续。我曾因跳过这步在rosdep install时卡死 40 分钟。3.2 ROS Melodic 安装只装导航必需组件拒绝全量安装ROS 官方全量安装会拖入 2GB 无用包。OpenBot 只需 5 个核心功能# 添加源并更新 sudo sh -c echo deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main /etc/apt/sources.list.d/ros-latest.list sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-key C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654 sudo apt update # 只安装这 5 个元包meta-package它们会自动拉取所有依赖 sudo apt install ros-melodic-ros-base \ ros-melodic-slam-gmapping \ ros-melodic-navigation \ ros-melodic-robot-state-publisher \ ros-melodic-joint-state-publisher # 初始化 rosdep关键否则 catkin_make 会报找不到依赖 sudo rosdep init rosdep update为什么不用ros-melodic-desktop-full因为它会强制安装gazebo9、opencv-python等树莓派编译不过的包导致apt install卡在Setting up ros-melodic-gazebo-ros-pkgs。我试过七次只有上述精简列表能 100% 成功。3.3 工作空间构建catkin_ws 目录结构与编译技巧OpenBot 源码不能直接扔进/opt/ros/melodic/必须放在用户工作空间。我采用最稳妥的catkin_ws/src结构mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src # 将下载的 openbot_all_src.zip 解压到这里确保目录结构为 # ~/catkin_ws/src/openbot_bringup/ # ~/catkin_ws/src/openbot_description/ # ... 其他四个包同理 # 初始化工作空间重要必须指定 python2ROS Melodic 不支持 python3 cd ~/catkin_ws source /opt/ros/melodic/setup.bash catkin_init_workspace src catkin_make # 永久生效每次打开终端自动 source echo source ~/catkin_ws/devel/setup.bash ~/.bashrc source ~/.bashrc编译排错关键如果catkin_make报ModuleNotFoundError: No module named rospkg说明 python2 环境未激活。执行sudo apt install python-rospkg python-rosdep python-catkin-tools后重试。这是树莓派 Python 环境碎片化的经典坑。3.4 实机连线与传感器校准USB 摄像头如何当“激光雷达”用OpenBot 支持两种感知方案方案 A推荐新手USB 摄像头 depthimage_to_laserscan节点成本 ¥100方案 B进阶RPLIDAR A1建图精度更高但需额外接线。以方案 A 为例校准三步走确认摄像头识别lsusb | grep -i camera # 应看到类似 Bus 001 Device 004: ID 046d:0825 Logitech, Inc. Webcam C270 roslaunch usb_cam usb_cam-test.launch # 在另一台电脑用 rviz 查看 /usb_cam/image_raw 是否有画面生成 2D 激光扫描修改openbot_slam/launch/slam.launch取消注释这一段!-- 使用摄像头模拟激光雷达 -- node namedepthimage_to_laserscan pkgdepthimage_to_laserscan typedepthimage_to_laserscan outputscreen param nameoutput_frame_id valuecamera_link/ param namerange_min value0.45/ param namerange_max value3.0/ remap fromimage to/usb_cam/image_raw/ /node验证扫描数据roslaunch openbot_slam slam.launch rostopic hz /scan # 正常应输出 5~10 Hz rostopic echo /scan/ranges | head -n 5 # 确认数值在 0.45~3.0 范围内跳变玄学参数range_min: 0.45是摄像头最近对焦距离设太小会导致近处数据全为infrange_max: 3.0是室内建图合理上限设太大噪声激增。这两个值必须实测拿张白纸在摄像头前慢慢推远用rqt_image_view看边缘模糊点对应的距离。3.5 首次建图实操从启动到保存地图的完整命令流现在进入最激动人心的环节。请确保机器人放在开阔区域至少 3×3 米周围无反光玻璃、纯黑物体摄像头无法测距# 终端 1启动底层驱动与 TF roslaunch openbot_bringup robot.launch # 终端 2启动摄像头与激光转换 roslaunch openbot_slam camera_scan.launch # 此 launch 文件已包含 usb_cam 和 depthimage_to_laserscan # 终端 3启动 SLAM 建图此时不要动机器人 roslaunch openbot_slam slam.launch # 终端 4启动 rviz 可视化从另一台 Ubuntu 电脑 ssh 连入或用 VNC rosrun rviz rviz -d rospack find openbot_rviz/rviz/navigation.rviz在rviz中Fixed Frame设为map添加RobotModel、LaserScan、Map显示层用2D Pose Estimate工具在地图上点击设置机器人初始位置红箭头用2D Nav Goal点击目标点观察蓝色路径是否生成缓慢推动机器人走“日”字形路线非直线每走 1 米停 2 秒让slam_gmapping充分匹配当地图边缘出现明显锯齿或漂移立即CtrlC终止slam.launch然后rosrun map_server map_saver -f ~/first_map你会得到first_map.pgm图像和first_map.yaml分辨率、原点等元数据。验证地图质量用gimp first_map.pgm打开白色是自由空间黑色是障碍物灰色是未知区域。理想地图中墙壁应为连续黑色线条宽度均匀约 3~5 像素无大面积灰色“迷雾区”。4. 避坑指南五个真实翻车现场与血泪修复方案OpenBot 源码虽成熟但树莓派硬件限制、ROS Melodic 版本老化、传感器个体差异共同构成了一个“不踩坑不算入门”的实践场。以下是我在三台不同配置机器人上累计 47 小时调试中最常触发、最隐蔽、最浪费时间的五个坑按现象→原因→解决三步给出可抄作业的方案。4.1 现象slam_gmapping输出位姿剧烈抖动/slam_out_pose的x/y/z每秒跳变 ±0.3 米原因USB 摄像头帧率不稳定导致depthimage_to_laserscan生成的/scan消息时间戳乱序slam_gmapping的粒子滤波器误判运动突变。树莓派 USB 总线带宽不足是主因尤其当同时接 USB 摄像头和 USB 串口如 RPLIDAR时。解决强制摄像头固定帧率# 修改 openbot_bringup/launch/usb_cam.launch param nameframerate value10/ !-- 从默认 30 降到 10 -- param namepixel_format valueyuyv/ !-- yuyv 比 mjpeg 更省 CPU --在slam.launch中为slam_gmapping添加时间戳同步过滤node pkgslam_gmapping typeslam_gmapping nameslam_gmapping outputscreen param nameuse_sim_time valuefalse/ param namethrottle_scans value1/ !-- 只处理每 1 帧丢弃中间帧 -- remap fromscan to/scan/ /node终极方案拔掉所有非必要 USB 设备仅保留摄像头。实测帧率稳定在 9.8±0.2 Hz 后位姿抖动消失。4.2 现象move_base规划出的路径在rviz中显示正常但机器人原地打转不前进原因dwa_local_planner的min_trans_vel参数过小导致在costmap中检测到微小障碍如地面反光、阴影时计算出的可行速度区间为空触发rotate_recovery行为。解决检查当前参数rosparam get /move_base/DWAPlannerROS/min_trans_vel # 默认是 0.1对树莓派摄像头方案太小动态调大rosparam set /move_base/DWAPlannerROS/min_trans_vel 0.25 rosparam set /move_base/DWAPlannerROS/max_trans_vel 0.5永久生效修改openbot_navigation/config/base_local_planner_params.yamlmin_trans_vel: 0.25 max_trans_vel: 0.5 acc_lim_x: 0.8 # 加速度上限避免起步过猛验证方法启动move_base后rostopic echo /move_base/DWAPlannerROS/local_plan观察points数组中x坐标是否单调递增。若出现x值来回跳变说明仍在震荡需继续调高min_trans_vel。4.3 现象rviz中机器人模型RobotModel显示为“Missing”或紫色问号原因robot_state_publisher未正确加载 URDF 模型或tf树断裂。常见于openbot_description包未catkin_make成功或roslaunch openbot_bringup robot.launch未先启动。解决确认 URDF 可解析rospack find openbot_description # 应返回路径 rosrun xacro xacro rospack find openbot_description/urdf/openbot.urdf.xacro /tmp/test.urdf # 若报错检查 xacro 文件中是否有未定义的 property检查tf树完整性rosrun tf view_frames evince frames.pdf # 查看生成的 tf 关系图确认 chassis → wheel_left → camera_link 链路完整强制重载模型在robot.launch中添加node namerobot_state_publisher pkgrobot_state_publisher typerobot_state_publisher outputscreen param namepublish_frequency value50.0/ param nameuse_tf_static valuetrue/ /node4.4 现象键盘遥控openbot_teleop按i键无反应rostopic echo /cmd_vel无输出原因teleop_twist_keyboard节点默认绑定stdin而树莓派串口登录时stdin被占用导致按键事件无法捕获。解决切换到图形界面即使精简版也有startxsudo systemctl set-default graphical.target sudo reboot或改用ssh登录后启动# 在另一台电脑 ssh piraspberrypi.local roslaunch openbot_teleop teleop.launch免 GUI 方案修改openbot_teleop/src/teleop_twist_keyboard.py将sys.stdin替换为open(/dev/tty, r)并加权限sudo chmod arw /dev/tty4.5 现象建图完成后map_saver生成的my_map.pgm全黑或全白原因slam_gmapping的occ_thresh占据阈值与free_thresh自由阈值不匹配摄像头生成的scan数据分布。默认值0.25/0.19适合激光雷达但摄像头深度图噪声大需放宽。解决动态调整建图前执行rosparam set /slam_gmapping/occ_thresh 0.35 rosparam set /slam_gmapping/free_thresh 0.12永久生效修改openbot_slam/config/slam.yamlocc_thresh: 0.35 free_thresh: 0.12 # 同时调高粒子数防退化 particles: 80验证阈值建图中rostopic echo /map/data | head -n 20观察数值分布。理想状态是0未知、100占据、0自由三值分明若大量50~80的中间值说明阈值需再调。注意occ_thresh必须大于free_thresh否则map_server无法解析。差值小于0.05会导致地图模糊。5. 进阶技巧用 OpenBot 源码反向验证 ROS 导航原理三个必做实验OpenBot 最大的价值不是让你“跑起来”而是让你“看明白”——每一行代码都在回答一个经典问题“ROS 导航栈里数据到底怎么流动哪个参数改了会影响哪一层”下面三个实验我要求自己团队新人入职第一周必须完成因为它们能瞬间打通从理论到实操的认知断层。5.1 实验一可视化 costmap 的三层结构理解“机器人为什么不敢走那里”move_base的costmap_2d不是单张图而是由static_layer静态地图、obstacle_layer实时障碍、inflation_layer膨胀层叠加而成。OpenBot 的openbot_navigation/launch/move_base.launch已预留接口只需三步启动导航栈时启用所有 costmap 层roslaunch openbot_navigation move_base.launch \ visualize:true \ publish_costmap:true在rviz中添加三个Map显示层分别订阅topic:/move_base/global_costmap/costmap→ 命名为global_costmaptopic:/move_base/local_costmap/costmap→ 命名为local_costmaptopic:/move_base/local_costmap/obstacle_layer/obstacles→ 命名为obstacle_points关键操作用2D Nav Goal设置一个目标点然后缓慢将手伸向机器人前方 1 米处。观察三张图变化obstacle_points立即出现红色点云原始障碍检测local_costmap红色点云向外膨胀成黄色区域inflation_radius生效global_costmap几乎不变静态层除非你移动了地图。原理印证此时若local_costmap的黄色区域完全覆盖了规划路径dwa_local_planner就会判定“无可行路径”触发rotate_recovery。这就是为什么调inflation_radius比调obstacle_range更影响通过性——前者决定“心理安全距离”后者只决定“探测距离”。5.2 实验二篡改slam_gmapping的linearUpdate量化“运动更新”对建图精度的影响linearUpdate参数控制 SLAM 更新频率但它的真实影响远超直觉。我们用 OpenBot 源码做对照实验备份原始slam.yaml新建slam_fast.yamllinearUpdate: 0.2 # 原为 1.0改为 0.2每 20cm 更新一次 angularUpdate: 0.1 # 原为 0.5改为 0.1每 0.1 弧度更新在相同场地用同一路径用粉笔画好“口”字形跑两次建图# 第一次慢速0.2 m/s用默认参数 roslaunch openbot_slam slam.launch params_file:rospack find openbot_slam/config/slam.yaml # 第二次同速用 fast 参数 roslaunch openbot_slam slam.launch params_file:rospack find openbot_slam/config/slam_fast.yaml用gimp打开两张pgm地图叠图对比默认参数地图墙壁平直但拐角处有 10~15 像素的“圆角”欠更新导致fast参数地图墙壁锯齿明显但拐角锐利整体轮廓更接近真实过更新引入噪声。结论表格参数墙壁直线度拐角锐利度地图内存占用推荐场景linearUpdate: 1.0★★★★☆★★☆☆☆低大型空旷仓库linearUpdate: 0.5★★★★☆★★★☆☆中普通办公室linearUpdate: 0.2★★★☆☆★★★★☆高狭窄实验室走廊这就是为什么 OpenBot 文档强调“参数必须按场景调”而不是“抄别人配置”。5.3 实验三注入人工噪声理解dwa_local_planner的轨迹评估逻辑dwa_local_planner的核心是评估每条候选轨迹的score而score由path_distance_bias、goal_distance_bias、occdist_scale三个权重决定。OpenBot 的base_local_planner_params.yaml提供了修改入口但必须亲手破坏才能理解本文还有配套的精品资源点击获取