新闻详情

新闻详情

首页 / 资讯中心 / 详情

ROS2+FrankaPanda机械臂颜色分拣实战:从视觉识别到MoveIt2抓取闭环

发布时间:2026/9/25 8:17:44来源:尧图网络
ROS2+FrankaPanda机械臂颜色分拣实战:从视觉识别到MoveIt2抓取闭环
简介基于ROS2的FrankaPanda颜色分拣机器人项目面向机器人、人工智能方向的毕业设计、课程设计或进阶学习者完整演示了从摄像头实时采集图像、颜色识别定位到机械臂抓取分拣的自动化闭环流程。压缩包共112个文件大小约5.78MB内容覆盖Python核心代码视觉识别与控制、URDF/Xacro/DAE/STL等机器人模型与物理描述、YAML/XML/Config等多类配置、MoveIt运动规划参数、Dockerfile容器化环境以及README操作手册Python脚本负责视觉识别与运动控制模型文件用于仿真和可视化各文件按功能分模块存放便于对照复现。目前已有60人学习下载适合按文档从零搭建环境也适合有ROS2基础的开发者研究pymoveit2接口、panda_moveit规划逻辑与任务调度方法。项目整合了颜色识别、运动控制、容器化部署等关键环节通过实际工程代码展示分拣系统的完整构成可作为课程设计、工程实践或二次开发的直接基础材料。1. 拿到这个 ROS2 的 FrankaPanda 颜色分拣包先确认它解决什么问题如果你刚消化完 ros2 菜鸟教程里的小乌龟还没见过一个完整的“感知—决策—执行”闭环那这个包就是典型该拆的 ros2 项目实例。它把颜色检测、坐标变换、MoveIt2 规划、夹爪动作四件事串在同一条链路上摄像头拍到彩色工件识别出颜色和位置FrankaPanda 机械臂按颜色把它送到对应料盒。拆完它你基本就摸清了 ros2 里话题、服务、动作各自该在什么时候用也理解了仿真和真机的差距在哪。这包适合两类人。一类是学完 ros2 基础、想找一个完整项目练手的开发者它能帮你把零散 API 拼成整机另一类是实验室或小产线里要做协作机器人分拣原型、需要快速交方案的工程师。后文我会按“环境与驱动 → 颜色识别 → 执行与控制 → 排错 → 进阶调试”的顺序展开每一步都能直接照做。2. 先把环境和驱动对齐ROS2 版本、libfranka、MoveIt2 三处匹配好颜色分拣这个任务真正卡进度的往往不是识别算法而是驱动链路是否通。解压 zip 之前先把宿主机的版本矩阵理清楚能省掉后面一大半玄学故障。2.1 版本矩阵为什么选 Humble以及 libfranka 与 franka_ros2 的搭配做 FrankaPanda 分拣我一般建议 Ubuntu 22.04 ROS2 Humble。原因不是 Humble 版本号更新而是 franka_ros2 和 MoveIt2 在 Humble 这条线维护最勤你搜 ros2 安装教程、ros2 humble 避坑帖时命中也最高。Foxy 虽然也能跑但不少依赖包已经停止向它同步装到一半被依赖解析卡住的概率明显更高。版本匹配有一条容易忽略的链条机器人控制器里的固件版本决定 libfranka 能用的版本libfranka 又约束 franka_ros2 的编译版本。三者里最核心的是 libfranka。如果你手上的 Panda 控制柜固件比较老强行装新版 libfranka 会导致连接失败。组件推荐配置注意点操作系统Ubuntu 22.04 LTS别急着上 24.04部分驱动和 MoveIt2 二进制还没完全跟上ROS2 发行版Humble与 22.04 绑定最长维护期libfranka0.9 系列以控制柜固件为准版本不匹配表现为连接时握手超时franka_ros2与 libfranka 同源编译二进制包缺了就源码编译MoveIt2ros-humble-moveit用 Ubuntu 源里的二进制即可不建议源码编译这里有个技术背景值得说明ROS2 与 ROS1 最大的区别是把底层通信换成了 DDS节点之间的发现、订阅、服务质量策略全部走 DDS 协议。对分拣这类实时性要求高的任务DDS 带来的好处是话题频率和延迟可控节点崩溃后也能自动重连。代价是你必须花时间理解 QoS 匹配规则否则会出现“两个节点都活着但话题就是互相收不到”的怪现象。这一点后面第 5 章会具体展开。2.2 真机连接与仿真准备两条路径的启动命令环境装好后第一件事不是写颜色识别而是确认机械臂驱动节点能起来。真机连接的关键参数是机器人控制柜的 IP一般写在控制柜铭牌或配置文件里。启动命令通常长这样# 安装 ROS2 桌面版与 MoveIt2 sudo apt update sudo apt install -y ros-humble-desktop ros-humble-moveit # 创建工作空间并编译 franka_ros2 源码 mkdir -p ~/ros2_ws/src cd ~/ros2_ws colcon build --symlink-install source install/setup.bash # 连接真机robot_ip 换成你的控制柜地址 ros2 launch franka_ros2 franka.launch.py robot_ip:172.16.0.1 robot_name:panda第一段 apt 命令注意分清ros-humble-desktop和ros-humble-desktop-full的区别前者只带核心工具后者多了仿真和可视化插件。做颜色分拣建议直接装 full省得后面补依赖。第二段colcon build --symlink-install里的 symlink 模式让你改 python 节点代码后不用重新编译这对频繁调视觉参数非常关键。最后一段启动后驱动节点会以大约 1kHz 的频率发布关节状态同时开启机器人控制器的运动使能。没有真机的人也别卡在这。常见做法是先用仿真把分拣流程跑通用 gazebo 自带 Panda 模型加载机械臂和彩色方块视觉、规划、抓取逻辑全在仿真里验证最后再切真机只做手眼标定和参数微调。仿真启动命令与真机类似只是把 robot_ip 换成仿真配置。需要注意的是仿真里测出的夹爪力度、加减速参数不能直接搬到真机仿真模型的摩擦系数和电机力矩都是理想化的。2.3 用 rviz2 验证关节状态与 TF 树驱动起来后开 rviz2 检查三样东西机器人模型是否显示、TF 树是否完整、关节状态话题是否在刷新。# 终端一查看关节角度输出正常会每秒几十到几百条 ros2 topic echo /joint_states --field position # 终端二查看坐标变换树是否有从 base_link 到 tool0 的完整链路 ros2 run rviz2 rviz2在 rviz2 里添加 RobotModel 显示项再把 Fixed Frame 设为 base_link如果能看到机械臂模型完整展开说明描述文件加载正确。接着添加 TF 显示项检查 base_link、link0 到 link8、hand 等一系列坐标系是否连续。常见问题有两个一是 Fixed Frame 设错导致模型漂移二是缺 joint_states 话题导致模型保持初始姿态不动。颜色分拣后面所有像素坐标都要变换到机械臂基坐标系这一步没验证透后面抓取位置一定偏。3. 颜色识别的视觉链路用 HSV 阈值把像素坐标变成分拣目标视觉环节的目标很单一从相机图像里找到颜色块给出它相对机器人基座的空间位姿。实现上拆成三步——相机安装与标定、颜色提取、坐标变换。每一步都有独立的坑。3.1 相机安装与手眼标定顶装和眼在手上的选择常见做法是固定顶装也就是相机固定在天花板或支架上向下看分拣平面。这种方案标定一次就能长期用分拣范围固定像素坐标到机器人坐标的映射也是固定关系适合大多数实验室分拣台。另一种是眼在手上相机装在机械臂末端跟随机械臂移动灵活但每次换标定后都要重复校验通常留给抓取范围大或物体堆叠的场景。手眼标定这块固定顶装需要的是一次相机外参标定。用一个打印的棋盘格或者 Charuco 板放在机器人工作平面记录棋盘格角点的像素坐标和它在机器人基座坐标系下的实际位置然后用 OpenCV 的 solvePnP 解出相机到机器人基座的外参矩阵。已经有 ROS2 标定包能半自动完成这个过程但要注意它输出的坐标系方向是否符合你机器人基座的定义经常有人在这里把 X 轴和 Y 轴搞反导致抓取时左右镜像。3.2 用 OpenCV 写一个颜色检测节点HSV 阈值与轮廓提取颜色检测最直接的做法是把 BGR 图像转成 HSV 再设阈值。理由很简单BGR 受光照亮度影响大同一物体在亮处和暗处会呈现截然不同的通道值HSV 把色调与亮度分开只要灯的色温不变物体的 H 通道基本稳定。下面是一个最小可用的颜色检测节点它对相机话题做订阅、输出掩膜和检测结果import cv2 import numpy as np import rclpy from rclpy.node import Node from sensor_msgs.msg import Image from cv_bridge import CvBridge class ColorDetector(Node): def __init__(self): super().__init__(color_detector) self.bridge CvBridge() # 订阅相机图像话题 self.sub self.create_subscription( Image, /camera/color/image_raw, self.detect, 10) # 发布可视化掩膜供 rviz2 调试 self.mask_pub self.create_publisher(Image, /debug/color_mask, 10) # HSV 阈值参数下界和上界 # 这里以红色为例橙色-红色区间常用 H 0~15 self.lower np.array([0, 80, 80]) self.upper np.array([15, 255, 255]) # 形态学开运算的核大小过滤噪点 self.kernel np.ones((5, 5), np.uint8) def detect(self, msg): frame self.bridge.imgmsg_to_cv2(msg, bgr8) hsv cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) mask cv2.inRange(hsv, self.lower, self.upper) mask cv2.morphologyEx(mask, cv2.MORPH_OPEN, self.kernel) self.mask_pub.publish(self.bridge.cv2_to_imgmsg(mask, mono8)) # 找轮廓并取最大块过滤面积过小的误检 contours, _ cv2.findContours( mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) if not contours: return c max(contours, keycv2.contourArea) if cv2.contourArea(c) 300: return # minAreaRect 输出 (中心点, 长宽, 旋转角) rect cv2.minAreaRect(c) center_px rect[0] angle rect[2] self.get_logger().info( fdetected center_px({center_px[0]:.1f},{center_px[1]:.1f}) fangle{angle:.1f})逻辑说明inRange对 HSV 三个通道做区间筛选得到二值掩膜MORPH_OPEN是先腐蚀后膨胀用来去掉细小的反光噪点核大小 5×5 在 1080p 图像上属于适中值核太大会吃掉小块目标太小则噪声滤不干净。findContours找连通域按面积取最大的一个面积阈值 300 是按你的相机分辨率调的如果相机离工作台近这个阈值要相应调大。minAreaRect返回带角度的最小外接矩形中心点用于抓取角度用于后续调整夹爪朝向。HSV 阈值范围表是颜色分拣的核心参数常见做法是先给一组初值再对着实物图像微调颜色H 范围S 范围V 范围备注红色0~1580~25580~255红色在 HSV 里跨 0 和 180 两端通常取 0~15 加 165~180 两组绿色35~8580~25560~255受阴影影响大V 下限要放低蓝色90~13080~25560~255与绿色区分度大最不容易误检调整方法是在 rviz2 里同时打开原始图像和掩膜图像边滑 HSV 参数边观察直到目标物体被完整选中、背景噪点消失。这个滑参过程是典型的“调参靠手评判靠眼”所以我才强调用--symlink-install编译省得每改一次参数就重新构建。3.3 像素坐标到机器人坐标相机模型与 TF 发布检测节点输出的 center_px 是像素坐标机器人抓取需要的是 base_link 坐标系下的三维坐标。中间隔了一道相机外参换算。假设相机标定给出的内参是 fx、fy、cx、cy相机到机器人基座的外参矩阵是 T_cam_to_base那么像素点到机械臂基座坐标系的换算如下def pixel_to_base(u, v, depth, T_cam_to_base, fx615.0, fy615.0, cx320.0, cy240.0): 把像素坐标 (u, v) 和深度/高度值转换成机器人基坐标系坐标。 对固定顶装平面分拣depth 通常取工件的实际高度。 x_cam (u - cx) * depth / fx y_cam (v - cy) * depth / fy z_cam depth p_cam np.array([x_cam, y_cam, z_cam, 1.0]) p_base T_cam_to_base p_cam return p_base[:3]这里把物体当成一个固定高度 z 的平面上的点是平面分拣最常见的近似。除非物体有堆叠否则不需要深度相机。式子里 fx、fy 来自标定cx、cy 是图像主点通常接近分辨率的一半。T_cam_to_base 是 4×4 齐次矩阵由标定得到你可以把它存成 YAML 文件节点启动时读取。这里要特别提醒T_cam_to_base 不同于 TF 树里的静态变换它描述的是像素坐标系到机器人基座的空间关系可以直接发布成静态 TF也可以只保存在节点内部。实际项目我更推荐发布成静态 TF这样 rviz2 里能直观看到相机看到的点和机器人看到的点是否重合。坐标变换做完后视觉链路的输出就是一个带颜色的目标位姿通常是 position(x,y,z) 加上 yaw 角。这个输出会发布成 ROS2 话题或通过服务调用交给抓取节点。4. 分拣执行链路MoveIt2 规划、夹爪动作与状态机的串法视觉给了目标机械臂怎么过去、抓起来、放到哪是执行链路的事。执行链路的核心是 MoveIt2 的规划接口和机器人的夹爪控制接口两者要按状态机节奏协调。4.1 MoveIt2 规划组配置arm 与 hand 的划分FrankaPanda 有 7 个关节末端是两指夹爪。MoveIt2 里要建两个规划组panda_arm包含 7 个关节用于手臂运动规划panda_hand包含两个手指的关节用于夹爪开合。实际抓取时大部分规划只针对panda_arm夹爪用独立接口开合即可这样能避免 MoveIt 把手指也纳入轨迹规划导致规划时间变长。Kinematics 求解器一般用默认的 KDL。如果发现规划频繁失败可以把求解器换成 TRAC-IK这个替代方案在 YouBot 类机械臂和 Panda 上都有现成配置。TRAC-IK 对奇异位姿更宽容规划成功率会高一截代价是求解时间略长。对于颜色分拣这种低速任务多几十毫秒完全可接受。4.2 写一个抓取状态机接近、抓取、抬升、放置分拣动作本质是一个五步状态机接近 → 夹爪闭合 → 抬升 → 移动到放料位 → 张开夹爪。每一步都对应一次 MoveIt 规划或一个夹爪动作请求。下面用伪代码结构展示控制循环实际工程里会把每步封装成独立函数class SortController: def __init__(self): self.state IDLE self.target None # 视觉输出的目标位姿 self.place_pose None # 对应颜色的放料位姿 def on_target(self, goal): self.target goal self.state APPROACH def step(self): if self.state APPROACH: # 朝目标点上方 15cm 规划 pre self.target.copy() pre.z 0.15 self.plan_and_execute(pre) self.state GRASP elif self.state GRASP: self.gripper_close(width0.04, force20.0) self.state LIFT elif self.state LIFT: lift self.target.copy() lift.z 0.15 self.plan_and_execute(lift) self.state MOVE_PLACE elif self.state MOVE_PLACE: self.plan_and_execute(self.place_pose) self.state RELEASE elif self.state RELEASE: self.gripper_open(width0.08) self.state IDLE逻辑说明APPROACH阶段先去目标上方 15cm 的预抓取点而不是直接去目标点。这步是为了让轨迹从任意方向安全降下来避免机械臂水平横摆时撞到旁边物体。GRASP阶段用夹爪闭合传两个参数期望夹持宽度和夹持力。宽度按工件实际厚度设定若工件形变明显力优先于宽度。LIFT阶段再抬升 15cm这步很关键它把工件亲密地贴在夹爪上确认夹持稳定后再移动防止中途脱落。最后MOVE_PLACE直接走到对应颜色的放料位置RELEASE张开手指。这个状态机没有处理失败重试实际项目中每步都要检查执行结果。4.3 ROS2 话题、服务、动作的边界以及 QoS 配合把视觉和抓取串起来时会用到三种通信原语新手最容易混。高频图像流用话题一拍一答的目标位姿请求用服务夹爪运动这种带进度反馈和可取消的任务用动作。这样分工是有讲究的图像数据量大且需要持续更新适合话题这种“发完即忘”的模式分拣请求是“问一次答一次”服务最直接夹爪闭合要回传是否夹紧、能否中途取消动作接口天然带目标反馈和取消语义。# 查看三个节点的接口定义确认话题与服务名 ros2 interface show sensor_msgs/msg/Image ros2 interface show std_srvs/srv/Trigger ros2 interface show control_msgs/action/GripperCommand一个常见的初学者失误是让颜色检测节点以服务方式等待抓取节点来拉取结果。这样做在单目标时没问题但传送带上连续来料时会忙死抓取节点不如让检测节点以固定频率发布结果抓取节点只订阅自己感兴趣的那一帧。另外检测节点和 rviz2 之间也要注意 QoS 策略匹配如果相机话题默认是 sensor data 的可靠传输而你订阅时用了 BestEffort那图像就永远收不到。5. 颜色分拣避坑与排查5 个高频翻车点的现象、原因与修复这章集中写我见过最多的几个坑。每条都按“现象 → 原因 → 解决”的顺序方便你对着日志排查。5.1 颜色误检反光、白平衡、面积突变现象工件明明是红色检测结果时红时不红或者地面上出现大块红色误检区域。原因反光表面在 HSV 里 S 通道急剧下降亮斑区域被滤出阈值相机自动白平衡会让同一物体在不同光源下的色相偏移面积阈值设置过低反光斑也被当成目标。解决先固定相机曝光时间和白平衡让输出色彩恒定把 HSV 的 S 下限降到 60~80 之间给反光留出余量形态学开运算核从 3×3 提到 5×5再配合面积阈值过滤。如果工件表面是塑料或金属亮面给相机加偏振片能根治大部分反光问题。5.2 两个节点都活着但话题就是收不到数据现象ros2 topic list里能看到相机话题但ros2 topic echo订阅后一帧都没有。原因ROS2 引入了 DDS 的 QoS 兼容性检查。相机节点发布时用了 BestEffort 策略你的订阅节点用 Relay 策略两者协商失败数据只在通信栈内部被丢弃。解决查看发布者的实际策略ros2 topic info --verbose /camera/color/image_raw然后用相同策略创建订阅。5.3 MoveIt 规划失败或轨迹中途碰撞现象rviz2 里目标位姿看着没问题但 MoveIt 反复返回规划失败或轨迹能生成实际执行时却与某物体擦碰。原因目标位姿超出了机械臂工作空间或接近奇异位形分拣区域内点云/碰撞物体未加入 Planning SceneMoveIt 认为整条路径无障碍。解决把预抓取点抬高到安全高度避开机械臂工作空间边缘在 Planning Scene 里添加分拣台和周边物体的碰撞网格调整规划参数组里的goal_joint_tolerance把容差从 1e-4 放宽到 1e-3规划成功率通常明显上升。5.4 抓取时工件滑落或夹偏现象机械臂到达目标位置夹爪闭合抬升后工件掉落或歪斜。原因夹爪材质与工件表面摩擦系数低夹持点不在工件质心正上方夹持力不足或下降到具不完全闭合。解决给夹爪贴橡胶垫片代替硬质指面接近流程中加入“碰触检测”让夹爪以低力缓慢闭合检测到力突变后立即锁定而不是按固定宽度直接夹死抬升前加一步短促的微抬验证如果力反馈掉为零说明没夹上此时停下来报警。5.5 手眼标定完成后位置仍偏 5~10mm现象标定棋盘格角点位姿看起来没问题但机械臂实际抓取时总会有几毫米到一厘米的偏移。原因标定板打印尺寸误差累积相机与机器人基座间的外参全局最优但局部偏差或标定时机械臂所处的关节位形与抓取时差异很大。解决标定后不要只看棋盘格整体残差要在分拣平面多取几个角点做逐点验证重点看工作区域中心附近是否偏若只有边缘偏说明标定板照片太少补拍几个边缘视角重算。如果手上有激光测距仪量一次相机安装高度把高度方向偏差喂给标定求解能快速砍掉一半 Y 轴误差。6. 让分拣系统更可靠的两个进阶调试习惯录包回放与成功率统计分拣系统做到能跑只是第一步真正让它可靠靠的是可持续验证的调试习惯。我每调一次参数都会录一份包每调完一轮都会跑一组统计。这两件事看起来简单但能省掉大量“玄学”时间。录包用 ros2 bag 就行视觉和状态机数据都记上# 记录相机图像、关节状态、TF 树和目标位姿话题 ros2 bag record -o scene_2025_01 \ /camera/color/image_raw /joint_states /tf /target_pose回放时把 bag 当作录制的现场重现来跑ros2 bag play scene_2025_01回放后再处理效果。每次失败先回放看是视觉阈值漂移还是轨迹规划问题比反复跑到现场盲猜效率高出太多。这里要理解 bag 记录的图像是录制时刻的曝光和白平衡结果回放时如果相机参数改了旧图像只会更有价值——它相当于一份带时间戳的光照样本库。成功率统计要有明确口径。我的做法是每轮跑 100 次按颜色和位置分组记录三类数据识别成功率、抓取成功率、单次分拣耗时。颜色样本数识别准确率抓取成功率主要失败模式红10098%93%反光误检绿10096%95%阴影漏检蓝10099%97%抓偏滑落统计时有一个我认为很重要的习惯不要把滑动位置的失败记成识别失败。识别误判和抓取打滑是两个不同环节的问题混在一起统计会把排查视线引偏。把一批次的数据拆开细看时往往会发现失败集中在某几个位置这就能倒推出标定残差的方向。改成双相机或多层分拣时这套录包与统计流程不用变只需把 2D 像素坐标换成深度点云里的位姿。真机调试时我吃过一次亏仿真里连续跑 50 次全成功真机第一次就夹空。原因并不复杂——仿真的工件是规则立方体真机工件表面有脱模斜度。所以我现在约定所有仿真测过的成功率只当作验收线不上真机不下结论。希望这些经验能帮你少走一段弯路。本文还有配套的精品资源点击获取
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

声光效应与布喇格衍射:从晶体张量到声光调制器选型 2026/9/25 8:52:44

声光效应与布喇格衍射:从晶体张量到声光调制器选型

简介:这份关于晶体光波传播的课程演示文稿,以北京理工大学《导波光学基础》教学内容为蓝本,面向光电、光学工程及相关专业学生与科研人员,系统梳理了光波在晶体中传播的核心概念与关键公式。资源包为单个PPT文件,大小约…

阅读更多 →
Atlas:面向 macOS/Rust 开发者的运行时快照与协作基础设施 2026/9/25 8:52:44

Atlas:面向 macOS/Rust 开发者的运行时快照与协作基础设施

1. 项目概述:Atlas 不是“地图集”,而是一套面向现代开发者的开源协作基础设施最近在 Rust 社区和 macOS 开发者圈子里,“atlas”这个词频繁出现在技术讨论、CI/CD 配置片段、本地开发环境脚本甚至团队内部文档里。它既不是地理信息系统里的传…

阅读更多 →
华为IPD与ISO9000融合的研发质量管理方案:从流程框架到落地实践 2026/9/25 8:52:37

华为IPD与ISO9000融合的研发质量管理方案:从流程框架到落地实践

简介:本资源为基于华为IPD与质量管理体系融合的研发质量管理方案PPT,面向研发管理者、质量工程师及产品经理,帮助理解IPD主业务流框架与ISO9000质量管理体系的结合路径。内容涵盖IPD核心思想、产品实现流程、管理职责、资源管理、度量分析与改…

阅读更多 →
潮汐表原理与应用:从海洋动力学到渔业实践 2026/9/25 8:52:31

潮汐表原理与应用:从海洋动力学到渔业实践

1. 潮汐表查询的核心价值与应用场景潮汐表对于沿海地区的渔民、航海人员、海洋工程从业者以及海钓爱好者而言,就像农民手中的农历节气表一样重要。以乳山口这个典型的黄海海域为例,这里每天会有两次涨潮和两次落潮,潮差能达到3-4米。掌握精确…

阅读更多 →
尤克里里入门指南:从零基础到弹唱速成 2026/9/25 8:52:31

尤克里里入门指南:从零基础到弹唱速成

1. 尤克里里入门:为什么选择这把四弦小吉他第一次接触尤克里里是在五年前的夏威夷旅行中。当地街头艺人用这把小巧的乐器弹奏出的欢快旋律,让我瞬间被它吸引。相比吉他,尤克里里更轻便(通常只有500-800克)、弦距更短&a…

阅读更多 →
装了 OpenClaw 却不会用?这 20 个 Skills 让你的 AI 助手聪明(TaoToken 配置篇) 2026/9/25 8:52:24

装了 OpenClaw 却不会用?这 20 个 Skills 让你的 AI 助手聪明(TaoToken 配置篇)

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉