删除当前图像文件,优化 main.py 中的恢复站立逻辑,新增 lie_down 和 stand_up 方法到 BaseMsg 类,更新 task_1.py 以使用新的移动和休息功能。
This commit is contained in:
parent
35e8cc9858
commit
18248d7ad9
198
base_move/go_straight.py
Normal file
198
base_move/go_straight.py
Normal file
@ -0,0 +1,198 @@
|
||||
import math
|
||||
import time
|
||||
import sys
|
||||
import os
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
from utils.localization_lcmt import localization_lcmt
|
||||
|
||||
def go_straight(ctrl, msg, distance, speed=0.5, observe=False):
|
||||
"""
|
||||
控制机器人沿直线行走指定距离
|
||||
|
||||
参数:
|
||||
ctrl: Robot_Ctrl 对象,包含里程计信息
|
||||
msg: robot_control_cmd_lcmt 对象,用于发送命令
|
||||
distance: 要行走的距离(米),正值为前进,负值为后退
|
||||
speed: 行走速度(米/秒),范围0.1~1.0,默认为0.5
|
||||
observe: 是否输出中间状态信息,默认为False
|
||||
|
||||
返回:
|
||||
bool: 是否成功完成行走
|
||||
"""
|
||||
# 参数验证
|
||||
if abs(distance) < 0.01:
|
||||
print("距离太短,无需移动")
|
||||
return True
|
||||
|
||||
# 限制速度范围
|
||||
speed = min(max(abs(speed), 0.1), 1.0)
|
||||
|
||||
# 确定前进或后退方向
|
||||
forward = distance > 0
|
||||
move_speed = speed if forward else -speed
|
||||
abs_distance = abs(distance)
|
||||
|
||||
# 获取起始位置
|
||||
start_position = list(ctrl.odo_msg.xyz)
|
||||
start_yaw = ctrl.odo_msg.rpy[2] # 记录起始朝向,用于保持直线
|
||||
|
||||
if observe:
|
||||
print(f"起始位置: {start_position}")
|
||||
print(f"开始{'前进' if forward else '后退'} {abs_distance:.3f}米,速度: {abs(move_speed):.2f}米/秒")
|
||||
# 在起点放置标记
|
||||
if hasattr(ctrl, 'place_marker'):
|
||||
ctrl.place_marker(start_position[0], start_position[1],
|
||||
start_position[2] if len(start_position) > 2 else 0.0,
|
||||
'green', observe=True)
|
||||
|
||||
# 设置移动命令
|
||||
msg.mode = 11 # Locomotion模式
|
||||
msg.gait_id = 26 # 自变频步态
|
||||
|
||||
# 根据需要移动的距离动态调整移动速度
|
||||
if abs_distance > 1.0:
|
||||
actual_speed = move_speed # 距离较远时用设定速度
|
||||
elif abs_distance > 0.5:
|
||||
actual_speed = move_speed * 0.8 # 中等距离略微降速
|
||||
elif abs_distance > 0.2:
|
||||
actual_speed = move_speed * 0.6 # 较近距离降低速度
|
||||
else:
|
||||
actual_speed = move_speed * 0.4 # 非常接近时用更慢速度
|
||||
|
||||
# 设置移动速度和方向
|
||||
msg.vel_des = [actual_speed, 0, 0] # [前进速度, 侧向速度, 角速度]
|
||||
msg.duration = 0 # wait next cmd
|
||||
msg.step_height = [0.06, 0.06] # 抬腿高度
|
||||
msg.life_count += 1
|
||||
|
||||
# 发送命令
|
||||
ctrl.Send_cmd(msg)
|
||||
|
||||
# 估算移动时间,但实际上会通过里程计控制
|
||||
estimated_time = abs_distance / abs(actual_speed)
|
||||
timeout = estimated_time + 3 # 增加超时时间为预计移动时间加3秒
|
||||
|
||||
# 使用里程计进行实时监控移动距离
|
||||
distance_moved = 0
|
||||
start_time = time.time()
|
||||
last_position = start_position
|
||||
|
||||
# 动态调整参数
|
||||
angle_correction_threshold = 0.05 # 角度偏差超过多少弧度开始修正
|
||||
slow_down_ratio = 0.85 # 当移动到目标距离的85%时开始减速
|
||||
completion_threshold = 0.95 # 当移动到目标距离的95%时停止
|
||||
position_check_interval = 0.1 # 位置检查间隔(秒)
|
||||
last_check_time = start_time
|
||||
|
||||
# 监控移动距离
|
||||
while distance_moved < abs_distance * completion_threshold and time.time() - start_time < timeout:
|
||||
current_time = time.time()
|
||||
|
||||
# 按固定间隔检查位置,减少计算负担
|
||||
if current_time - last_check_time >= position_check_interval:
|
||||
# 获取当前位置和朝向
|
||||
current_position = ctrl.odo_msg.xyz
|
||||
current_yaw = ctrl.odo_msg.rpy[2]
|
||||
|
||||
# 计算已移动距离
|
||||
dx = current_position[0] - start_position[0]
|
||||
dy = current_position[1] - start_position[1]
|
||||
distance_moved = math.sqrt(dx*dx + dy*dy)
|
||||
|
||||
# 计算移动方向与初始朝向的偏差
|
||||
movement_direction = math.atan2(current_position[1] - last_position[1],
|
||||
current_position[0] - last_position[0]) if distance_moved > 0.05 else start_yaw
|
||||
yaw_error = movement_direction - start_yaw
|
||||
# 角度归一化
|
||||
while yaw_error > math.pi:
|
||||
yaw_error -= 2 * math.pi
|
||||
while yaw_error < -math.pi:
|
||||
yaw_error += 2 * math.pi
|
||||
|
||||
# 计算完成比例
|
||||
completion_ratio = distance_moved / abs_distance
|
||||
|
||||
# 根据距离完成情况调整速度
|
||||
if completion_ratio > slow_down_ratio:
|
||||
# 计算减速系数
|
||||
slow_factor = 1.0 - (completion_ratio - slow_down_ratio) / (1.0 - slow_down_ratio)
|
||||
# 确保不会减速太多
|
||||
slow_factor = max(0.2, slow_factor)
|
||||
new_speed = actual_speed * slow_factor
|
||||
|
||||
if observe and abs(new_speed - msg.vel_des[0]) > 0.05:
|
||||
print(f"减速: {msg.vel_des[0]:.2f} -> {new_speed:.2f} 米/秒 (完成: {completion_ratio*100:.1f}%)")
|
||||
|
||||
msg.vel_des[0] = new_speed
|
||||
msg.life_count += 1
|
||||
ctrl.Send_cmd(msg)
|
||||
|
||||
# 如果偏离初始方向,进行角度修正
|
||||
if abs(yaw_error) > angle_correction_threshold:
|
||||
# 计算角速度修正值,偏差越大修正越强
|
||||
angular_correction = -yaw_error * 0.5 # 比例系数可调整
|
||||
# 限制最大角速度修正
|
||||
angular_correction = max(min(angular_correction, 0.2), -0.2)
|
||||
|
||||
if observe and abs(angular_correction) > 0.05:
|
||||
print(f"方向修正: 偏差 {math.degrees(yaw_error):.1f}度,应用角速度 {angular_correction:.3f}rad/s")
|
||||
|
||||
# 应用角速度修正
|
||||
msg.vel_des[2] = angular_correction
|
||||
msg.life_count += 1
|
||||
ctrl.Send_cmd(msg)
|
||||
elif msg.vel_des[2] != 0:
|
||||
# 如果方向已修正,重置角速度
|
||||
msg.vel_des[2] = 0
|
||||
msg.life_count += 1
|
||||
ctrl.Send_cmd(msg)
|
||||
|
||||
if observe and current_time - start_time > 1 and (current_time % 0.5 < position_check_interval):
|
||||
print(f"已移动: {distance_moved:.3f}米, 目标: {abs_distance:.3f}米 (完成: {completion_ratio*100:.1f}%)")
|
||||
print(f"当前速度: [{msg.vel_des[0]:.2f}, {msg.vel_des[1]:.2f}, {msg.vel_des[2]:.2f}]")
|
||||
|
||||
# 更新最后检查时间和位置
|
||||
last_check_time = current_time
|
||||
last_position = current_position
|
||||
|
||||
time.sleep(0.01) # 小间隔检查位置
|
||||
|
||||
# 平滑停止
|
||||
if hasattr(ctrl.base_msg, 'stop_smooth'):
|
||||
ctrl.base_msg.stop_smooth()
|
||||
else:
|
||||
ctrl.base_msg.stop()
|
||||
|
||||
# 获取最终位置和实际移动距离
|
||||
final_position = ctrl.odo_msg.xyz
|
||||
dx = final_position[0] - start_position[0]
|
||||
dy = final_position[1] - start_position[1]
|
||||
actual_distance = math.sqrt(dx*dx + dy*dy)
|
||||
|
||||
if observe:
|
||||
print(f"移动完成,从里程计计算的移动距离: {actual_distance:.3f}米")
|
||||
# 在终点放置标记
|
||||
if hasattr(ctrl, 'place_marker'):
|
||||
ctrl.place_marker(final_position[0], final_position[1],
|
||||
final_position[2] if len(final_position) > 2 else 0.0,
|
||||
'red', observe=True)
|
||||
|
||||
# 判断是否成功完成
|
||||
distance_error = abs(actual_distance - abs_distance)
|
||||
success = distance_error < 0.1 # 如果误差小于10厘米,则认为成功
|
||||
|
||||
if observe:
|
||||
print(f"目标距离: {abs_distance:.3f}米, 实际距离: {actual_distance:.3f}米, 误差: {distance_error:.3f}米")
|
||||
print(f"移动{'成功' if success else '失败'}")
|
||||
|
||||
return success
|
||||
|
||||
# 用法示例
|
||||
if __name__ == "__main__":
|
||||
# 这里是示例代码,实际使用时需要提供合适的ctrl和msg对象
|
||||
# 前进1米
|
||||
# go_straight(ctrl, msg, 1.0, speed=0.5, observe=True)
|
||||
# 后退0.5米
|
||||
# go_straight(ctrl, msg, -0.5, speed=0.3, observe=True)
|
||||
pass
|
||||
@ -110,4 +110,4 @@ def turn_degree(ctrl, msg, degree=90, absolute=False):
|
||||
# 判断是否成功达到目标
|
||||
return final_error <= limit
|
||||
|
||||
return True
|
||||
return True
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 76 KiB |
6
main.py
6
main.py
@ -31,11 +31,7 @@ def main():
|
||||
|
||||
try:
|
||||
print("Recovery stand")
|
||||
msg.mode = 12 # Recovery stand
|
||||
msg.gait_id = 0
|
||||
msg.life_count += 1
|
||||
Ctrl.Send_cmd(msg)
|
||||
Ctrl.Wait_finish(12, 0)
|
||||
Ctrl.base_msg.stand_up()
|
||||
|
||||
# time.sleep(100) # TEST
|
||||
|
||||
|
||||
@ -8,6 +8,7 @@ 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.go_straight import go_straight
|
||||
|
||||
observe = False
|
||||
|
||||
@ -38,7 +39,7 @@ def run_task_1(ctrl, msg):
|
||||
|
||||
print('😺 task 1 - 3')
|
||||
# direction = True if qr_result == 'A-1' else False
|
||||
# TODO
|
||||
# TODO
|
||||
turn_success = arc_turn_around_hori_line(
|
||||
ctrl=ctrl,
|
||||
msg=msg,
|
||||
@ -47,13 +48,21 @@ def run_task_1(ctrl, msg):
|
||||
left=False, # direction,
|
||||
pass_align=True,
|
||||
observe=observe,
|
||||
|
||||
# TODO clear
|
||||
bad_big_angle_corret=True
|
||||
)
|
||||
|
||||
print('😺 task 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)
|
||||
|
||||
print('😺 task 1 - 5 休眠,模拟装货')
|
||||
ctrl.base_msg.lie_down(wait_time=5000)
|
||||
|
||||
# 站起来
|
||||
ctrl.base_msg.stand_up()
|
||||
|
||||
print('😺 task 1 - 6 back')
|
||||
go_straight(ctrl, msg, distance=-move_distance + 0.1, speed=0.5, observe=observe)
|
||||
|
||||
|
||||
@ -61,4 +61,26 @@ class BaseMsg:
|
||||
self.msg.life_count += 1
|
||||
self.ctrl.Send_cmd(self.msg)
|
||||
time.sleep(step_time / 1000)
|
||||
|
||||
def lie_down(self, wait_time=500):
|
||||
"""发送趴下指令
|
||||
|
||||
参数:
|
||||
wait_time: 等待时间(毫秒),默认为500ms
|
||||
"""
|
||||
assert wait_time != 0 or wait_time > 3000, "wait_time 必须在 0 or > 3000"
|
||||
self.msg.mode = 7
|
||||
self.msg.gait_id = 1
|
||||
self.msg.duration = wait_time
|
||||
self.msg.life_count += 1
|
||||
self.ctrl.Send_cmd(self.msg)
|
||||
if wait_time:
|
||||
time.sleep(wait_time / 1000)
|
||||
|
||||
def stand_up(self):
|
||||
self.msg.mode = 12
|
||||
self.msg.gait_id = 0
|
||||
self.msg.life_count += 1
|
||||
self.ctrl.Send_cmd(self.msg)
|
||||
self.ctrl.Wait_finish(12, 0)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user