#!/usr/bin/env python3 """ 调试航向控制的符号定义 根据实际IMU定义:GyroZ正值 = 顺时针(CW) = 右转 = 罗盘角增加 """ import math # 从log中提取的数据 pos_x, pos_y = 1.89, -2.81 # ENU坐标 tgt_x, tgt_y = 5.40, -7.17 current_hdg_compass = 308.13 # 罗盘角度 turn_output = 0.80 # log中显示的turn值(正值) print("=" * 60) print("实际测试数据分析") print("=" * 60) print(f"当前位置(ENU): ({pos_x:.2f}, {pos_y:.2f})") print(f"目标位置(ENU): ({tgt_x:.2f}, {tgt_y:.2f})") print(f"当前航向(罗盘): {current_hdg_compass:.1f}°") print(f"Log显示turn: {turn_output:.2f} (正值)") print() # 1. 计算目标航向 dx = tgt_x - pos_x # 东方向 dy = tgt_y - pos_y # 北方向 dist = math.sqrt(dx**2 + dy**2) target_math_rad = math.atan2(dy, dx) target_math_deg = math.degrees(target_math_rad) # 转换为罗盘角度 target_compass_deg = 90.0 - target_math_deg if target_compass_deg < 0: target_compass_deg += 360 if target_compass_deg >= 360: target_compass_deg -= 360 print("=" * 60) print("步骤1: 计算目标航向") print("=" * 60) print(f"位移向量: dx={dx:.2f}m(东), dy={dy:.2f}m(北), dist={dist:.2f}m") print(f"目标航向(数学坐标系): {target_math_deg:.1f}° = {target_math_rad:.3f} rad") print(f"目标航向(罗盘坐标系): {target_compass_deg:.1f}°") print() # 2. 模拟motion_control.c中的转换 # mc_compass_deg_to_math_rad: math_deg = 90.0f - heading_deg current_math_deg = 90.0 - current_hdg_compass current_math_rad = math.radians(current_math_deg) # 归一化到-π~π def wrap_angle(angle_rad): while angle_rad > math.pi: angle_rad -= 2 * math.pi while angle_rad < -math.pi: angle_rad += 2 * math.pi return angle_rad current_math_rad = wrap_angle(current_math_rad) target_math_rad_wrapped = wrap_angle(target_math_rad) print("=" * 60) print("步骤2: 罗盘角→数学坐标系(motion_control.c第114行)") print("=" * 60) print(f"math_deg = 90.0 - heading_deg = 90.0 - {current_hdg_compass:.1f} = {current_math_deg:.1f}°") print(f"current_math_rad = {current_math_rad:.3f} rad = {math.degrees(current_math_rad):.1f}°") print(f"target_math_rad = {target_math_rad_wrapped:.3f} rad = {math.degrees(target_math_rad_wrapped):.1f}°") print() # 3. 计算航向误差(数学坐标系) heading_err_rad = target_math_rad_wrapped - current_math_rad heading_err_rad = wrap_angle(heading_err_rad) heading_err_deg = math.degrees(heading_err_rad) print("=" * 60) print("步骤3: 计算航向误差(motion_control.c第43行)") print("=" * 60) print(f"heading_err = target - current") print(f" = {target_math_rad_wrapped:.3f} - {current_math_rad:.3f}") print(f" = {heading_err_rad:.3f} rad") print(f" = {heading_err_deg:.1f}°") if heading_err_rad > 0: print("误差为正 → 数学坐标系中需要逆时针转(CCW)") print(" → 罗盘坐标系中需要顺时针转(从西北转向东南)") else: print("误差为负 → 数学坐标系中需要顺时针转(CW)") print(" → 罗盘坐标系中需要逆时针转") print() # 4. 计算yaw_rate_cmd(假设Kp=1,简化) Kp = 1.0 max_turn_rate = 0.8 yaw_rate_cmd = Kp * heading_err_rad yaw_rate_cmd = max(-max_turn_rate, min(max_turn_rate, yaw_rate_cmd)) print("=" * 60) print("步骤4: 计算yaw_rate_cmd(motion_control.c第247行)") print("=" * 60) print(f"yaw_rate_cmd = Kp × heading_err") print(f" = {Kp:.1f} × {heading_err_rad:.3f}") print(f" = {yaw_rate_cmd:.3f} rad/s") print(f"限制到±{max_turn_rate}: yaw_rate_cmd = {yaw_rate_cmd:.3f} rad/s") print() # 5. motion_control.c第548行:取反 turn_rate_before_invert = yaw_rate_cmd turn_rate_after_invert = -yaw_rate_cmd print("=" * 60) print("步骤5: 第548行取反(motion_control.c)") print("=" * 60) print(f"_out->turn_rate = -yaw_rate_cmd") print(f" = -{yaw_rate_cmd:.3f}") print(f" = {turn_rate_after_invert:.3f} rad/s") print() # 6. 对比log中的值 print("=" * 60) print("步骤6: 对比实际log输出") print("=" * 60) print(f"计算的turn_rate: {turn_rate_after_invert:.3f} rad/s") print(f"Log显示turn: {turn_output:.2f} rad/s") print() if (turn_rate_after_invert > 0 and turn_output > 0) or (turn_rate_after_invert < 0 and turn_output < 0): print("✓ 符号一致") else: print("✗ 符号不一致!需要检查代码") print() # 7. PWM映射分析 print("=" * 60) print("步骤7: PWM映射(motion_control_task.c第469-487行)") print("=" * 60) print("注释说:正值=左转,负值=右转") print(f"turn_rate = {turn_rate_after_invert:.3f} rad/s") if turn_rate_after_invert > 0: print("→ 正值 → 应该左转(逆时针,罗盘角减少)") print("→ PWM < 1500") elif turn_rate_after_invert < 0: print("→ 负值 → 应该右转(顺时针,罗盘角增加)") print("→ PWM > 1500") print() # 8. 实际车辆行为 print("=" * 60) print("步骤8: 实际车辆行为") print("=" * 60) print(f"Log显示航向从308°增加到344° → 顺时针转(右转)") print(f"目标航向141°") print(f"正确的转向:308° → 逆时针 → 141°(转167°)") print(f"实际转向:顺时针转") print() print("结论:转向方向反了!") print() # 9. 问题诊断 print("=" * 60) print("问题诊断") print("=" * 60) print("可能的原因:") print("1. 第548行的取反导致符号错误") print("2. PWM映射的符号定义与注释不符") print("3. 航向误差计算有问题") print() print("建议:") print("1. 去掉motion_control.c第548行的取反") print("2. 或者修改motion_control_task.c的PWM映射符号") print("3. 或者检查mc_compass_deg_to_math_rad转换是否正确")