尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

从抓取到触摸:机器人触觉感知与柔顺控制的核心技术拆解

从抓取到触摸:机器人触觉感知与柔顺控制的核心技术拆解 最近一段时间关于机器人具身智能的演示视频越来越多。最让我感兴趣的不是机器人能跑多远能翻几个跟头而是它能“摸”出物体了。有的视频里机器人的手指在麻将牌表面来回搓动似乎能感知到牌面的平整度有的视频里它慢慢挤压一支牙膏压力再大一点就会挤出来。这类动作对人类来说几乎不需要思考但对机器人来说是从“能抓”到“会摸”的一次重要跨越。这篇文章不打算复述新闻而是围绕“触觉感知 柔顺控制 大模型决策”这条技术线把这类演示拆开来看。文章会先讲清楚难点在哪里再给出一套基于 PyBullet 的最小仿真实验最后聊一聊从仿真走向真机时常见的工程问题。无论你是做机器人控制、做 AI 算法还是刚开始接触具身智能应该都能从中找到值得收藏的内容。1. “摸麻将”“挤牙膏”难在哪先理解具身智能的触觉闭环1.1 一个人类习以为常的动作机器人为什么搞不定先思考一个问题抓取和触摸到底有什么区别抓取一个麻将牌重点在于位置和姿态。视觉系统识别到牌的位置机械臂规划一条轨迹末端夹爪张开、闭合夹持力大于重力即可。整个过程可以用刚体运动学和简单的摩擦模型来描述很多工业机械臂已经能稳定做到。但“摸”一个麻将牌难度完全不同。机器人手指需要贴近牌面施加一个可控且较小的压力在接触后保持稳定甚至要沿着牌面滑动来感知纹理和边缘。这就涉及三个关键问题末端执行器与物体接触时力的方向、大小要实时可感知控制策略不能只关心位置还要考虑力与位置的关系如果牌面材质不同、表面有污渍或划痕系统需要根据触觉反馈动态调整动作。“挤牙膏”则更复杂。牙膏管是典型的柔性物体挤压时会发生非线性形变内部的膏体流动、管口受力情况都会实时变化。机器人无法提前用精确模型算出“用力 5N 就会挤出来多少”它必须在不断反馈中调整压力这个过程很像人类凭手感操作。所以这些演示看起来轻松背后其实是触觉感知、力控算法和决策模型三方面的深度结合。1.2 触觉感知在具身智能中的位置传统机器人动作流程可以概括为视觉感知 → 路径规划 → 运动执行这个流程适合抓取固定姿态的刚体。但一旦进入接触操作场景比如插拔、组装、打磨、揉搓、挤压流程就变成了视觉预判 → 接近目标 → 触觉反馈 → 力/位调整 → 完成操作在这种闭环中触觉不再是“事后检测”而是实时控制回路的一部分。机器人不能等到牌被压坏才发现力太大必须在接触瞬间感知到力的变化趋势并及时松开或停止。近两年具身智能领域反复提到“多模态感知”视觉负责提供全局几何信息触觉负责提供局部交互信息。视觉告诉你麻将牌在哪里触觉告诉你手指已经碰到牌面了、压力是否合适。两者缺一不可。1.3 从视觉到大模型VLA 正在改变机器人交互方式短视频里经常出现的“李飞飞教机器人摸麻将”这类描述技术上往往和视觉-语言-动作模型有一定关系也就是常说的 VLAVision-Language-Action Model。简单理解VLA 模型把“图像 语言指令 动作序列”统一映射到一个神经网络中。用户可以说“轻轻摸一下麻将牌的花纹”模型根据当前图像和历史经验输出动作分布再由底层控制器转换成电机指令。为什么大家会把机器人摸麻将和这类大模型联系起来因为“摸”这个动作隐藏着大量人类先验麻将牌是硬的、表面光滑、不能用力按压牙膏管是软的、挤压力度要平滑、挤过之后会回弹。这些知识很难手动编写成明确的工程规则但可以通过大模型从海量视频、遥操作数据中学习。不过也要冷静看待模型输出的是“动作指令的高维分布”真正落地时仍然需要底层控制器提供安全、稳定、高频的反馈控制。VLA 负责“想”底层力控负责“做”。2. 环境准备用仿真平台先“演”一遍2.1 为什么先用仿真而不是直接上真机很多人看到演示视频后第一反应是“我也想做一套”。但真机实验的成本和风险都比较高触觉传感器价格不低灵巧手更贵真机调试过程中容易发生碰撞维修成本高数据采集速度慢一次实验需要大量人工干预算法不成熟时硬件容易损坏。因此在机器人研究中通常会先在仿真环境里验证算法逻辑。仿真环境可以快速复现控制策略也可以为强化学习提供大量训练样本。当然仿真与真实世界之间始终存在差距业内称之为 Sim-to-Real Gap。仿真不能完全替代真机但能帮我们少踩很多低级坑。2.2 常见机器人仿真平台对比本文的示例选择 PyBullet因为它开源、轻量、安装简单适合快速验证控制思路。下面是几个常见平台的对比仿真平台特点适用场景PyBullet开源、轻量、安装简单快速验证、教学、中小规模强化学习MuJoCo接触求解精度高、物理引擎成熟触觉交互、灵巧手、强化学习研究Isaac Sim / Isaac Lab图形真实、支持 GPU 并行工业级仿真、大规模机器人训练Coppeliasim可视化强、支持多种控制接口机械臂、移动机器人教学与科研选择平台时要根据自己的场景来。如果只是验证“接触力检测 停止决策”这种逻辑PyBullet 足够了。如果要做高精度触觉仿真、弹性体形变实验可以进一步学习 MuJoCo 或 Isaac Lab。2.3 环境搭建步骤本文示例使用 Python 3.8 以上版本通过虚拟环境管理依赖。mkdir robot_touch_demo cd robot_touch_demo python -m venv venv source venv/bin/activate # Windows 下执行 venv\Scripts\activate pip install pybullet安装完成后可以用一行命令验证是否成功python -c import pybullet; print(pybullet.getAPIVersion())正常情况下会输出一个 API 版本号。不同 PyBullet 版本的模型文件、接口参数可能略有差异本文以常见环境为例重点演示实现思路。3. 核心技术拆解触觉传感器、柔顺控制与世界模型3.1 触觉传感器的几种主流方案要想让机器人“有手感”第一步是让硬件能感知力。目前主流触觉感知方案大致分为以下几类传感器类型原理优点局限压阻式压力改变导电材料电阻成本低、工艺成熟漂移明显、需要标定电容式压力改变极板间距和电容灵敏度高、可做阵列抗干扰要求高视触觉传感器摄像头拍摄凝胶表面形变空间分辨率高、信息丰富体积大、数据量高压电薄膜力改变材料电荷输出动态响应快不适合静态测量这里特别提一下视触觉传感器比如 GelSight 系列。它的思路是在手指表面覆盖一层带标记点的弹性凝胶内部用微型摄像头记录变形图像再通过图像计算接触力分布和纹理信息。它的空间分辨率很高适合“摸麻将牌花纹”这类精细任务。3.2 从位置控制到柔顺控制传统工业机械臂大多使用位置控制设定一个目标角度伺服系统驱动电机到达目标。这种方式适合轮廓已知、无碰撞场景的任务。但接触操作不行。如果机械臂带着刚性位置控制去挤压牙膏一旦接触力超过预期要么电机继续硬推要么直接触发急停结果不是挤爆牙膏就是机器人停机。柔顺控制的核心思想是让机器人末端在接触时表现出弹簧、阻尼一样的力学特性。最常用的是阻抗控制和导纳控制阻抗控制根据位置误差计算需要的力矩导纳控制根据力矩传感器读到的外力修正位置增量。“挤牙膏”这类演示通常可以设计成导纳控制末端先缓慢下降检测到接触力后根据力的大小决定下一拍是继续下压、保持还是回退。这样机器人挤压柔软的物体时动作会显得自然、平滑。3.3 摸与挤背后的模型能力有了触觉传感器也有了力控算法为什么还需要大模型因为“摸麻将”和“挤牙膏”不只是一个控制问题还是一个语义理解和经验决策问题。机器人需要知道麻将牌表面是光滑的不能施加过大压力摸的目标是感知纹理而不是推走它牙膏管的形变是非线性的力过大会变形、过小挤不出来如果操作失败在下一个动作里要如何修正。这些知识需要模型从海量数据中自动学习。视觉-语言-动作模型通过图像和自然语言输入将人类经验转化为动作策略。而世界模型之所以被频繁提及是因为它让机器人学会预测“下一步会怎样”——比如“在这个角度继续推牌会不会滑走”这更接近人类的手感。3.4 为什么“摸”“挤”是分水岭从刚体操作到柔性体操作是机器人作业难度的一次明显跃升。刚体物体可以用解析模型表达存在明确的几何约束和控制方法。柔性体则不同比如牙膏、纸巾、面团、布料它们的状态空间是无限维的无法靠手工建模来精确控制。所以能够稳定完成“摸麻将”“挤牙膏”的机器人往往意味着它已经具备了三类能力高分辨率触觉感知能力实时力/位混合控制能力数据驱动的物体交互经验。这就是为什么这些动作被看成“手感”的标志性突破。4. 实战在 PyBullet 中模拟末端触觉感知与停止决策4.1 实验目标我们做一个最小可运行的仿真实验控制机械臂末端从高处缓慢下压当末端与桌面上的薄板物体模拟麻将牌发生接触且接触力超过阈值时机械臂停止下压并打印接触力信息。这个实验虽然简单但已经包含了一个完整的“触觉反馈 → 停止决策”闭环是很多精细操作任务的基础逻辑。4.2 完整示例代码下面给出完整脚本保存为demo_touch_sensing.py。# demo_touch_sensing.py import time import pybullet as p import pybullet_data # 连接 GUI 界面 physics_client p.connect(p.GUI) p.setAdditionalSearchPath(pybullet_data.getDataPath()) p.setGravity(0, 0, -9.8) # 加载地面 plane_id p.loadURDF(plane.urdf) # 创建薄板物体模拟“麻将牌” half_extents [0.04, 0.03, 0.012] collision_id p.createCollisionShape(p.GEOM_BOX, halfExtentshalf_extents) visual_id p.createVisualShape( p.GEOM_BOX, halfExtentshalf_extents, rgbaColor[0.1, 0.5, 0.8, 1] ) board_id p.createMultiBody( baseMass0.05, baseCollisionShapeIndexcollision_id, baseVisualShapeIndexvisual_id, basePosition[0.45, 0.0, 0.2] ) # 加载 Franka 机械臂 robot_id p.loadURDF( franka_panda/panda.urdf, basePosition[0, 0, 0], useFixedBaseTrue ) # 找出所有非固定关节 joint_indices [] for i in range(p.getNumJoints(robot_id)): joint_info p.getJointInfo(robot_id, i) if joint_info[2] ! p.JOINT_FIXED: joint_indices.append(i) print(非固定关节索引:, joint_indices) # 找到末端执行器 link end_effector_index None for i in range(p.getNumJoints(robot_id)): link_name p.getJointInfo(robot_id, i)[12].decode(utf-8) if panda_grasptarget in link_name: end_effector_index i break if end_effector_index is None: # 部分模型命名不同可手动指定一个近似末端 end_effector_index 11 print(末端执行器 link 索引:, end_effector_index) # 设置一个合理的初始关节角度避免奇异位形 initial_joint_positions [0.0, -0.785, 0.0, -2.356, 0.0, 1.571, 0.785] for idx, joint_idx in enumerate(joint_indices[:7]): p.resetJointState(robot_id, joint_idx, initial_joint_positions[idx]) p.stepSimulation() # 目标从高处逐步下压 start_pos [0.45, 0.0, 0.35] end_pos [0.45, 0.0, 0.21] force_threshold 3.0 steps 80 print(开始下压当接触力超过阈值时停止...) for step in range(steps): alpha step / float(steps) target_pos [ start_pos[0] (end_pos[0] - start_pos[0]) * alpha, start_pos[1] (end_pos[1] - start_pos[1]) * alpha, start_pos[2] (end_pos[2] - start_pos[2]) * alpha ] # 逆运动学求解目标关节角度 joint_pose p.calculateInverseKinematics( robot_id, end_effector_index, target_pos, targetOrientation[0, 0, 0, 1] ) # 位置控制只控制前 7 个手臂关节 control_idx joint_indices[:7] target_angles joint_pose[:len(control_idx)] p.setJointMotorControlArray( robot_id, control_idx, p.POSITION_CONTROL, targetPositionstarget_angles ) p.stepSimulation() # 检查末端与薄板之间的接触力 contacts p.getContactPoints(robot_id, board_id) max_force 0.0 for cp in contacts: # cp[9] 表示法向接触力 if cp[9] max_force: max_force cp[9] if max_force force_threshold: print(f第 {step} 步感知到接触力 {max_force:.2f} N停止下压) break time.sleep(1.0 / 240.0) print(实验结束)4.3 代码讲解这段代码可以拆成几个部分来看。第一部分是环境初始化。p.connect(p.GUI)会打开一个可视化窗口方便观察机械臂运动过程。如果服务器环境没有图形界面可以把p.GUI改成p.DIRECT。第二部分是创建物体。我们用createCollisionShape和createVisualShape创建了一个长方体薄板这比加载外部模型文件更简单也更稳定。模拟麻将牌时薄板的尺寸参考了真实麻将牌的大致比例。第三部分是加载机械臂。PyBullet 自带的pybullet_data中包含 Franka Panda 机械臂模型路径是franka_panda/panda.urdf。如果你的环境里没有这个模型可以换成kuka_iiwa/model.urdf但需要相应调整末端 link 索引。第四部分是计算末端执行器 link。Panda 模型里有专门的panda_grasptargetlink它位于夹爪中心是控制末端位置常用的参考点。第五部分是主循环。机械臂末端从[0.45, 0.0, 0.35]开始缓慢下压每次前进一步到达[0.45, 0.0, 0.21]。每一拍都用逆运动学解算关节角度并通过位置控制执行。随后检查机械臂与薄板之间的接触点一旦法向接触力达到阈值就停止下压。4.4 运行与预期结果在脚本目录下执行python demo_touch_sensing.py预期可以看到一个 3D 仿真窗口机械臂缓缓向桌面上的蓝色薄板下压。当接触力超过 3.0 时终端会打印类似内容非固定关节索引: [0, 1, 2, 3, 4, 5, 6, 9, 10] 末端执行器 link 索引: 11 开始下压当接触力超过阈值时停止... 第 42 步感知到接触力 3.24 N停止下压 实验结束具体步数会根据仿真环境中的碰撞模型、初始关节角度和阈值不同而有差异。如果接触力一直为 0可以适当调低终点高度或者调小接触力阈值。4.5 实验扩展思路这个 Demo 只是接触逻辑的最小验证。实际项目中可以做以下扩展把薄板替换为柔性物体观察挤压时的力变化加入视觉识别先在图像中找到麻将牌位置再控制末端靠近在接触后执行“轻压-微抬-滑动”的轨迹模拟真实摸牌动作将停止决策替换为强化学习策略让机器人学习不同材质下的最优压力。5. 常见问题与排查思路在实际动手过程中会遇到各种问题。我整理了几个高频场景。问题现象可能原因解决思路接触力一直为 0末端还没碰到物体目标点 Z 坐标过高物体没有碰撞体降低终点高度检查是否设置碰撞形状在 GUI 中调整视角确认机械臂剧烈抖动目标点距离当前位置太远IK 数值噪声单步增量过大增大总步数缩小每一步的位移使用阻尼最小二乘 IK启动时报错找不到 URDF 模型没有设置 pybullet_data 路径模型名称不匹配调用p.setAdditionalSearchPath(pybullet_data.getDataPath())换用kuka_iiwa/model.urdf等内置模型仿真接触力与真机差异大仿真接触模型偏理想摩擦系数、材质参数失真先做传感器标定使用 domain randomization 增强迁移能力强化学习训练不稳定奖励稀疏力信号噪声大控制频率不统一设计 reward shaping对力信号做滤波统一控制周期排查顺序一般遵循先确认模型加载成功再确认接触点位置是否正确最后检查力阈值是否合理。很多时候问题并不在算法而在“末端到底有没有碰到物体”这个基础问题上。6. 从 Demo 到真机工程落地的几点建议6.1 数据与标定触觉传感器不像视觉相机那样有统一的数据协议。不同厂家、不同型号的传感器量程、分辨率、采样率都不同。真机实验前一定要做标定用已知重量的砝码建立传感器读数与真实力值的映射关系记录传感器的静态漂移和温漂特性对手指接触面积不同的场景分别修正力值曲线。如果后续要训练 VLA 模型还要注意视觉和触觉数据的时间同步。很多项目失败不是因为模型不够好而是因为相机图像和触觉数据根本没有对齐。6.2 安全边界无论演示视频里看起来多么丝滑真机调试都要把安全放在第一位。设置最大关节力矩和最大末端速度在机器人工作区外设置急停按钮调试人员离开机械臂动作范围后再执行自动程序首次接触实验用软性物体或低功率模式验证反馈逻辑所有操作遵循最小权限原则只开放必要的控制权限。机器人一旦进入接触操作位置控制下的碰撞保护能力很弱务必保证力控算法的优先级和安全阈值。6.3 硬件接口与控制架构真机系统通常采用“上位机 实时内核”的架构ROS2 / MoveIt2 负责上层规划伺服驱动器通过 EtherCAT、CANopen 等总线接收实时指令触觉传感器通过 SPI、I2C 或 USB 采集并尽量保持 1kHz 以上采样率力控算法放在实时线程中运行避免被上层逻辑阻塞。仿真环境里我们可以用p.stepSimulation()控制节奏但真机对实时性要求高得多。控制周期抖动会导致触觉反馈延迟进而引发振荡甚至碰撞。6.4 模型决策与底层控制分层VLA 模型输出动作频率往往较低通常在几赫兹到十几赫兹。而底层力控需要几百到上千赫兹的反馈频率。直接让大模型输出细粒度力矩信号并不现实。更合理的方案是分层视觉和大模型层负责理解任务、识别目标、提出动作意图中间层将动作意图转换为轨迹或阻抗控制参数底层力控层高频执行力/位混合控制实时响应接触力变化。“摸麻将”这类动作其实是由大量底层力控原语组成的高层策略。大模型负责选择“该摸哪里、该用什么力度”底层控制器负责把“摸”这个动作执行稳定。6.5 仿真到真机的迁移从 PyBullet 迁移到真机前通常需要做三步工作参数对齐把仿真中的摩擦系数、关节质量、接触模型调到尽量接近真机域随机化在训练时随机化质量、摩擦、材质等参数提升策略鲁棒性数据补充仿真数据训练出粗模型再用真机遥操作数据微调。这条路径目前在学术界和工业界都比较常见。先用仿真批量跑策略再在真机上做小样本微调能显著降低数据采集成本。7. 总结与下一步学习路线回顾一下这篇文章主要拆解了“机器人摸麻将、挤牙膏”这类演示背后的三层能力硬件层触觉传感器让机器人能感知接触力、纹理、形变控制层柔顺控制让机器人在接触时不是“硬顶”而是根据力反馈调整动作模型层VLA 模型和世界模型提供了任务理解与经验决策能力。同时我们用 PyBullet 完成了一个最小仿真实验验证了“接触力检测 阈值停止”的闭环逻辑。你可以在这个基础上继续扩展逐步加入视觉识别、柔顺控制和强化学习。如果这篇文章对你有帮助建议收藏备用。下次再看到“机器人摸麻将”“机器人挤牙膏”这类视频时你就可以清楚地说出它背后需要哪些能力了。下一步学习方向可以按这个路线走补齐机器人学基础刚体运动学、逆运动学、雅可比矩阵深入学习控制理论阻抗控制、导纳控制、力位混合控制掌握一个仿真平台PyBullet 或 MuJoCo多做接触操作实验学习 ROS2 和 MoveIt2为真机部署打基础了解 VLA 模型从 RT-1、RT-2、OpenVLA 等开源工作入手关注触觉感知方向尤其是视触觉传感器如 GelSight 相关的研究成果。具身智能现在还处于快速变化阶段触碰操作是这个领域里最有“手感”的方向之一。如果你也在做相关实验欢迎在评论区交流你的踩坑经历。
返回列表