在 move_base_hori_line.py 中新增 go_straight_by_hori_line 函数,封装了基于横向线的直线移动逻辑。更新 task_1.py 以集成新功能,优化任务执行流程,增强 QR 码扫描的处理和结果返回格式,提升代码可读性和可维护性。

This commit is contained in:
Havoc 2025-05-17 19:21:32 +08:00
parent 6d41ffa96c
commit d7675093d1
2 changed files with 105 additions and 74 deletions

View File

@ -8,6 +8,7 @@ import os
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from utils.detect_track import detect_horizontal_track_edge
from base_move.turn_degree import turn_degree
from base_move.go_straight import go_straight
from utils.log_helper import LogHelper, get_logger, section, info, debug, warning, error, success, timing
# 创建此模块特定的日志记录器
@ -206,6 +207,29 @@ def calculate_distance_to_line(edge_info, camera_height, camera_tilt_angle_deg=0
return final_distance
def go_straight_by_hori_line(ctrl, msg, distance=0.5, speed=0.5, observe=False):
"""
根据横向线位置控制机器人移动到指定距离
# INFO 本质就是封装了一下 go-straight但是需要先校准到水平
参数:
ctrl: Robot_Ctrl 对象包含里程计信息
msg: robot_control_cmd_lcmt 对象用于发送命令
distance: 目标位置与横向线的距离()默认为0.5
speed: 移动速度(/)默认为0.5/
observe: 是否输出中间状态信息和可视化结果默认为False
"""
# 首先校准到水平
section("校准到横向线水平", "校准")
aligned = align_to_horizontal_line(ctrl, msg, observe=observe)
if not aligned:
error("无法校准到横向线水平,停止移动", "停止")
return False
go_straight(ctrl, msg, distance=distance, speed=speed, observe=observe)
def move_to_hori_line(ctrl, msg, target_distance=0.5, observe=False):
"""
控制机器人校准并移动到横向线前的指定距离
@ -379,8 +403,8 @@ def arc_turn_around_hori_line(ctrl, msg, angle_deg=90, left=True, target_distanc
error("无法校准到横向线水平,停止动作", "停止")
if scan_qrcode:
ctrl.image_processor.stop_async_scan()
return False, None
return False
return False, res
return False, res
else:
info("跳过对准步骤", "信息")
@ -391,8 +415,8 @@ def arc_turn_around_hori_line(ctrl, msg, angle_deg=90, left=True, target_distanc
error("无法检测到横向线,停止动作", "停止")
if scan_qrcode:
ctrl.image_processor.stop_async_scan()
return False, qr_result
return False
return False, res
return False, res
camera_height = 0.355 # 单位: 米
r = calculate_distance_to_line(edge_info, camera_height, observe=observe)
@ -400,25 +424,17 @@ def arc_turn_around_hori_line(ctrl, msg, angle_deg=90, left=True, target_distanc
error("无法计算到横向线的距离,停止动作", "停止")
if scan_qrcode:
ctrl.image_processor.stop_async_scan()
return False, qr_result
return False
return False, res
return False, res
# 减去目标距离
# 减去目标距离
r -= target_distance
res['radius'] = r
if observe:
info(f"当前距离: {r:.3f}", "距离")
# 3. 计算圆弧运动参数
# 根据角度大小调整时间补偿系数
if angle_deg <= 70:
time_compensation = 0.78 # 对70度及以下角度使用更小的补偿系数
elif angle_deg <= 90:
time_compensation = 0.85 # 90度左右使用稍大的系数
else:
# 对180度旋转增加补偿系数使旋转时间更长
time_compensation = 1.4 # 增加40%的时间
# 调整实际目标角度,针对不同角度应用不同的缩放比例
actual_angle_deg = angle_deg
if angle_deg <= 70:
@ -430,16 +446,11 @@ def arc_turn_around_hori_line(ctrl, msg, angle_deg=90, left=True, target_distanc
if observe and actual_angle_deg != angle_deg:
info(f"应用角度补偿: 目标{angle_deg}度 -> 实际指令{actual_angle_deg:.1f}", "角度")
angle_rad = math.radians(actual_angle_deg)
# 设定角速度rad/s可根据实际调整
# 减小基础角速度,增加精度
# if angle_deg >= 170:
# base_w = 0.5 # 大角度旋转时使用更小的基础角速度,提高精度
# else:
base_w = 0.8 # 原来是0.6
base_w = 0.8
w = base_w if left else -base_w # 左转为正,右转为负
# 确保r有一个最小值避免速度过低
@ -456,12 +467,9 @@ def arc_turn_around_hori_line(ctrl, msg, angle_deg=90, left=True, target_distanc
t = abs(angle_rad / w) # 运动时间,取绝对值保证为正
# 应用时间补偿系数
t *= time_compensation
if observe:
debug(f"圆弧半径: {effective_r:.3f}米, 角速度: {w:.3f}rad/s, 线速度: {v:.3f}m/s", "计算")
debug(f"理论运动时间: {abs(angle_rad / w):.2f}s, 应用补偿系数{time_compensation}后: {t:.2f}s", "时间")
debug(f"理论运动时间: {t:.2f}s", "时间")
# 4. 发送圆弧运动指令
msg.mode = 11
@ -477,41 +485,36 @@ def arc_turn_around_hori_line(ctrl, msg, angle_deg=90, left=True, target_distanc
start_yaw = ctrl.odo_msg.rpy[2]
start_position = list(ctrl.odo_msg.xyz)
# 在起点放置蓝色标记
# TEST 获取当前姿态
yaw = ctrl.odo_msg.rpy[2]
ctrl.place_marker(start_position[0], start_position[1],
start_position[2] if len(start_position) > 2 else 0.0,
'blue', observe=True)
info(f"在起点位置放置蓝色标记: {start_position}", "位置")
# DEBUG 在起点放置蓝色标记
if observe:
yaw = ctrl.odo_msg.rpy[2]
ctrl.place_marker(start_position[0], start_position[1],
start_position[2] if len(start_position) > 2 else 0.0,
'blue', observe=True)
info(f"在起点位置放置蓝色标记: {start_position}", "位置")
# 计算圆心位置 - 相对于机器人前进方向的左侧或右侧
# 圆心与机器人当前位置的距离就是圆弧半径
center_x = start_position[0] - effective_r * math.sin(yaw) * (1 if left else -1)
center_y = start_position[1] + effective_r * math.cos(yaw) * (1 if left else -1)
center_z = start_position[2] if len(start_position) > 2 else 0.0
# 计算圆心位置 - 相对于机器人前进方向的左侧或右侧
# 圆心与机器人当前位置的距离就是圆弧半径
center_x = start_position[0] - effective_r * math.sin(yaw) * (1 if left else -1)
center_y = start_position[1] + effective_r * math.cos(yaw) * (1 if left else -1)
center_z = start_position[2] if len(start_position) > 2 else 0.0
# 在圆心放置绿色标记
if observe and hasattr(ctrl, 'place_marker'):
# 在圆心放置绿色标记
ctrl.place_marker(center_x, center_y, center_z, 'green', observe=True)
info(f"在旋转圆心放置绿色标记: [{center_x:.3f}, {center_y:.3f}, {center_z:.3f}]", "位置")
# 计算目标点的位置 - 旋转后的位置
# 使用几何关系目标点是从起点绕圆心旋转angle_rad弧度后的位置
target_angle = yaw + (angle_rad if left else -angle_rad)
# 计算从圆心到目标点的向量
target_x = center_x + effective_r * math.sin(target_angle) * (1 if left else -1)
target_y = center_y - effective_r * math.cos(target_angle) * (1 if left else -1)
target_z = start_position[2] if len(start_position) > 2 else 0.0
# 在目标点放置红色标记
if observe and hasattr(ctrl, 'place_marker'):
# 计算目标点的位置 - 旋转后的位置
# 使用几何关系目标点是从起点绕圆心旋转angle_rad弧度后的位置
target_angle = yaw + (angle_rad if left else -angle_rad)
# 计算从圆心到目标点的向量
target_x = center_x + effective_r * math.sin(target_angle) * (1 if left else -1)
target_y = center_y - effective_r * math.cos(target_angle) * (1 if left else -1)
target_z = start_position[2] if len(start_position) > 2 else 0.0
# 在目标点放置红色标记
ctrl.place_marker(target_x, target_y, target_z, 'red', observe=True)
info(f"在目标位置放置红色标记: [{target_x:.3f}, {target_y:.3f}, {target_z:.3f}]", "位置")
# 计算圆弧长度
arc_length = abs(angle_rad * effective_r)
# 进入循环,实时判断
distance_moved = 0
angle_turned = 0
@ -700,10 +703,10 @@ def arc_turn_around_hori_line(ctrl, msg, angle_deg=90, left=True, target_distanc
if observe:
info(f"旋转过程结束,当前速度: [{current_v:.3f}, 0, {current_w:.3f}]", "停止")
debug(f'{math.degrees(ctrl.odo_msg.rpy[2]):.2f}°', "角度")
debug(f'旋转结束角度: {math.degrees(ctrl.odo_msg.rpy[2]):.2f}°', "角度")
ctrl.base_msg.stop()
if observe:
debug(f'{math.degrees(ctrl.odo_msg.rpy[2]):.2f}°', "角度")
debug(f'停止角度: {math.degrees(ctrl.odo_msg.rpy[2]):.2f}°', "角度")
# 记录停止前的角度
pre_stop_yaw = ctrl.odo_msg.rpy[2]
@ -737,6 +740,7 @@ def arc_turn_around_hori_line(ctrl, msg, angle_deg=90, left=True, target_distanc
final_angle_turned += 2 * math.pi
final_angle_deg = math.degrees(final_angle_turned)
# 这里使用原始目标角度进行比较
if not bad_big_angle_corret:
target_angle_deg = angle_deg if left else -angle_deg
@ -846,15 +850,15 @@ def arc_turn_around_hori_line(ctrl, msg, angle_deg=90, left=True, target_distanc
# 停止异步扫描
ctrl.image_processor.stop_async_scan()
# 将QR码结果添加到res字典中
res['qr_result'] = qr_result
if observe:
success("圆弧转弯完成", "完成")
# 根据scan_qrcode参数返回不同格式的结果
if scan_qrcode:
return True, qr_result
else:
return True
# 统一返回结果格式
return True, res
# 用法示例
if __name__ == "__main__":

View File

@ -5,10 +5,13 @@ import math
# 添加父目录到路径以便能够导入utils
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from base_move.move_base_hori_line import move_to_hori_line, arc_turn_around_hori_line, align_to_horizontal_line
from utils.detect_track import detect_horizontal_track_edge
from base_move.move_base_hori_line import calculate_distance_to_line
from base_move.move_base_hori_line import (
arc_turn_around_hori_line,
go_straight_by_hori_line,
move_to_hori_line
)
from base_move.go_straight import go_straight
from base_move.turn_degree import turn_degree
from utils.log_helper import LogHelper, get_logger, section, info, debug, warning, error, success, timing
# 创建本模块特定的日志记录器
@ -23,7 +26,7 @@ def run_task_1(ctrl, msg):
# v2
section('任务1-1转弯并扫描QR码', "移动")
# 在 arc_turn_around_hori_line 中启用 QR 码扫描
turn_success, qr_result = arc_turn_around_hori_line(
success, res = arc_turn_around_hori_line(
ctrl=ctrl,
msg=msg,
angle_deg=85,
@ -33,8 +36,8 @@ def run_task_1(ctrl, msg):
qr_check_interval=0.3 # 每 0.3 秒检查一次扫描结果
)
if qr_result:
success(f"在任务1-1中成功扫描到QR码: {qr_result}", "扫描")
if res and res['qr_result']:
success(f"在任务1-1中成功扫描到QR码: {res['qr_result']}", "扫描")
else:
warning("任务1-1中未能扫描到任何QR码", "警告")
@ -43,14 +46,13 @@ def run_task_1(ctrl, msg):
move_to_hori_line(ctrl, msg, target_distance=1, observe=observe)
section('任务1-3转弯', "旋转")
# direction = True if qr_result == 'A-1' else False
# TODO
turn_success = arc_turn_around_hori_line(
direction = True if res['qr_result'] == 'A-1' else False
success, res = arc_turn_around_hori_line(
ctrl=ctrl,
msg=msg,
angle_deg=170,
target_distance=0.4, # TODO 优化这里的参数
left=False, # direction,
left=direction,
pass_align=True,
observe=observe,
# TODO clear
@ -59,8 +61,11 @@ def run_task_1(ctrl, msg):
section('任务1-4直线移动', "移动")
move_distance = 0.4
go_straight(ctrl, msg, distance=move_distance, speed=0.5, observe=observe)
# move_to_hori_line(ctrl, msg, target_distance=0.6, observe=observe)
if direction:
# TODO 这里的校准不一定好用,需要优化
go_straight_by_hori_line(ctrl, msg, distance=move_distance, speed=0.5, observe=observe)
else:
go_straight(ctrl, msg, distance=move_distance, speed=0.5, observe=observe)
section('任务1-5模拟装货', "停止")
info('机器人躺下,模拟装货过程', "信息")
@ -74,7 +79,29 @@ def run_task_1(ctrl, msg):
ctrl.base_msg.stand_up()
section('任务1-6返回', "移动")
go_straight(ctrl, msg, distance=-move_distance + 0.1, speed=0.5, observe=observe)
go_straight(ctrl, msg, distance=-move_distance + res['radius'], speed=0.5, observe=observe)
go_straight(ctrl, msg, distance=-move_distance - res['radius'], speed=0.5, observe=observe)
# turn and back
turn_degree(ctrl, msg, degree=-90, absolute=True)
section('任务1-790度转弯', "旋转")
success, res = arc_turn_around_hori_line(
ctrl=ctrl,
msg=msg,
angle_deg=-85,
left=True,
observe=observe
)
section('任务1-8直线移动', "移动")
move_to_hori_line(ctrl, msg, target_distance=0.4, observe=observe)
section('任务1-990度旋转', "旋转")
turn_degree(ctrl, msg, degree=90, absolute=True)
section('任务1-10: y校准准备 task-2', "移动")
# TODO
success("任务1完成", "完成")