diff --git a/src/Robotic_arm/main.py b/src/Robotic_arm/main.py index 27a685095c..27818121d4 100644 --- a/src/Robotic_arm/main.py +++ b/src/Robotic_arm/main.py @@ -1,15 +1,13 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- """ -机械臂关节负载性能优化版(终极全XML错误修复) +机械臂关节刚度与可靠性优化控制器 核心优化: -1. 彻底修复所有XML Schema错误(body/mass/forcelimit 均移除违规配置) -2. 精准关节负载建模(末端负载/关节负载可配置) -3. 负载自适应PD控制(抗干扰、无超调、响应快) -4. 物理仿真优化(减少负载下的计算冗余,提升实时性) -5. 负载状态监控(实时显示负载大小、关节受力、控制误差) -6. 软件层面过载保护(替代forcelimit,兼容所有Mujoco版本) -7. 全Mujoco版本兼容(支持新旧版本,无任何语法隐患) +1. 关节刚度分层配置+自适应调节(负载/误差驱动) +2. 全方位可靠性保障(卡死检测/过载保护/异常复位/容错处理) +3. 刚度-阻尼-惯量匹配优化,降低振动与干扰 +4. 全状态监控与日志记录,便于故障追溯 +5. 兼容新旧Mujoco版本,无XML语法错误 """ import sys @@ -20,8 +18,9 @@ import threading import numpy as np import mujoco +from datetime import datetime -# ====================== 全局配置(负载优化专用) ====================== +# ====================== 全局配置(刚度+可靠性专用) ====================== # 系统适配(Windows优先,极致CPU优化) if os.name == 'nt': try: @@ -31,7 +30,7 @@ kernel32.SetThreadPriority(kernel32.GetCurrentThread(), 1) except Exception as e: print(f"⚠️ Windows系统优化失败(不影响核心功能): {e}") - # 强制单线程,避免负载下多线程竞争导致卡顿 + # 强制单线程,避免多线程竞争导致的控制不稳定 os.environ['OMP_NUM_THREADS'] = '1' os.environ['MKL_NUM_THREADS'] = '1' os.environ['NUMEXPR_NUM_THREADS'] = '1' @@ -49,22 +48,39 @@ print(f"⚠️ Mujoco Viewer导入失败(无法可视化): {e}") # 核心参数配置 -# 关节基础配置 +# 关节基础配置(按重要性分层:1>2>3>4>5) JOINT_COUNT = 5 JOINT_NAMES = ["joint1", "joint2", "joint3", "joint4", "joint5"] JOINT_LIMITS_RAD = np.array([ - [-np.pi, np.pi], # joint1 (Z轴) - [-np.pi / 2, np.pi / 2], # joint2 (Y轴) - [-np.pi / 2, np.pi / 2], # joint3 (Y轴) - [-np.pi / 2, np.pi / 2], # joint4 (Y轴) - [-np.pi / 2, np.pi / 2], # joint5 (Y轴) + [-np.pi, np.pi], # joint1(基座,最高刚度) + [-np.pi / 2, np.pi / 2], # joint2(大臂,高刚度) + [-np.pi / 2, np.pi / 2], # joint3(中臂,中高刚度) + [-np.pi / 2, np.pi / 2], # joint4(小臂,中刚度) + [-np.pi / 2, np.pi / 2], # joint5(末端,低刚度) ], dtype=np.float64) JOINT_MAX_VELOCITY_RAD = np.array([1.0, 0.8, 0.8, 0.6, 0.6], dtype=np.float64) -JOINT_MAX_TORQUE = np.array([15.0, 12.0, 10.0, 8.0, 5.0], dtype=np.float64) # 关节最大扭矩(软件过载保护) +JOINT_MAX_TORQUE = np.array([15.0, 12.0, 10.0, 8.0, 5.0], dtype=np.float64) # 最大扭矩(可靠性保护) + +# 关节刚度分层配置(核心优化:按关节层级设定基准刚度) +STIFFNESS_PARAMS = { + 'base_stiffness': np.array([200.0, 180.0, 150.0, 120.0, 80.0]), # 各关节基准刚度 + 'load_stiffness_gain': 1.8, # 负载下刚度放大系数 + 'error_stiffness_gain': 1.5, # 大误差下刚度放大系数 + 'min_stiffness': np.array([100.0, 90.0, 75.0, 60.0, 40.0]), # 最小允许刚度 + 'max_stiffness': np.array([300.0, 270.0, 225.0, 180.0, 120.0]), # 最大允许刚度 + 'stiffness_smoothing': 0.05, # 刚度变化平滑系数,防止突变 +} + +# 阻尼与惯量匹配配置(刚度配套优化,提升可靠性) +DAMPING_INERTIA_PARAMS = { + 'base_damping': np.array([8.0, 7.0, 6.0, 5.0, 3.0]), # 基准阻尼(与刚度匹配) + 'damping_stiffness_ratio': 0.04, # 阻尼-刚度匹配比,保证运动平稳 + 'armature_inertia': np.array([0.5, 0.4, 0.3, 0.2, 0.1]), # 关节惯量补偿 +} -# 仿真配置(负载下实时性优化) -SIMULATION_TIMESTEP = 0.002 # 更小步长,提升负载下控制精度 -CONTROL_FREQUENCY = 500 # 更高控制频率,应对负载下响应滞后 +# 仿真配置(可靠性优化:小步长提升控制稳定性) +SIMULATION_TIMESTEP = 0.001 # 更小步长,降低控制误差 +CONTROL_FREQUENCY = 1000 # 更高控制频率,提升响应可靠性 CONTROL_TIMESTEP = 1.0 / CONTROL_FREQUENCY FPS = 60 SLEEP_TIME = 1.0 / FPS @@ -72,30 +88,41 @@ RUNNING = True SIMULATION_START_TIME = None -# PD控制参数(负载自适应配置) +# PD控制参数(与刚度/阻尼联动) PD_PARAMS = { 'kp_base': 80.0, 'kd_base': 5.0, - 'kp_load_gain': 1.5, # 负载下比例增益放大系数 - 'kd_load_gain': 1.2, # 负载下微分增益放大系数 + 'kp_load_gain': 1.5, + 'kd_load_gain': 1.2, 'max_vel': JOINT_MAX_VELOCITY_RAD.copy() } -# 负载配置(可动态调整) +# 负载配置(与刚度联动优化) LOAD_PARAMS = { - 'end_effector_mass': 0.5, # 末端负载质量(kg),默认0.5kg - 'joint_loads': np.zeros(JOINT_COUNT), # 各关节附加负载(N·m) - 'max_allowed_load': 2.0, # 最大允许末端负载(过载保护) - 'load_smoothing_factor': 0.1 # 负载检测平滑系数,避免抖动 + 'end_effector_mass': 0.5, + 'joint_loads': np.zeros(JOINT_COUNT), + 'max_allowed_load': 2.0, + 'load_smoothing_factor': 0.1 +} + +# 可靠性保护配置(核心:卡死/过载/异常检测参数) +RELIABILITY_PARAMS = { + 'stall_detection_threshold': 0.01, # 关节卡死判定阈值(速度<此值且扭矩>90%) + 'stall_duration_threshold': 1.0, # 卡死持续时间(秒),触发复位 + 'overload_duration_threshold': 2.0, # 过载持续时间,触发保护 + 'max_angle_error': np.deg2rad(10.0), # 最大允许角度误差,触发异常报警 + 'auto_reset_on_error': True, # 是否自动复位异常关节 + 'log_reliability_data': True, # 是否记录可靠性日志 + 'log_path': 'arm_reliability_log.txt' # 日志保存路径 } -# ====================== 信号处理(负载下优雅退出) ====================== +# ====================== 信号处理(可靠性优化:优雅退出) ====================== def signal_handler(sig, frame): global RUNNING if not RUNNING: sys.exit(0) - print("\n⚠️ 收到退出信号,正在优雅退出(清理负载相关资源)...") + print("\n⚠️ 收到退出信号,正在优雅退出(保存可靠性日志+清理资源)...") RUNNING = False @@ -103,9 +130,9 @@ def signal_handler(sig, frame): signal.signal(signal.SIGTERM, signal_handler) -# ====================== 工具函数(负载优化专用) ====================== +# ====================== 工具函数(刚度+可靠性专用) ====================== def get_mujoco_id(model, obj_type, name): - """兼容所有Mujoco版本的ID查询函数(容错增强)""" + """兼容所有Mujoco版本的ID查询(容错增强,提升可靠性)""" if model is None: return -1 type_map = { @@ -125,7 +152,7 @@ def get_mujoco_id(model, obj_type, name): def deg2rad(degrees): - """角度值(度)转弧度(容错增强)""" + """角度转弧度(容错增强,可靠性保障)""" try: degrees = np.array(degrees, dtype=np.float64) return np.deg2rad(degrees) @@ -135,7 +162,7 @@ def deg2rad(degrees): def rad2deg(radians): - """弧度转角度值(度)(容错增强)""" + """弧度转角度(容错增强,可靠性保障)""" try: radians = np.array(radians, dtype=np.float64) return np.rad2deg(radians) @@ -144,97 +171,107 @@ def rad2deg(radians): return 0.0 if np.isscalar(radians) else np.zeros(JOINT_COUNT, dtype=np.float64) -def calculate_load_adaptive_gains(current_load): - """ - 负载自适应增益计算(核心优化) - 根据当前末端负载,动态调整PD增益,抵消负载干扰 - :param current_load: 当前末端负载(kg) - :return: 自适应kp, kd - """ - # 负载归一化(0 ~ 1) - normalized_load = min(current_load / LOAD_PARAMS['max_allowed_load'], 1.0) - # 动态调整增益(负载越大,增益越高,保证响应性) - adaptive_kp = PD_PARAMS['kp_base'] * (1 + normalized_load * (PD_PARAMS['kp_load_gain'] - 1)) - adaptive_kd = PD_PARAMS['kd_base'] * (1 + normalized_load * (PD_PARAMS['kd_load_gain'] - 1)) - return adaptive_kp, adaptive_kd +def write_reliability_log(content, log_path=RELIABILITY_PARAMS['log_path']): + """写入可靠性日志(核心:记录异常状态,便于追溯)""" + if not RELIABILITY_PARAMS['log_reliability_data']: + return + try: + with open(log_path, 'a', encoding='utf-8') as f: + timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S') + f.write(f"[{timestamp}] {content}\n") + except Exception as e: + print(f"⚠️ 写入可靠性日志失败: {e}") -# ====================== 机械臂模型生成(终极全XML错误修复) ====================== -def create_arm_model_with_load(): +# ====================== 机械臂模型生成(刚度配置+无XML错误) ====================== +def create_arm_model_with_stiffness(): """ - 生成带负载建模的机械臂XML模型(终极全修复+全版本兼容) - 1. 彻底修复所有XML Schema错误: - - 移除body的mass属性(改用geom定义质量) - - 移除motor的forcelimit属性(改用软件层面过载保护) - 2. 末端负载通过geom的mass属性配置,保留可动态调整功能 - 3. 关节添加阻尼和惯量,模拟真实负载特性 - 4. 简化非核心几何,提升负载下仿真速度 - 5. 依赖compiler的inertiafromgeom="true",自动由geom质量推导body惯性属性 - 6. 无任何违规配置,兼容所有Mujoco版本 + 生成带关节刚度配置的机械臂XML模型(兼容所有Mujoco版本) + 1. 按关节层级配置基准刚度、阻尼、惯量,实现刚度分层 + 2. 移除所有违规XML属性,保证无语法错误 + 3. 几何与质量配置优化,提升仿真可靠性 """ end_effector_mass = LOAD_PARAMS['end_effector_mass'] - # 连杆geom质量(对应原body质量,通过geom定义,兼容所有Mujoco版本) + # 连杆geom质量(兼容新旧Mujoco版本) link1_geom_mass = 0.8 link2_geom_mass = 0.6 link3_geom_mass = 0.6 link4_geom_mass = 0.4 link5_geom_mass = 0.2 + # 从配置中提取关节参数(刚度/阻尼/惯量) + base_stiffness = STIFFNESS_PARAMS['base_stiffness'] + base_damping = DAMPING_INERTIA_PARAMS['base_damping'] + armature_inertia = DAMPING_INERTIA_PARAMS['armature_inertia'] + xml = f""" - + -