back turn degree
This commit is contained in:
		
							parent
							
								
									1146bdc4ef
								
							
						
					
					
						commit
						c3fe5e69d1
					
				@ -45,146 +45,202 @@ def turn_degree(ctrl, msg, degree=90, absolute=False, precision=False):
 | 
			
		||||
    # 如果是精确模式,使用更小的误差阈值
 | 
			
		||||
    limit = 0.03 if precision else 0.04  # 约1.7度或2.3度
 | 
			
		||||
    
 | 
			
		||||
    # 确定最短旋转方向
 | 
			
		||||
    remaining_dist = target_yaw - current_yaw
 | 
			
		||||
    if remaining_dist > math.pi:
 | 
			
		||||
        remaining_dist -= 2 * math.pi
 | 
			
		||||
    elif remaining_dist < -math.pi:
 | 
			
		||||
        remaining_dist += 2 * math.pi
 | 
			
		||||
    
 | 
			
		||||
    # 如果误差已经在允许范围内,无需旋转
 | 
			
		||||
    if abs(remaining_dist) <= limit:
 | 
			
		||||
        success(f"当前角度误差已在允许范围内,无需旋转", "成功")
 | 
			
		||||
        return True
 | 
			
		||||
    
 | 
			
		||||
    # 确定旋转方向和速度
 | 
			
		||||
    turn_direction = 1 if remaining_dist > 0 else -1
 | 
			
		||||
    
 | 
			
		||||
    # 根据精确模式选择旋转速度
 | 
			
		||||
    if precision:
 | 
			
		||||
        # 精确模式下,角度较大时使用中等速度,较小时使用慢速
 | 
			
		||||
        if abs(remaining_dist) > 0.5:  # 大约28度以上
 | 
			
		||||
            turn_speed = 0.25
 | 
			
		||||
    # 计算最短旋转方向和距离
 | 
			
		||||
    def circle_dist(target, location):
 | 
			
		||||
        value1 = abs(target - location)
 | 
			
		||||
        value2 = 2 * math.pi - value1
 | 
			
		||||
        direction1 = 1 if target > location else 0  # 1为逆时针,0为顺时针
 | 
			
		||||
        
 | 
			
		||||
        # 计算两个方向哪个距离更短
 | 
			
		||||
        if value1 < value2:
 | 
			
		||||
            return direction1, value1
 | 
			
		||||
        else:
 | 
			
		||||
            turn_speed = 0.15
 | 
			
		||||
    else:
 | 
			
		||||
        # 非精确模式下,角度较大时使用快速,较小时使用中等速度
 | 
			
		||||
        if abs(remaining_dist) > 0.5:  # 大约28度以上
 | 
			
		||||
            turn_speed = 0.5
 | 
			
		||||
            return 1 - direction1, value2
 | 
			
		||||
    
 | 
			
		||||
    # 获取旋转方向和距离
 | 
			
		||||
    direction, dist = circle_dist(target_yaw, current_yaw)
 | 
			
		||||
    info(f"开始旋转: 当前角度={math.degrees(current_yaw):.2f}°, 目标角度={math.degrees(target_yaw):.2f}°", "旋转")
 | 
			
		||||
    
 | 
			
		||||
    if abs(dist) > limit:
 | 
			
		||||
        # 主要转向
 | 
			
		||||
        const_int = 2470  # 转1.57弧度约需2470的duration值
 | 
			
		||||
        
 | 
			
		||||
        # 精确模式下使用更小的旋转速度
 | 
			
		||||
        turn_speed = 0.3 if precision else 0.5
 | 
			
		||||
        
 | 
			
		||||
        # 如果角度很小且使用精确模式,进一步降低速度
 | 
			
		||||
        if precision and abs(dist) < 0.2:  # 约11.5度
 | 
			
		||||
            turn_speed = 0.2
 | 
			
		||||
        
 | 
			
		||||
        # 设置转向命令
 | 
			
		||||
        msg.mode = 11  # Locomotion模式
 | 
			
		||||
        msg.gait_id = 26  # 自变频步态
 | 
			
		||||
        msg.vel_des = [0, 0, turn_speed if direction > 0 else -turn_speed]  # 转向速度
 | 
			
		||||
        
 | 
			
		||||
        # 精确模式下延长转向时间以保证稳定性
 | 
			
		||||
        duration_factor = 1.2 if precision else 1.0
 | 
			
		||||
        msg.duration = int(const_int * abs(dist) * duration_factor)
 | 
			
		||||
        msg.step_height = [0.06, 0.06]  # 抬腿高度
 | 
			
		||||
        msg.life_count += 1
 | 
			
		||||
        
 | 
			
		||||
        # 发送命令
 | 
			
		||||
        ctrl.Send_cmd(msg)
 | 
			
		||||
        debug(f"发送旋转命令:方向={'逆时针' if direction > 0 else '顺时针'}, 速度={turn_speed}, 持续时间={msg.duration}", "旋转")
 | 
			
		||||
        
 | 
			
		||||
        # 等待转向完成
 | 
			
		||||
        # 精确模式下增加等待时间
 | 
			
		||||
        wait_factor = 1.3 if precision else 1.0
 | 
			
		||||
        wait_time = 7 * abs(dist) / 1.57 * wait_factor
 | 
			
		||||
        debug(f"等待旋转完成: {wait_time:.2f}秒", "时间")
 | 
			
		||||
        
 | 
			
		||||
        # 精确模式下使用实时监控而不是固定等待时间
 | 
			
		||||
        if precision and abs(dist) > 0.1:  # 对于较大角度
 | 
			
		||||
            start_time = time.time()
 | 
			
		||||
            last_yaw = current_yaw
 | 
			
		||||
            stable_count = 0
 | 
			
		||||
            timeout = wait_time + 3  # 增加超时保护
 | 
			
		||||
            
 | 
			
		||||
            # 实时监控旋转进度
 | 
			
		||||
            while time.time() - start_time < timeout:
 | 
			
		||||
                time.sleep(0.1)  # 频繁检查
 | 
			
		||||
                
 | 
			
		||||
                current_yaw_now = ctrl.odo_msg.rpy[2]
 | 
			
		||||
                # 计算已旋转角度
 | 
			
		||||
                rotated = abs(current_yaw_now - last_yaw)
 | 
			
		||||
                if rotated > math.pi:
 | 
			
		||||
                    rotated = 2 * math.pi - rotated
 | 
			
		||||
                
 | 
			
		||||
                # 如果旋转速度很小(几乎停止)
 | 
			
		||||
                if rotated < 0.01:  # 约0.6度
 | 
			
		||||
                    stable_count += 1
 | 
			
		||||
                else:
 | 
			
		||||
                    stable_count = 0
 | 
			
		||||
                    
 | 
			
		||||
                last_yaw = current_yaw_now
 | 
			
		||||
                
 | 
			
		||||
                # 如果机器人稳定一段时间,认为旋转完成
 | 
			
		||||
                if stable_count >= 3:
 | 
			
		||||
                    debug(f"检测到旋转已稳定,提前结束等待", "旋转")
 | 
			
		||||
                    break
 | 
			
		||||
                
 | 
			
		||||
                # 每0.5秒打印一次进度
 | 
			
		||||
                elapsed = time.time() - start_time
 | 
			
		||||
                if int(elapsed * 2) % 2 == 0:
 | 
			
		||||
                    remaining_yaw = target_yaw - current_yaw_now
 | 
			
		||||
                    # 标准化到 [-pi, pi]
 | 
			
		||||
                    if remaining_yaw > math.pi:
 | 
			
		||||
                        remaining_yaw -= 2 * math.pi
 | 
			
		||||
                    if remaining_yaw < -math.pi:
 | 
			
		||||
                        remaining_yaw += 2 * math.pi
 | 
			
		||||
                    debug(f"旋转进度: {elapsed:.1f}s/{wait_time:.1f}s, 剩余角度: {math.degrees(remaining_yaw):.2f}°", "进度")
 | 
			
		||||
        else:
 | 
			
		||||
            turn_speed = 0.3
 | 
			
		||||
    
 | 
			
		||||
    info(f"开始旋转: 当前角度={math.degrees(current_yaw):.2f}°, 目标角度={math.degrees(target_yaw):.2f}°, 需旋转{math.degrees(abs(remaining_dist)):.2f}°", "旋转")
 | 
			
		||||
    
 | 
			
		||||
    # 发送旋转命令(持续旋转)
 | 
			
		||||
    msg.mode = 11  # Locomotion模式
 | 
			
		||||
    msg.gait_id = 26  # 自变频步态
 | 
			
		||||
    msg.vel_des = [0, 0, turn_speed * turn_direction]  # 转向速度和方向
 | 
			
		||||
    msg.duration = 30000  # 设置一个大的持续时间值,后面会主动停止
 | 
			
		||||
    msg.step_height = [0.06, 0.06]  # 抬腿高度
 | 
			
		||||
    msg.life_count += 1
 | 
			
		||||
    
 | 
			
		||||
    # 发送命令
 | 
			
		||||
    ctrl.Send_cmd(msg)
 | 
			
		||||
    debug(f"开始持续旋转:方向={'逆时针' if turn_direction > 0 else '顺时针'}, 速度={turn_speed}", "旋转")
 | 
			
		||||
    
 | 
			
		||||
    # 等待并监测旋转进度
 | 
			
		||||
    start_time = time.time()
 | 
			
		||||
    last_yaw = current_yaw
 | 
			
		||||
    stable_count = 0
 | 
			
		||||
    
 | 
			
		||||
    # 设置最大超时时间(秒)防止无限等待
 | 
			
		||||
    max_timeout = 15 if abs(remaining_dist) > 1.0 else 10
 | 
			
		||||
    
 | 
			
		||||
    while True:
 | 
			
		||||
        time.sleep(0.05)  # 高频监测旋转状态
 | 
			
		||||
            # 非精确模式使用固定等待时间
 | 
			
		||||
            time.sleep(wait_time)
 | 
			
		||||
        
 | 
			
		||||
        # 获取当前角度
 | 
			
		||||
        current_yaw_now = ctrl.odo_msg.rpy[2]
 | 
			
		||||
        current_yaw = ctrl.odo_msg.rpy[2]
 | 
			
		||||
        info(f"主要转向完成: 当前角度={math.degrees(current_yaw):.2f}°, 目标角度={math.degrees(target_yaw):.2f}°", "角度")
 | 
			
		||||
        
 | 
			
		||||
        # 计算当前与目标的角度差
 | 
			
		||||
        current_error = target_yaw - current_yaw_now
 | 
			
		||||
        if current_error > math.pi:
 | 
			
		||||
            current_error -= 2 * math.pi
 | 
			
		||||
        elif current_error < -math.pi:
 | 
			
		||||
            current_error += 2 * math.pi
 | 
			
		||||
            
 | 
			
		||||
        # 计算已旋转角度(用于检测机器人是否在移动)
 | 
			
		||||
        rotated = current_yaw_now - last_yaw
 | 
			
		||||
        if abs(rotated) > math.pi:
 | 
			
		||||
            rotated = 2 * math.pi - abs(rotated)
 | 
			
		||||
            rotated *= -1 if current_yaw_now > last_yaw else 1
 | 
			
		||||
            
 | 
			
		||||
        last_yaw = current_yaw_now
 | 
			
		||||
        # 计算剩余误差
 | 
			
		||||
        remaining_dist = target_yaw - current_yaw
 | 
			
		||||
        if remaining_dist > math.pi:
 | 
			
		||||
            remaining_dist -= 2 * math.pi
 | 
			
		||||
        elif remaining_dist < -math.pi:
 | 
			
		||||
            remaining_dist += 2 * math.pi
 | 
			
		||||
        
 | 
			
		||||
        # 每0.5秒打印一次进度
 | 
			
		||||
        elapsed = time.time() - start_time
 | 
			
		||||
        if int(elapsed * 2) % 10 == 0:  # 每5秒
 | 
			
		||||
            debug(f"旋转进度: {elapsed:.1f}s, 剩余角度: {math.degrees(abs(current_error)):.2f}°", "进度")
 | 
			
		||||
        # 精细调整(如果误差大于限制)
 | 
			
		||||
        if abs(remaining_dist) > limit:
 | 
			
		||||
            warning(f"剩余误差: {math.degrees(remaining_dist):.2f}°, 需要进行微调", "角度")
 | 
			
		||||
            
 | 
			
		||||
        # 判断是否已经接近目标角度
 | 
			
		||||
        if abs(current_error) <= limit:
 | 
			
		||||
            # 立即发送停止命令
 | 
			
		||||
            # 进行微调
 | 
			
		||||
            const_int_tiny = 1200 if not precision else 1000  # 精确模式下使用更小的系数
 | 
			
		||||
            
 | 
			
		||||
            # 精确模式下使用更小的微调速度
 | 
			
		||||
            fine_turn_speed = 0.3 if precision else 0.5
 | 
			
		||||
            
 | 
			
		||||
            # 如果剩余误差很小,进一步降低速度
 | 
			
		||||
            if abs(remaining_dist) < 0.1:  # 约5.7度
 | 
			
		||||
                fine_turn_speed = 0.15
 | 
			
		||||
            
 | 
			
		||||
            # 设置微调命令
 | 
			
		||||
            msg.mode = 11
 | 
			
		||||
            msg.gait_id = 26
 | 
			
		||||
            msg.vel_des = [0, 0, 0]  # 停止旋转
 | 
			
		||||
            msg.duration = 200  # 短暂停止命令
 | 
			
		||||
            msg.vel_des = [0, 0, fine_turn_speed if remaining_dist > 0 else -fine_turn_speed]
 | 
			
		||||
            
 | 
			
		||||
            # 精确模式下使用更长的微调时间
 | 
			
		||||
            duration_factor = 1.25 if precision else 1.0
 | 
			
		||||
            msg.duration = int(const_int_tiny * abs(remaining_dist) * duration_factor)
 | 
			
		||||
            msg.step_height = [0.06, 0.06]
 | 
			
		||||
            msg.life_count += 1
 | 
			
		||||
            
 | 
			
		||||
            # 发送命令
 | 
			
		||||
            ctrl.Send_cmd(msg)
 | 
			
		||||
            debug(f"发送微调命令:方向={'逆时针' if remaining_dist > 0 else '顺时针'}, 速度={fine_turn_speed}, 持续时间={msg.duration}", "旋转")
 | 
			
		||||
            
 | 
			
		||||
            success(f"旋转成功,误差在允许范围内: {math.degrees(abs(current_error)):.2f}°", "成功")
 | 
			
		||||
            return True
 | 
			
		||||
            # 精确模式下等待更长时间
 | 
			
		||||
            wait_time = 5 if not precision else 7
 | 
			
		||||
            time.sleep(wait_time)
 | 
			
		||||
            
 | 
			
		||||
        # 检测是否接近目标角度,需要减速
 | 
			
		||||
        if abs(current_error) < 0.3 and abs(turn_speed) > 0.15:  # 约17度内减速
 | 
			
		||||
            turn_speed = 0.15 * (1 if turn_speed > 0 else -1)
 | 
			
		||||
            msg.vel_des = [0, 0, turn_speed]
 | 
			
		||||
            msg.life_count += 1
 | 
			
		||||
            ctrl.Send_cmd(msg)
 | 
			
		||||
            debug(f"接近目标,减速至: {turn_speed}", "减速")
 | 
			
		||||
            # 获取最终角度
 | 
			
		||||
            final_yaw = ctrl.odo_msg.rpy[2]
 | 
			
		||||
            info(f"微调完成: 最终角度={math.degrees(final_yaw):.2f}°, 目标角度={math.degrees(target_yaw):.2f}°", "角度")
 | 
			
		||||
            
 | 
			
		||||
        # 如果旋转方向不对(过头或方向错误),修正方向
 | 
			
		||||
        if (current_error > 0 and turn_direction < 0) or (current_error < 0 and turn_direction > 0):
 | 
			
		||||
            turn_direction = 1 if current_error > 0 else -1
 | 
			
		||||
            turn_speed = 0.15  # 方向调整时使用低速
 | 
			
		||||
            msg.vel_des = [0, 0, turn_speed * turn_direction]
 | 
			
		||||
            msg.life_count += 1
 | 
			
		||||
            ctrl.Send_cmd(msg)
 | 
			
		||||
            debug(f"调整旋转方向: {'逆时针' if turn_direction > 0 else '顺时针'}, 速度={turn_speed}", "方向")
 | 
			
		||||
        
 | 
			
		||||
        # 检查超时
 | 
			
		||||
        if elapsed > max_timeout:
 | 
			
		||||
            # 发送停止命令
 | 
			
		||||
            msg.mode = 11
 | 
			
		||||
            msg.gait_id = 26
 | 
			
		||||
            msg.vel_des = [0, 0, 0]  # 停止旋转
 | 
			
		||||
            msg.duration = 500
 | 
			
		||||
            msg.life_count += 1
 | 
			
		||||
            ctrl.Send_cmd(msg)
 | 
			
		||||
            final_error = abs(target_yaw - final_yaw)
 | 
			
		||||
            if final_error > math.pi:
 | 
			
		||||
                final_error = 2 * math.pi - final_error
 | 
			
		||||
            
 | 
			
		||||
            error(f"旋转超时,已停止。当前误差: {math.degrees(abs(current_error)):.2f}°", "超时")
 | 
			
		||||
            return False
 | 
			
		||||
        
 | 
			
		||||
        # 检测机器人是否卡住(长时间无明显角度变化)
 | 
			
		||||
        if abs(rotated) < 0.005:  # 角度变化很小
 | 
			
		||||
            stable_count += 1
 | 
			
		||||
        else:
 | 
			
		||||
            stable_count = 0
 | 
			
		||||
            
 | 
			
		||||
        # 如果连续多次检测到角度几乎不变,可能卡住了
 | 
			
		||||
        if stable_count > 30:  # 连续30次检测(约1.5秒)角度几乎不变
 | 
			
		||||
            # 尝试增加速度或改变方向
 | 
			
		||||
            if abs(turn_speed) < 0.5:
 | 
			
		||||
                turn_speed = 0.5 * turn_direction
 | 
			
		||||
                msg.vel_des = [0, 0, turn_speed]
 | 
			
		||||
                msg.life_count += 1
 | 
			
		||||
                ctrl.Send_cmd(msg)
 | 
			
		||||
                debug(f"检测到旋转停滞,增加速度至: {turn_speed}", "调整")
 | 
			
		||||
                stable_count = 0
 | 
			
		||||
            # 判断是否成功达到目标
 | 
			
		||||
            if final_error <= limit:
 | 
			
		||||
                success(f"旋转成功,误差在允许范围内: {math.degrees(final_error):.2f}°", "成功")
 | 
			
		||||
                return True
 | 
			
		||||
            else:
 | 
			
		||||
                # 如果速度已经很大还是卡住,可能有障碍,停止旋转
 | 
			
		||||
                msg.vel_des = [0, 0, 0]  # 停止旋转
 | 
			
		||||
                msg.life_count += 1
 | 
			
		||||
                ctrl.Send_cmd(msg)
 | 
			
		||||
                error(f"检测到旋转异常,已停止。当前误差: {math.degrees(abs(current_error)):.2f}°", "异常")
 | 
			
		||||
                warning(f"旋转完成,但误差超出允许范围: {math.degrees(final_error):.2f}° > {math.degrees(limit):.2f}°", "警告")
 | 
			
		||||
                
 | 
			
		||||
                # 在精确模式下,如果误差仍然很大,尝试第二次微调
 | 
			
		||||
                if precision and final_error > limit * 2:
 | 
			
		||||
                    info("尝试第二次微调", "精确")
 | 
			
		||||
                    
 | 
			
		||||
                    # 计算第二次微调角度
 | 
			
		||||
                    second_adj = target_yaw - final_yaw
 | 
			
		||||
                    if second_adj > math.pi:
 | 
			
		||||
                        second_adj -= 2 * math.pi
 | 
			
		||||
                    elif second_adj < -math.pi:
 | 
			
		||||
                        second_adj += 2 * math.pi
 | 
			
		||||
                    
 | 
			
		||||
                    # 降低微调速度
 | 
			
		||||
                    very_fine_speed = 0.1
 | 
			
		||||
                    
 | 
			
		||||
                    # 设置第二次微调命令
 | 
			
		||||
                    msg.mode = 11
 | 
			
		||||
                    msg.gait_id = 26
 | 
			
		||||
                    msg.vel_des = [0, 0, very_fine_speed if second_adj > 0 else -very_fine_speed]
 | 
			
		||||
                    msg.duration = int(800 * abs(second_adj))  # 使用更小的系数
 | 
			
		||||
                    msg.step_height = [0.06, 0.06]
 | 
			
		||||
                    msg.life_count += 1
 | 
			
		||||
                    
 | 
			
		||||
                    # 发送命令
 | 
			
		||||
                    ctrl.Send_cmd(msg)
 | 
			
		||||
                    debug(f"第二次微调:旋转{math.degrees(second_adj):.2f}°", "精确")
 | 
			
		||||
                    
 | 
			
		||||
                    # 等待第二次微调完成
 | 
			
		||||
                    time.sleep(3)
 | 
			
		||||
                    
 | 
			
		||||
                    # 获取最终结果
 | 
			
		||||
                    final_final_yaw = ctrl.odo_msg.rpy[2]
 | 
			
		||||
                    
 | 
			
		||||
                    final_final_error = abs(target_yaw - final_final_yaw)
 | 
			
		||||
                    if final_final_error > math.pi:
 | 
			
		||||
                        final_final_error = 2 * math.pi - final_final_error
 | 
			
		||||
                    
 | 
			
		||||
                    if final_final_error <= limit:
 | 
			
		||||
                        success(f"第二次微调成功,最终误差: {math.degrees(final_final_error):.2f}°", "成功")
 | 
			
		||||
                        return True
 | 
			
		||||
                    else:
 | 
			
		||||
                        warning(f"两次微调后仍有误差: {math.degrees(final_final_error):.2f}°", "警告")
 | 
			
		||||
                        # 如果误差已经比第一次小,算作改进
 | 
			
		||||
                        return final_final_error < final_error
 | 
			
		||||
                
 | 
			
		||||
                return False
 | 
			
		||||
    
 | 
			
		||||
    success("旋转成功完成", "完成")
 | 
			
		||||
    return True
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user