From a9db87d81dbcd11f349b3b03ba196d583a9ce271 Mon Sep 17 00:00:00 2001 From: sladro Date: Fri, 12 Sep 2025 22:40:11 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E9=87=8D=E6=9E=84=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=E7=AE=A1=E7=90=86=EF=BC=8C=E9=81=B5=E5=BE=AA=E5=8D=95?= =?UTF-8?q?=E4=B8=80=E8=81=8C=E8=B4=A3=E5=8E=9F=E5=88=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 将单文件使用的配置改为文件内常量定义: - kinematics.py: 运动学求解参数改为常量 - ai_rrt_star.py: RRT*算法参数改为常量 - path_optimizer.py: 路径优化参数改为常量 - main_window.py: GUI界面参数改为常量 - hole_crossing.py: 洞口穿越参数改为常量 保留跨文件共享的配置在config.json: - robot, wall, hole, task_points等多模块使用的配置 - path_planning的collision和execution参数 更新CLAUDE.md文档说明新的配置管理原则。 遵循"配置文件用于多文件共享,单文件使用参数定义为文件内常量"原则。 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- CLAUDE.md | 17 ++- config.json | 30 ----- debug_coordinates.py | 156 ++++++++++++++++++++++ debug_execution.py | 230 +++++++++++++++++++++++++++++++++ src/gui/main_window.py | 38 +++--- src/planning/ai_rrt_star.py | 30 +++-- src/planning/hole_crossing.py | 10 +- src/planning/path_optimizer.py | 17 +-- src/robot/kinematics.py | 19 ++- 9 files changed, 457 insertions(+), 90 deletions(-) create mode 100644 debug_coordinates.py create mode 100644 debug_execution.py diff --git a/CLAUDE.md b/CLAUDE.md index c08274c..8cdd885 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -32,14 +32,25 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co ## 配置管理原则 -**所有配置参数必须从 `config.json` 文件读取,严禁硬编码:** -- 机械臂模型路径必须从 `config.robot.model_path` 读取 +**配置管理遵循单一职责原则:** + +### 跨文件共享配置(存储在 `config.json`) +- 机械臂模型路径从 `config.robot.model_path` 读取 - 墙体参数从 `config.wall` 读取 - 洞口参数从 `config.hole` 读取 - 任务点A、B从 `config.task_points` 读取 - 运送物体参数从 `config.transport_object` 读取 - 仿真参数从 `config.simulation` 读取 -- 修改任何参数只需修改配置文件,无需改动代码 +- 路径规划的碰撞检测和执行参数从 `config.path_planning` 读取 + +### 单文件专用配置(定义为文件内常量) +- **运动学求解参数**:在 `src/robot/kinematics.py` 中定义 `MAX_ITERATIONS`、`EPSILON` +- **RRT*算法参数**:在 `src/planning/ai_rrt_star.py` 中定义所有算法常量 +- **路径优化参数**:在 `src/planning/path_optimizer.py` 中定义优化常量 +- **GUI界面参数**:在 `src/gui/main_window.py` 中定义界面常量 +- **洞口穿越参数**:在 `src/planning/hole_crossing.py` 中定义策略常量 + +**原则**:配置文件用于多文件共享,单文件使用的参数定义为文件内常量 ## 项目架构 diff --git a/config.json b/config.json index 9f2eb4b..af6aecf 100644 --- a/config.json +++ b/config.json @@ -95,41 +95,11 @@ ], "real_time": false }, - "camera": { - "distance": 4.0, - "yaw": 45, - "pitch": -30, - "target": [ - 0, - 0, - 0 - ] - }, - "gui": { - "window_size": "1200x800" - }, - "kinematics": { - "max_iterations": 1500, - "epsilon": 1e-05 - }, "path_planning": { - "ai_rrt_star": { - "enabled": true, - "max_iterations": 5000, - "step_size": 0.1, - "goal_sample_rate": 0.15, - "search_radius": 0.5, - "hole_bias_rate": 0.3, - "enforce_hole_crossing": false - }, "collision": { "check_resolution": 0.05, "safety_margin": 0.01 }, - "optimization": { - "shortcut_iterations": 50, - "smoothing_factor": 0.5 - }, "execution": { "velocity_scaling": 1.0, "position_tolerance": 0.01, diff --git a/debug_coordinates.py b/debug_coordinates.py new file mode 100644 index 0000000..4bfd4c6 --- /dev/null +++ b/debug_coordinates.py @@ -0,0 +1,156 @@ +#!/usr/bin/env python3 +""" +坐标系统调试脚本 +验证KDL运动学与PyBullet仿真的坐标一致性 +""" + +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +from src.config_loader import ConfigLoader +from src.robot.arm_controller import create_arm_controller +from src.simulation.environment import Environment +import pybullet as p +import pybullet_data +import numpy as np + +def debug_coordinates(): + """调试坐标系统一致性""" + print("=== 坐标系统调试分析 ===") + + # 初始化仿真 + physics_client = p.connect(p.GUI) + p.setAdditionalSearchPath(pybullet_data.getDataPath()) + + try: + # 加载配置 + config_loader = ConfigLoader() + config = config_loader.get_full_config() + + print(f"机械臂基座位置: {config['robot']['base_position']}") + print(f"机械臂基座朝向: {config['robot']['base_orientation']}") + + # 创建机械臂控制器 + arm_controller = create_arm_controller(config_loader, physics_client) + + # 创建环境(包括墙体和任务点) + environment = Environment(config_loader, physics_client) + + print("\n=== 关节映射信息 ===") + kdl_names = arm_controller.kinematics_engine.get_joint_names() + pb_names = arm_controller.robot_loader.get_joint_names() + print(f"KDL关节顺序: {kdl_names}") + print(f"PyBullet关节顺序: {pb_names}") + print(f"KDL→PyBullet映射: {arm_controller._kdl_to_pb}") + print(f"PyBullet→KDL映射: {arm_controller._pb_to_kdl}") + + print("\n=== 当前机械臂状态测试 ===") + + # 测试1:获取当前关节位置 + current_joints = arm_controller.get_current_joint_positions() + print(f"当前关节位置(KDL顺序): {[f'{x:.3f}' for x in current_joints]}") + + # 测试2:正向运动学 - 计算末端位置 + fk_position, fk_orientation = arm_controller.forward_kinematics(current_joints) + print(f"正向运动学计算的末端位置: {[f'{x:.3f}' for x in fk_position]}") + print(f"正向运动学计算的末端姿态: {[f'{x:.3f}' for x in fk_orientation]}") + + # 测试3:直接从PyBullet获取末端位置(验证) + robot_id = arm_controller.robot_loader.get_robot_id() + end_effector_index = len(pb_names) # 末端执行器通常是最后一个link + link_state = p.getLinkState(robot_id, end_effector_index - 1, physicsClientId=physics_client) + pb_end_position = link_state[0] # 世界坐标中的位置 + pb_end_orientation = link_state[1] # 世界坐标中的姿态(四元数) + + print(f"PyBullet直接查询的末端位置: {[f'{x:.3f}' for x in pb_end_position]}") + print(f"PyBullet直接查询的末端姿态: {[f'{x:.3f}' for x in pb_end_orientation]}") + + # 测试4:坐标差异分析 + pos_diff = np.array(fk_position) - np.array(pb_end_position) + pos_error = np.linalg.norm(pos_diff) + print(f"位置差异: {[f'{x:.4f}' for x in pos_diff]}") + print(f"位置误差幅度: {pos_error:.4f} 米") + + if pos_error > 0.01: # 1cm tolerance + print("⚠️ 发现显著位置差异!KDL和PyBullet坐标不一致") + else: + print("✅ 位置一致性良好") + + print("\n=== 逆向运动学测试 ===") + + # 测试5:任务点可达性 + task_points = config_loader.get_task_points() + + for point_name, point_info in task_points.items(): + target_pos = point_info['position'] + print(f"\n测试 {point_name}: {target_pos}") + + # 使用逆运动学求解 + joint_solution = arm_controller.inverse_kinematics(target_pos, seed_angles=current_joints) + + if joint_solution is None: + print(f"❌ {point_name} 不可达") + continue + else: + print(f"✅ {point_name} 可达,关节解: {[f'{x:.3f}' for x in joint_solution]}") + + # 验证:使用求得的关节配置计算正向运动学 + verify_pos, verify_ori = arm_controller.forward_kinematics(joint_solution) + target_error = np.linalg.norm(np.array(verify_pos) - np.array(target_pos)) + print(f" 验证位置: {[f'{x:.3f}' for x in verify_pos]}") + print(f" 目标误差: {target_error:.4f} 米") + + if target_error > 0.01: + print(f" ⚠️ 逆运动学验证失败,误差过大") + else: + print(f" ✅ 逆运动学验证通过") + + print("\n=== 路径执行测试模拟 ===") + + # 测试6:模拟路径执行中的坐标转换 + test_joint_config = current_joints.copy() + test_joint_config[0] += 0.1 # 微调第一个关节 + + print(f"测试关节配置(KDL顺序): {[f'{x:.3f}' for x in test_joint_config]}") + + # 计算预期末端位置(通过KDL) + expected_pos, _ = arm_controller.forward_kinematics(test_joint_config) + print(f"KDL计算预期末端位置: {[f'{x:.3f}' for x in expected_pos]}") + + # 模拟路径执行器的关节设置 + arm_controller.set_joint_positions(test_joint_config) + + # 等待仿真稳定 + for _ in range(100): + p.stepSimulation(physicsClientId=physics_client) + + # 检查实际到达的位置 + actual_joints = arm_controller.get_current_joint_positions() + actual_pos, _ = arm_controller.get_current_pose() + + print(f"实际关节位置(KDL顺序): {[f'{x:.3f}' for x in actual_joints]}") + print(f"实际末端位置: {[f'{x:.3f}' for x in actual_pos]}") + + # 分析执行误差 + joint_error = np.linalg.norm(np.array(test_joint_config) - np.array(actual_joints)) + pos_error = np.linalg.norm(np.array(expected_pos) - np.array(actual_pos)) + + print(f"关节执行误差: {joint_error:.4f} rad") + print(f"位置执行误差: {pos_error:.4f} 米") + + if pos_error > 0.05: # 5cm tolerance + print("❌ 发现路径执行误差,坐标转换存在问题") + else: + print("✅ 路径执行精度良好") + + except Exception as e: + print(f"调试过程中发生错误: {e}") + import traceback + traceback.print_exc() + + finally: + p.disconnect(physicsClientId=physics_client) + +if __name__ == "__main__": + debug_coordinates() \ No newline at end of file diff --git a/debug_execution.py b/debug_execution.py new file mode 100644 index 0000000..ad53606 --- /dev/null +++ b/debug_execution.py @@ -0,0 +1,230 @@ +#!/usr/bin/env python3 +""" +路径执行调试脚本 +专门测试路径执行过程中的坐标对应关系 +""" + +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +from src.config_loader import ConfigLoader +from src.robot.arm_controller import create_arm_controller +from src.simulation.environment import Environment +from src.planning.ai_rrt_star import AIRRTStarPlanner +from src.planning.collision_checker import CollisionChecker +from src.planning.path_executor import PathExecutor +import pybullet as p +import pybullet_data +import numpy as np +import time + +def debug_path_execution(): + """调试路径执行的具体步骤""" + print("=== 路径执行调试分析 ===") + + # 初始化仿真 + physics_client = p.connect(p.GUI) + p.setAdditionalSearchPath(pybullet_data.getDataPath()) + p.setGravity(0, 0, 0) # 关闭重力 + + try: + # 加载配置和组件 + config_loader = ConfigLoader() + arm_controller = create_arm_controller(config_loader, physics_client) + environment = Environment(config_loader, physics_client) + collision_checker = CollisionChecker(arm_controller, environment, config_loader) + path_executor = PathExecutor(arm_controller, config_loader) + + print("=== 步骤1: 生成简单测试路径 ===") + + # 获取当前位置 + current_joints = arm_controller.get_current_joint_positions() + print(f"起始关节配置: {[f'{x:.3f}' for x in current_joints]}") + + # 计算当前末端位置 + current_pos, current_ori = arm_controller.forward_kinematics(current_joints) + print(f"起始末端位置: {[f'{x:.3f}' for x in current_pos]}") + + # 生成一个简单的测试路径:只修改第一个关节 + test_path = [] + for i in range(5): # 5个路径点 + test_config = current_joints.copy() + test_config[0] += i * 0.2 # 每步增加0.2弧度 + test_path.append(test_config) + + print(f"测试路径包含 {len(test_path)} 个waypoint") + + print("\n=== 步骤2: 分析路径的理论末端位置 ===") + theoretical_positions = [] + for i, config in enumerate(test_path): + pos, ori = arm_controller.forward_kinematics(config) + theoretical_positions.append(pos) + print(f"Waypoint {i}: 关节{config[0]:.3f} -> 末端位置{[f'{x:.3f}' for x in pos]}") + + print("\n=== 步骤3: 可视化理论路径 ===") + # 绘制理论路径线条 + line_ids = [] + for i in range(len(theoretical_positions) - 1): + line_id = p.addUserDebugLine( + theoretical_positions[i], + theoretical_positions[i + 1], + lineColorRGB=[0, 1, 0], # 绿色 - 理论路径 + lineWidth=3, + physicsClientId=physics_client + ) + line_ids.append(line_id) + + print("\n=== 步骤4: 执行路径并记录实际位置 ===") + actual_positions = [] + + # 重置机械臂到起始位置 + arm_controller.set_joint_positions(current_joints) + for _ in range(50): # 等待稳定 + p.stepSimulation(physicsClientId=physics_client) + + # 模拟主程序的路径执行器插值方式 + timestep = 0.01 # 和主程序相同的timestep + velocity_scaling = 1.0 # 和主程序默认值相同 + position_tolerance = 0.01 # 和主程序默认值相同 + + for i, target_config in enumerate(test_path): + print(f"\n--- 执行Waypoint {i} (模拟路径执行器插值) ---") + print(f"目标关节配置: {[f'{x:.3f}' for x in target_config]}") + + # 计算理论末端位置 + theoretical_pos, _ = arm_controller.forward_kinematics(target_config) + print(f"理论末端位置: {[f'{x:.3f}' for x in theoretical_pos]}") + + # === 模拟路径执行器的插值过程 === + current_config = arm_controller.get_current_joint_positions() + + # 计算距离和插值步数 + distance = np.linalg.norm(np.array(target_config) - np.array(current_config)) + move_time = distance / velocity_scaling + num_steps = int(move_time / timestep) + 1 + + print(f" 插值参数: 距离{distance:.4f}, 移动时间{move_time:.3f}s, 插值步数{num_steps}") + + # 执行插值 + for step in range(1, num_steps + 1): + ratio = step / num_steps + interpolated = ( + np.array(current_config) * (1 - ratio) + + np.array(target_config) * ratio + ) + + # 设置插值位置 + arm_controller.set_joint_positions(interpolated.tolist()) + + # 等待timestep时间(和主程序相同) + time.sleep(timestep) + + # 记录状态(每10步一次) + if step % max(1, num_steps // 5) == 0: + actual_joints = arm_controller.get_current_joint_positions() + actual_pos, _ = arm_controller.get_current_pose() + + interp_error = np.linalg.norm(interpolated - np.array(actual_joints)) + pos_error = np.linalg.norm(np.array(theoretical_pos) - np.array(actual_pos)) + + print(f" 插值步{step}/{num_steps}: 插值误差{interp_error:.4f}, 位置误差{pos_error:.4f}") + + # 最终设置目标位置 + arm_controller.set_joint_positions(target_config) + + # 等待收敛(和主程序相同的逻辑) + wait_start = time.time() + max_wait = max(timestep * 10, move_time * 2) + final_converged = False + + while time.time() - wait_start < max_wait: + final_config = arm_controller.get_current_joint_positions() + final_distance = np.linalg.norm(np.array(target_config) - np.array(final_config)) + + if final_distance <= position_tolerance: + final_converged = True + break + time.sleep(timestep) + + # 记录最终实际位置 + final_joints = arm_controller.get_current_joint_positions() + final_pos, _ = arm_controller.get_current_pose() + actual_positions.append(final_pos) + + final_joint_error = np.linalg.norm(np.array(target_config) - np.array(final_joints)) + final_pos_error = np.linalg.norm(np.array(theoretical_pos) - np.array(final_pos)) + + print(f"最终关节位置: {[f'{x:.3f}' for x in final_joints]}") + print(f"最终末端位置: {[f'{x:.3f}' for x in final_pos]}") + print(f"最终关节误差: {final_joint_error:.4f}") + print(f"最终位置误差: {final_pos_error:.4f}") + + if final_pos_error > 0.02: # 2cm容差 + print(f"⚠️ Waypoint {i} 存在显著位置误差!") + + print("\n=== 步骤5: 绘制实际执行路径 ===") + # 绘制实际执行路径 + for i in range(len(actual_positions) - 1): + line_id = p.addUserDebugLine( + actual_positions[i], + actual_positions[i + 1], + lineColorRGB=[1, 0, 0], # 红色 - 实际路径 + lineWidth=3, + physicsClientId=physics_client + ) + line_ids.append(line_id) + + print("\n=== 步骤6: 对比分析 ===") + total_theoretical_length = 0 + total_actual_length = 0 + max_waypoint_error = 0 + + for i in range(len(test_path)): + theoretical_pos = theoretical_positions[i] + actual_pos = actual_positions[i] + waypoint_error = np.linalg.norm(np.array(theoretical_pos) - np.array(actual_pos)) + max_waypoint_error = max(max_waypoint_error, waypoint_error) + + print(f"Waypoint {i}:") + print(f" 理论: {[f'{x:.3f}' for x in theoretical_pos]}") + print(f" 实际: {[f'{x:.3f}' for x in actual_pos]}") + print(f" 误差: {waypoint_error:.4f}m") + + if i > 0: + theoretical_segment = np.linalg.norm( + np.array(theoretical_positions[i]) - np.array(theoretical_positions[i-1]) + ) + actual_segment = np.linalg.norm( + np.array(actual_positions[i]) - np.array(actual_positions[i-1]) + ) + total_theoretical_length += theoretical_segment + total_actual_length += actual_segment + + print(f"\n总结:") + print(f"理论路径长度: {total_theoretical_length:.4f}m") + print(f"实际路径长度: {total_actual_length:.4f}m") + print(f"路径长度差异: {abs(total_theoretical_length - total_actual_length):.4f}m") + print(f"最大waypoint误差: {max_waypoint_error:.4f}m") + + if max_waypoint_error > 0.02: + print("❌ 发现显著的路径执行误差") + else: + print("✅ 路径执行精度良好") + + print(f"\n绿色线条 = 理论路径(基于正向运动学)") + print(f"红色线条 = 实际执行路径(基于实际机械臂位置)") + print(f"如果两条线重合,说明路径执行准确") + + input("按回车键关闭...") + + except Exception as e: + print(f"调试过程中发生错误: {e}") + import traceback + traceback.print_exc() + + finally: + p.disconnect(physicsClientId=physics_client) + +if __name__ == "__main__": + debug_path_execution() \ No newline at end of file diff --git a/src/gui/main_window.py b/src/gui/main_window.py index ca5141f..f1bb256 100644 --- a/src/gui/main_window.py +++ b/src/gui/main_window.py @@ -20,6 +20,15 @@ from src.planning.collision_checker import CollisionChecker from src.planning.path_optimizer import PathOptimizer from src.planning.path_executor import PathExecutor +# GUI设置 +DEFAULT_WINDOW_SIZE = "1200x800" + +# 相机默认设置 +DEFAULT_CAMERA_DISTANCE = 4.0 +DEFAULT_CAMERA_YAW = 45 +DEFAULT_CAMERA_PITCH = -30 +DEFAULT_CAMERA_TARGET = [0, 0, 0] + class MainWindow: def __init__(self): @@ -56,16 +65,8 @@ class MainWindow: self.initialize_simulation() def _setup_window_geometry(self): - """Setup window geometry from config or defaults""" - try: - # Try to load from config if exists - config = ConfigLoader().get_full_config() - window_size = config.get('gui', {}).get('window_size', "1200x800") - self.root.geometry(window_size) - except Exception as e: - # Use config default if loading fails - default_config = {"gui": {"window_size": "1200x800"}} - self.root.geometry(default_config['gui']['window_size']) + """Setup window geometry from defaults""" + self.root.geometry(DEFAULT_WINDOW_SIZE) def _create_control_panel(self): """Create control panel on the left side""" @@ -739,18 +740,13 @@ class MainWindow: self.update_status(f"Path visualization failed: {e}") def _reset_camera_view(self): - """Reset camera to default view using config values""" + """Reset camera to default view""" try: - # Get camera settings from config - config = self.config_loader.get_full_config() if self.config_loader else {} - camera_config = config.get('camera', {}) - - # Use config values with explicit defaults from config structure - default_camera = {'distance': 4.0, 'yaw': 45, 'pitch': -30, 'target': [0, 0, 0]} - distance = camera_config.get('distance', default_camera['distance']) - yaw = camera_config.get('yaw', default_camera['yaw']) - pitch = camera_config.get('pitch', default_camera['pitch']) - target = camera_config.get('target', default_camera['target']) + # 使用文件内常量作为默认相机设置 + distance = DEFAULT_CAMERA_DISTANCE + yaw = DEFAULT_CAMERA_YAW + pitch = DEFAULT_CAMERA_PITCH + target = DEFAULT_CAMERA_TARGET p.resetDebugVisualizerCamera( cameraDistance=distance, diff --git a/src/planning/ai_rrt_star.py b/src/planning/ai_rrt_star.py index efb4dff..abca813 100644 --- a/src/planning/ai_rrt_star.py +++ b/src/planning/ai_rrt_star.py @@ -5,7 +5,6 @@ AI-Enhanced RRT* Path Planner AI增强的RRT*路径规划器,通过智能采样、自适应参数和启发式引导 提升路径规划效率和成功率,特别优化洞口穿越场景。 -配置驱动:所有参数从config.json读取 错误处理:失败立即抛出异常,无后备方案 """ @@ -17,6 +16,15 @@ import math from .collision_checker import CollisionChecker from .hole_crossing import HoleCrossingStrategy +# RRT*算法参数 +ENABLED = True +MAX_ITERATIONS = 5000 +STEP_SIZE = 0.1 +GOAL_SAMPLE_RATE = 0.15 +SEARCH_RADIUS = 0.5 +HOLE_BIAS_RATE = 0.3 +ENFORCE_HOLE_CROSSING = False + class TreeNode: """RRT*树节点""" @@ -39,10 +47,10 @@ class TreeNode: class AdaptiveParameters: """自适应参数管理器""" - def __init__(self, config: Dict[str, Any]): - self.step_size = config['step_size'] - self.goal_sample_rate = config['goal_sample_rate'] - self.search_radius = config['search_radius'] + def __init__(self): + self.step_size = STEP_SIZE + self.goal_sample_rate = GOAL_SAMPLE_RATE + self.search_radius = SEARCH_RADIUS self.iteration_count = 0 self.success_count = 0 self.failure_count = 0 @@ -100,15 +108,11 @@ class AIRRTStarPlanner: self.environment = environment self.config_loader = config_loader - # 从配置读取参数 - config = config_loader.get_full_config() - self.rrt_config = config['path_planning']['ai_rrt_star'] - - # 初始化参数 - self.max_iterations = self.rrt_config['max_iterations'] - self.params = AdaptiveParameters(self.rrt_config) + # 初始化参数(使用文件内常量) + self.max_iterations = MAX_ITERATIONS + self.params = AdaptiveParameters() # 是否强制穿洞(默认否) - self.enforce_hole = self.rrt_config.get('enforce_hole_crossing', False) + self.enforce_hole = ENFORCE_HOLE_CROSSING # 初始化组件 if collision_checker is None: diff --git a/src/planning/hole_crossing.py b/src/planning/hole_crossing.py index 5a8bfd4..a4c02d0 100644 --- a/src/planning/hole_crossing.py +++ b/src/planning/hole_crossing.py @@ -4,14 +4,15 @@ Hole Crossing Strategy Module 洞口穿越策略模块,提供专门的洞口穿越路径规划策略。 包括偏向采样、关键路径点生成、分阶段规划等功能。 - -配置驱动设计,所有参数从config.json读取。 """ import numpy as np from typing import List, Tuple, Dict, Any, Optional import random +# 洞口穿越策略参数 +HOLE_BIAS_RATE = 0.3 + class HoleCrossingStrategy: """洞口穿越策略""" @@ -29,9 +30,8 @@ class HoleCrossingStrategy: self.environment = environment self.config_loader = config_loader - # 从配置读取参数 - config = config_loader.get_full_config() - self.hole_bias_rate = config['path_planning']['ai_rrt_star']['hole_bias_rate'] + # 洞口策略参数(使用文件内常量) + self.hole_bias_rate = HOLE_BIAS_RATE # 获取洞口信息 self.hole_info = self.environment.get_hole_info() diff --git a/src/planning/path_optimizer.py b/src/planning/path_optimizer.py index 0aa2032..bf9a196 100644 --- a/src/planning/path_optimizer.py +++ b/src/planning/path_optimizer.py @@ -5,13 +5,16 @@ Path Optimizer Module 路径优化模块,对RRT*生成的路径进行平滑和优化。 包括路径简化、平滑处理、速度规划等功能。 -配置驱动:所有参数从config.json读取 错误处理:失败立即抛出异常,无后备方案 """ import numpy as np from typing import List, Tuple, Optional, Dict, Any +# 路径优化参数 +SHORTCUT_ITERATIONS = 50 +SMOOTHING_FACTOR = 0.5 + class PathOptimizer: """路径优化器""" @@ -27,18 +30,16 @@ class PathOptimizer: self.arm_controller = arm_controller self.config_loader = config_loader - # 从配置读取优化参数 - config = config_loader.get_full_config() - optimization_config = config['path_planning']['optimization'] - self.shortcut_iterations = optimization_config['shortcut_iterations'] - self.smoothing_factor = optimization_config['smoothing_factor'] + # 优化参数(使用文件内常量) + self.shortcut_iterations = SHORTCUT_ITERATIONS + self.smoothing_factor = SMOOTHING_FACTOR - # 从配置读取执行参数 + # 从配置读取跨文件共享参数 + config = config_loader.get_full_config() execution_config = config['path_planning']['execution'] self.velocity_scaling = execution_config['velocity_scaling'] self.position_tolerance = execution_config['position_tolerance'] - # 从配置读取碰撞检测参数 collision_config = config['path_planning']['collision'] self.check_resolution = collision_config['check_resolution'] diff --git a/src/robot/kinematics.py b/src/robot/kinematics.py index 6180397..af19a9e 100644 --- a/src/robot/kinematics.py +++ b/src/robot/kinematics.py @@ -13,12 +13,16 @@ from urdf_parser_py.urdf import URDF import sys import os +# 运动学求解参数 +MAX_ITERATIONS = 1500 +EPSILON = 1e-05 + class KinematicsEngine: """KDL-based kinematics engine for robot arm calculations""" def __init__(self, urdf_path: str, base_position: List[float] = None, - base_orientation: List[float] = None, kinematics_config: dict = None): + base_orientation: List[float] = None): """Initialize KDL kinematics engine from URDF file""" self.urdf_path = urdf_path self.base_link: Optional[str] = None @@ -30,11 +34,9 @@ class KinematicsEngine: self._base_to_world_frame = self._create_transform_frame(self.base_position, self.base_orientation) self._world_to_base_frame = self._base_to_world_frame.Inverse() - # Kinematics configuration - 必须提供 - if kinematics_config is None: - raise ValueError("kinematics_config is required") - self.max_iterations = kinematics_config['max_iterations'] - self.epsilon = kinematics_config['epsilon'] + # 运动学配置(使用文件内常量) + self.max_iterations = MAX_ITERATIONS + self.epsilon = EPSILON # KDL components self.chain: Optional[kdl.Chain] = None @@ -396,7 +398,4 @@ def create_kinematics_engine(config_loader) -> KinematicsEngine: base_position = robot_config.get('base_position', [0.0, 0.0, 0.0]) base_orientation = robot_config.get('base_orientation', [0.0, 0.0, 0.0]) - # Get kinematics config - kinematics_config = config_loader.get_full_config()['kinematics'] - - return KinematicsEngine(urdf_path, base_position, base_orientation, kinematics_config) + return KinematicsEngine(urdf_path, base_position, base_orientation)