
简介本资源是一篇发表于《农业机械学报》2020年第3期的学术论文聚焦机器人柔顺控制中的关键难点——力传感器受重力干扰导致的感知偏差问题面向机器人控制方向的研究生、工程师及科研人员提供一套基于六维力传感器重力补偿的完整技术方案。论文提出通过多姿态数据采集与姿态变换矩阵建模精确解算底座倾角、传感器零点、末端工具重力及重心坐标并结合导纳控制实现高精度抓取与柔顺放置显著提升环境交互的力感知准确性。资源为单个PDF文件1.73MB内容完整包含引言、方法推导、实验验证含重力补偿与柔顺放置实验、图表数据及参考文献结构严谨、公式详实适合作为机器人力控系统开发与算法优化的权威参考。目前已有309人学习下载是理解工业机器人力觉反馈与柔顺控制落地实践的重要文献支撑。1. 六维力传感器的重力干扰不是噪声而是系统性偏差——它让机器人“感觉错了自己的手有多重”你有没有试过让机械臂稳稳放下一个鸡蛋结果刚一接触台面就“啪”一声压碎或者在装配工件时明明还没碰到零件力传感器却已报出20N的接触力这不是电机响应慢也不是PID调得差——问题很可能出在力传感器读数里混进了未被剥离的重力分量。这篇发表于《农业机械学报》2020年第3期的研究直击工业现场最隐蔽的误差源六维力传感器安装后其自身敏感端重量、末端夹爪重力、甚至机器人底座微倾角实测达-0.2°都会在传感器坐标系中产生稳定的力与力矩偏置。这些偏置不是随机噪声而是随姿态变化的确定性干扰——当机器人抬高手臂时夹爪重力在Zs轴上的投影变小传感器却仍把这部分“消失的重力”误判为外部接触力。论文用9组不同位姿下的实测数据证明不补偿时fy方向相对误差峰值达15.76%mx方向达13.48%而经本文方法补偿后全量程平均误差压至2.98%以内。这方法不依赖高精度标定台仅靠机器人本体运动采集数据适合产线快速部署。它面向的是真实产线工程师需要在不拆卸力传感器敏感端无法单独称重、底座已固定安装、末端工具频繁更换的约束下实现可复现、可验证的柔顺控制基础——准确的受力感知。2. 从姿态采样到参数求解六维力传感器重力补偿的完整数学推导与代码实现2.1 为什么必须同时解算底座倾角、零点与工具重心六维力传感器输出的6通道信号fx, fy, fz, mx, my, mz是三类物理量的叠加①传感器固有零点偏置F₀、M₀②末端工具重力G在传感器坐标系OsXsYsZs中的投影Gs与力矩Ms③真实环境接触力F′、M′。其中Gs和Ms又取决于三个关键系统参数机器人基座相对于重力方向的安装倾角U、V工具重心在Os系中的坐标P[px, py, pz]ᵀ以及工具总重力G。若只校准零点如静态归零当机器人手臂转动时工具重力在传感器各轴上的分量剧烈变化零点补偿立即失效。论文图1明确建立世界坐标系O₀X₀Y₀Z₀Z₀竖直向上通过旋转矩阵⁰₁R将重力向量G₀[0,0,-G]ᵀ变换至基座坐标系再经¹ₛR映射至传感器坐标系最终得到Gs¹ₛR·⁰₁R·G₀。这一链式变换意味着U、V、G、P四个参数耦合在同一个非线性方程中必须联合求解。忽略任一参数如文献[9]未考虑底座倾角补偿残差将随姿态变化呈周期性漂移。2.2 基于最小二乘的姿态-力数据联合建模论文式(6)和式(7)将非线性问题线性化对N个位姿N≥3采集实测力向量Fᵢ[fxᵢ, fyᵢ, fzᵢ]ᵀ构造设计矩阵R∈ℝ^(3N×6)其第i块行为[¹ₛRᵢ, I₃]未知向量a[ax, ay, az, fx₀, fy₀, fz₀]ᵀ。此处axG·cosU·sinV等定义将重力分量与倾角解耦为线性组合。求解过程即标准最小二乘import numpy as np from scipy.linalg import lstsq # 假设已获取9个位姿的姿态变换矩阵列表 R_s_list (每个为3x3) # 和对应的实测力数据列表 F_meas_list (每个为3x1) R_design [] F_stack [] for i in range(len(R_s_list)): R_i R_s_list[i] # 3x3姿态变换矩阵 F_i F_meas_list[i].flatten() # [fx_i, fy_i, fz_i] # 构造第i块设计矩阵: [R_i | I_3] block np.hstack([R_i, np.eye(3)]) # shape: 3x6 R_design.append(block) F_stack.append(F_i) R_design np.vstack(R_design) # shape: 27x6 (9*3) F_stack np.hstack(F_stack) # shape: 27 # 求解最小二乘: a (R^T R)^{-1} R^T F a_solution, residuals, rank, s lstsq(R_design, F_stack) ax, ay, az, fx0, fy0, fz0 a_solution # 由式(10)(11)计算G, U, V G np.sqrt(ax**2 ay**2 az**2) U np.arcsin(-ay / G) * 180 / np.pi # 转换为度 V np.arctan2(-ax, -az) * 180 / np.pi注意代码中R_s_list需通过机器人正向运动学计算获得。以UR5为例给定关节角θ[θ₁…θ₆]调用ur_kinematics.fkine(θ)返回末端齐次变换矩阵T取其旋转部分R T[0:3,0:3]再根据论文图1坐标系定义提取¹ₛR R.T因传感器固连末端其坐标系与末端坐标系一致。实际部署时需确保机器人运动范围覆盖足够大的姿态差异如表1中α从57°到114°否则设计矩阵R_design秩不足解不稳定。2.3 工具重心坐标的迭代求解与力矩补偿获得F₀、G、U、V后需进一步解算工具重心P。论文式(15)构建了力矩方程对每个位姿i实测力矩Mᵢ与当前已知的fₓᵢ,fyᵢ,fzᵢ及F₀构成线性关系Mᵢ Aᵢ·P bᵢ其中Aᵢ为3×3矩阵含-fyᵢ,fzᵢ等bᵢ含fₓ₀, fy₀, fz₀及M₀。但M₀未知故引入中间变量b[px,py,pz,bx,by,bz]ᵀ将方程扩展为M F·b式16。求解后再用式(19)反推M₀# 继续使用上一步的9组数据 M_design [] M_stack [] for i in range(len(R_s_list)): fxi, fyi, fzi F_meas_list[i].flatten() Mi M_meas_list[i].flatten() # [mx_i, my_i, mz_i] # 构造A_i矩阵 (3x3) A_i np.array([ [0, fzi, -fyi], [-fzi, 0, fxi], [fyi, -fxi, 0] ]) # 构造设计矩阵块: [A_i | I_3] (3x6) block np.hstack([A_i, np.eye(3)]) M_design.append(block) M_stack.append(Mi) M_design np.vstack(M_design) # shape: 27x6 M_stack np.hstack(M_stack) # shape: 27 b_solution, *_ lstsq(M_design, M_stack) px, py, pz, bx, by, bz b_solution # 由式(19)计算M0需已知fx0,fy0,fz0 mx0 bx - fy0*pz fz0*py my0 by - fz0*px fx0*pz mz0 bz - fx0*py fy0*px提示此步骤依赖上一步求得的F₀。若F₀解算误差大会传播至M₀和P的计算。实践中建议采用两步法先用式(6)解F₀和G再固定F₀代入式(15)解P和M₀。表2数据显示手爪重心pz0.0470m47mm说明重心显著偏离传感器中心这是力矩补偿不可忽略的关键依据。3. 导纳控制闭环实现从补偿后力信号到机器人末端位移的实时映射3.1 导纳控制的本质是“力-位移”动态映射而非传统PID区别于阻抗控制位置偏差→力输出导纳控制将力偏差ΔF作为输入直接生成末端位姿修正量ΔX或速度修正量ΔV式24,25。其物理意义是当检测到接触力大于期望值如放置物体时Fz 0控制器立即指令末端向上微移Δz 0直至力回归设定区间。论文图3清晰展示该闭环结构F₀为期望力常设为0F′为重力补偿后的实测力ΔFF′-F₀经K₁、K₂矩阵加权后输出位移/速度增量。这种架构天然适配柔顺操作——无需预设轨迹仅根据实时力反馈动态调整运动。3.2 选择矩阵S的工程配置只在Z轴启用力控的实践逻辑机器人作业中并非所有自由度都需要力反馈。论文实验明确指出“物体在放置过程中只在重力方向上与接触平台有力信息的交流”。这意味着X/Y方向的位移应由位置规划主导避免因微小扰动导致水平晃动仅Z方向需力控调节。这通过6×6对角选择矩阵S实现式27# S矩阵仅Z轴(索引2)和绕Z轴旋转(索引5)启用力控其余置0 S np.diag([0, 0, 1, 0, 0, 0]) # 6x6对角矩阵 # K1, K2为对角增益矩阵需根据任务标定 K1 np.diag([0, 0, 0.1, 0, 0, 0]) # 单位: mm/N (Z向位移增益) K2 np.diag([0, 0, 0.1, 0, 0, 0]) # 单位: mm/(s·N) (Z向速度增益) # 实时控制循环 while not placement_done: # 1. 读取原始力传感器数据 F_raw sensor.read_force() # [fx, fy, fz, mx, my, mz] M_raw sensor.read_torque() # 2. 应用重力补偿式22 F_comp F_raw[:3] - np.array([fx0, fy0, fz0]) - Gs_calc(U, V, R_s_current) M_comp M_raw[:3] - np.array([mx0, my0, mz0]) - Ms_calc(G, px, py, pz, R_s_current) # 3. 计算力偏差期望F0[0,0,0,0,0,0] F0 np.zeros(6) F_prime np.hstack([F_comp, M_comp]) delta_F F_prime - F0 # 4. 导纳控制输出式27 delta_V S (K1 delta_F K2 delta_F) # 6x1速度修正量 # 5. 发送速度指令至机器人控制器 robot.set_cartesian_velocity(delta_V) # 6. 判断放置完成Fz在±0.05N内持续100ms if abs(F_comp[2]) 0.05: stable_count 1 if stable_count 100: # 假设控制周期1ms placement_done True else: stable_count 0关键参数说明K1[2,2]0.1 mm/N表示每超出期望力1N末端Z向位移增加0.1mmK2[2,2]0.1 mm/(s·N)表示每超出1NZ向速度增加0.1mm/s。图7实验显示增大K1/K2可缩短放置时间但会导致力/速度振荡如K10.5时出现超调。工程中需在响应速度与稳定性间权衡推荐初始值K10.05~0.15K20.05~0.1。3.3 补偿效果验证无补偿 vs 有补偿的力-位移曲线对比论文图7a/b直观揭示重力补偿的必要性。无补偿时力传感器读数包含未扣除的工具重力分量约3.15N导致控制器误判“物体尚未接触”持续向下施加位移直至产生冲击图7b中位移超调达15mm。而有补偿后Fz从3.15N平滑衰减至0位移同步收敛至0全程无超调。验证时需关注两个指标①力残差补偿后F′的均值应趋近于0表2中fz₀0.1976N补偿后残差0.05N②动态跟随性在位姿连续变化实验图5中补偿值与测量值曲线应严格对称误差带宽度±0.1N。若误差带偏移说明U/V角或G值标定不准需重新采集数据。4. 工程落地关键补偿参数在线更新与ROS2节点集成方案4.1 参数漂移应对基于滑动窗口的在线重标定机制实验室标定参数在产线长期运行中会因温度漂移、机械松动而失效。论文未涉及在线更新但工程必需。我们采用滑动窗口最小二乘每采集M50组新姿态数据间隔10s用式(9)重算a向量若新解与历史均值偏差5%则触发参数更新。Python实现核心逻辑class GravityCompensator: def __init__(self, window_size50): self.window_size window_size self.F_buffer deque(maxlenwindow_size) # 存储最近50组F self.R_buffer deque(maxlenwindow_size) # 存储对应R_s self.a_history [] # 历史解集 def update(self, F_new, R_new): self.F_buffer.append(F_new) self.R_buffer.append(R_new) if len(self.F_buffer) self.window_size: # 构造新设计矩阵并求解 R_design_new self._build_R_design() F_stack_new np.hstack(list(self.F_buffer)) a_new, *_ lstsq(R_design_new, F_stack_new) # 检查漂移 if self.a_history: drift np.max(np.abs(a_new - np.mean(self.a_history, axis0))) if drift 0.05 * np.mean(np.abs(a_new)): self.a_history.append(a_new) self._apply_new_params(a_new) # 更新内部参数 def _build_R_design(self): # 同2.2节略 pass提示窗口大小M需权衡。M过小如10易受瞬时噪声干扰M过大如200响应迟钝。建议M30~50对应5~10分钟采集周期覆盖典型温升过程。4.2 ROS2节点封装发布补偿后力话题供下游控制器订阅在ROS2 Humble环境下将补偿算法封装为独立节点遵循ROS2最佳实践!-- package.xml -- exec_dependrclpy/exec_depend exec_dependsensor_msgs/exec_depend exec_dependgeometry_msgs/exec_depend exec_dependstd_msgs/exec_depend# gravity_compensator_node.py import rclpy from rclpy.node import Node from sensor_msgs.msg import WrenchStamped from geometry_msgs.msg import Twist from std_msgs.msg import Float64MultiArray class GravityCompensatorNode(Node): def __init__(self): super().__init__(gravity_compensator) # 订阅原始力传感器话题 self.subscription self.create_subscription( WrenchStamped, /wrist_wrench/raw, self.wrench_callback, 10) # 发布补偿后力话题 self.publisher_ self.create_publisher( WrenchStamped, /wrist_wrench/compensated, 10) # 加载标定参数从yaml文件 self.declare_parameter(calib_file, /path/to/calib.yaml) self.calib_params self.load_calib_params() def wrench_callback(self, msg): # 解析原始数据 F_raw np.array([msg.wrench.force.x, msg.wrench.force.y, msg.wrench.force.z]) M_raw np.array([msg.wrench.torque.x, msg.wrench.torque.y, msg.wrench.torque.z]) # 应用补偿调用2.2节函数 F_comp, M_comp self.compensate(F_raw, M_raw, self.calib_params) # 构建WrenchStamped消息 compensated_msg WrenchStamped() compensated_msg.header msg.header compensated_msg.wrench.force.x F_comp[0] compensated_msg.wrench.force.y F_comp[1] compensated_msg.wrench.force.z F_comp[2] compensated_msg.wrench.torque.x M_comp[0] compensated_msg.wrench.torque.y M_comp[1] compensated_msg.wrench.torque.z M_comp[2] self.publisher_.publish(compensated_msg)部署要点在launch文件中启动该节点并确保/wrist_wrench/raw话题由硬件驱动节点如ros2_control的force_torque_sensor_broadcaster稳定发布。下游导纳控制器节点直接订阅/wrist_wrench/compensated避免重复计算。参数文件calib.yaml应包含U,V,G,fx0,fy0,fz0,mx0,my0,mz0,px,py,pz等字段支持热重载。4.3 硬件在环测试用示波器捕获补偿前后力信号的时域对比最终验证必须在真实机器人上进行。推荐使用示波器监测力传感器模拟输出若为模拟接口或通过ROS2命令行工具ros2 topic echo抓取数据# 抓取10秒原始力数据 ros2 topic echo /wrist_wrench/raw --csv raw_data.csv # 抓取补偿后数据 ros2 topic echo /wrist_wrench/compensated --csv comp_data.csv用Python脚本绘制时域图图7复现import pandas as pd import matplotlib.pyplot as plt raw_df pd.read_csv(raw_data.csv) comp_df pd.read_csv(comp_data.csv) plt.figure(figsize(12,6)) plt.subplot(2,1,1) plt.plot(raw_df[wrench.force.z], labelRaw Fz) plt.ylabel(Force Z (N)) plt.legend() plt.subplot(2,1,2) plt.plot(comp_df[wrench.force.z], labelCompensated Fz) plt.ylabel(Force Z (N)) plt.xlabel(Sample Index) plt.legend() plt.tight_layout() plt.show()合格的补偿效果表现为补偿后Fz曲线围绕0基线波动峰峰值0.2N对应论文±0.05N判定阈值且无趋势性漂移。若存在缓慢上升/下降斜率说明零点漂移未被完全抑制需检查温度补偿或重启在线标定。本文还有配套的精品资源点击获取