From e1ea0231cdaf844ccd7ae93f065ecdc06c0d14e9 Mon Sep 17 00:00:00 2001 From: XYTX0427 <481177497@qq.com> Date: Fri, 19 Dec 2025 18:41:14 +0800 Subject: [PATCH 01/21] =?UTF-8?q?=E6=8F=90=E4=BA=A4=E9=80=89=E9=A2=98?= =?UTF-8?q?=E5=92=8C=E8=AF=95=E9=AA=8C=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Unmanned_aerial_vehicle/README.md | 1 + src/Unmanned_aerial_vehicle/main.py | 102 ++++++++++++++++++++++++++ 2 files changed, 103 insertions(+) create mode 100644 src/Unmanned_aerial_vehicle/README.md create mode 100644 src/Unmanned_aerial_vehicle/main.py diff --git a/src/Unmanned_aerial_vehicle/README.md b/src/Unmanned_aerial_vehicle/README.md new file mode 100644 index 0000000000..b00460f809 --- /dev/null +++ b/src/Unmanned_aerial_vehicle/README.md @@ -0,0 +1 @@ +无人机导航 \ No newline at end of file diff --git a/src/Unmanned_aerial_vehicle/main.py b/src/Unmanned_aerial_vehicle/main.py new file mode 100644 index 0000000000..04a5ea1fdf --- /dev/null +++ b/src/Unmanned_aerial_vehicle/main.py @@ -0,0 +1,102 @@ +import math + +# 定义无人机类,包含核心导航属性和方法 +class UAVAutonomousNavigation: + def __init__(self): + # 无人机当前位置(经纬度,单位:度) + self.current_lon = 0.0 + self.current_lat = 0.0 + # 预设航点列表(格式:[纬度, 经度]) + self.waypoints = [] + # 当前目标航点索引 + self.target_waypoint_idx = 0 + # 到达航点的判定阈值(米) + self.arrival_threshold = 5.0 + + def set_waypoints(self, waypoints_list): + """设置航点列表""" + self.waypoints = waypoints_list + self.target_waypoint_idx = 0 # 重置目标航点索引 + + def calculate_distance(self, lat1, lon1, lat2, lon2): + """ + 计算两个经纬度点之间的地面距离(米) + 采用简化的Haversine公式,适用于近距离无人机导航 + """ + # 地球半径(米) + R = 6371000.0 + # 角度转弧度 + lat1_rad = math.radians(lat1) + lon1_rad = math.radians(lon1) + lat2_rad = math.radians(lat2) + lon2_rad = math.radians(lon2) + + # 经纬度差值 + dlat = lat2_rad - lat1_rad + dlon = lon2_rad - lon1_rad + + # Haversine公式 + a = math.sin(dlat / 2)**2 + math.cos(lat1_rad) * math.cos(lat2_rad) * math.sin(dlon / 2)**2 + c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a)) + distance = R * c + return distance + + def update_position(self, new_lat, new_lon): + """更新无人机当前位置""" + self.current_lat = new_lat + self.current_lon = new_lon + + def navigate_to_waypoints(self): + """核心航点导航逻辑:依次飞向每个航点""" + if not self.waypoints: + print("未设置航点,导航终止") + return + + # 获取当前目标航点 + target_lat, target_lon = self.waypoints[self.target_waypoint_idx] + # 计算当前位置到目标航点的距离 + distance_to_target = self.calculate_distance( + self.current_lat, self.current_lon, target_lat, target_lon + ) + + print(f"当前位置:({self.current_lat:.6f}, {self.current_lon:.6f})") + print(f"目标航点{self.target_waypoint_idx+1}:({target_lat:.6f}, {target_lon:.6f})") + print(f"到目标航点距离:{distance_to_target:.2f} 米") + + # 判断是否到达当前航点 + if distance_to_target < self.arrival_threshold: + print(f"已到达航点{self.target_waypoint_idx+1}") + self.target_waypoint_idx += 1 + # 判断是否完成所有航点 + if self.target_waypoint_idx >= len(self.waypoints): + print("所有航点导航完成!") + return + else: + print(f"切换至下一个航点:{self.target_waypoint_idx+1}") + else: + # 生成飞行指令(实际场景中需替换为无人机SDK的飞行控制指令) + print("飞行指令:向目标航点飞行(航向/速度需根据实际SDK调整)") + +# ------------------- 测试代码 ------------------- +if __name__ == "__main__": + # 初始化无人机导航实例 + uav = UAVAutonomousNavigation() + + # 设置航点列表(示例:3个航点) + waypoints = [ + (39.908823, 116.397470), # 航点1:天安门 + (39.997563, 116.337624), # 航点2:颐和园 + (40.006401, 116.397029) # 航点3:圆明园 + ] + uav.set_waypoints(waypoints) + + # 模拟无人机位置更新与导航过程 + # 模拟初始位置(靠近航点1) + uav.update_position(39.908820, 116.397468) + uav.navigate_to_waypoints() + + print("-" * 50) + + # 模拟无人机飞到航点1,更新位置 + uav.update_position(39.908823, 116.397470) + uav.navigate_to_waypoints() \ No newline at end of file From ab1c3922464162dfa8852344f928dcd1edeb908b Mon Sep 17 00:00:00 2001 From: XYTX0427 <481177497@qq.com> Date: Fri, 19 Dec 2025 20:59:18 +0800 Subject: [PATCH 02/21] =?UTF-8?q?=E6=8F=90=E4=BA=A4=E9=80=89=E9=A2=98?= =?UTF-8?q?=E5=92=8C=E8=AF=95=E9=AA=8C=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Unmanned_aerial_vehicle/main.py | 295 ++++++++++++++++++++-------- 1 file changed, 218 insertions(+), 77 deletions(-) diff --git a/src/Unmanned_aerial_vehicle/main.py b/src/Unmanned_aerial_vehicle/main.py index 04a5ea1fdf..3529838050 100644 --- a/src/Unmanned_aerial_vehicle/main.py +++ b/src/Unmanned_aerial_vehicle/main.py @@ -1,102 +1,243 @@ import math +import logging +from typing import List, Tuple + +# 配置日志,方便追踪运行状态 +logging.basicConfig( + level=logging.INFO, + format="%(asctime)s - %(levelname)s - %(message)s", + datefmt="%Y-%m-%d %H:%M:%S" +) +logger = logging.getLogger("UAV_Autonomous_Navigation") + -# 定义无人机类,包含核心导航属性和方法 class UAVAutonomousNavigation: + """无人机自主导航核心类:整合航点导航、避障、路径重规划""" + def __init__(self): - # 无人机当前位置(经纬度,单位:度) - self.current_lon = 0.0 - self.current_lat = 0.0 - # 预设航点列表(格式:[纬度, 经度]) - self.waypoints = [] - # 当前目标航点索引 - self.target_waypoint_idx = 0 - # 到达航点的判定阈值(米) - self.arrival_threshold = 5.0 - - def set_waypoints(self, waypoints_list): - """设置航点列表""" - self.waypoints = waypoints_list - self.target_waypoint_idx = 0 # 重置目标航点索引 - - def calculate_distance(self, lat1, lon1, lat2, lon2): + # 无人机核心状态 + self.current_position: Tuple[float, float] = (0.0, 0.0) # (纬度, 经度) + self.current_heading: float = 0.0 # 当前航向(度,0=正北,90=正东) + self.safety_distance: float = 10.0 # 避障安全距离(米) + self.arrival_threshold: float = 5.0 # 到达航点判定阈值(米) + + # 导航相关参数 + self.waypoints: List[Tuple[float, float]] = [] # 航点列表 + self.target_waypoint_idx: int = 0 # 当前目标航点索引 + self.is_obstacle_detected: bool = False # 是否检测到障碍物 + self.obstacle_distance: float = float("inf") # 障碍物距离(初始为无穷大) + + def set_waypoints(self, waypoints: List[Tuple[float, float]]) -> None: """ - 计算两个经纬度点之间的地面距离(米) - 采用简化的Haversine公式,适用于近距离无人机导航 + 设置航点列表,增加输入验证 + :param waypoints: 航点列表,每个元素为(纬度, 经度)元组 """ - # 地球半径(米) - R = 6371000.0 - # 角度转弧度 - lat1_rad = math.radians(lat1) - lon1_rad = math.radians(lon1) - lat2_rad = math.radians(lat2) - lon2_rad = math.radians(lon2) - - # 经纬度差值 - dlat = lat2_rad - lat1_rad - dlon = lon2_rad - lon1_rad - - # Haversine公式 - a = math.sin(dlat / 2)**2 + math.cos(lat1_rad) * math.cos(lat2_rad) * math.sin(dlon / 2)**2 - c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a)) - distance = R * c - return distance - - def update_position(self, new_lat, new_lon): - """更新无人机当前位置""" - self.current_lat = new_lat - self.current_lon = new_lon - - def navigate_to_waypoints(self): - """核心航点导航逻辑:依次飞向每个航点""" - if not self.waypoints: - print("未设置航点,导航终止") + try: + # 验证航点格式 + if not isinstance(waypoints, list): + raise TypeError("航点必须为列表格式") + for idx, wp in enumerate(waypoints): + if not isinstance(wp, tuple) or len(wp) != 2: + raise ValueError(f"第{idx + 1}个航点格式错误,需为(纬度, 经度)元组") + if not (isinstance(wp[0], (int, float)) and isinstance(wp[1], (int, float))): + raise ValueError(f"第{idx + 1}个航点经纬度必须为数字") + + self.waypoints = waypoints + self.target_waypoint_idx = 0 + logger.info(f"成功设置{len(waypoints)}个航点,初始目标航点:1") + + except (TypeError, ValueError) as e: + logger.error(f"设置航点失败:{str(e)}") + raise + + def calculate_haversine_distance(self, lat1: float, lon1: float, lat2: float, lon2: float) -> float: + """ + 高精度计算两个经纬度点的地面距离(米) + 采用Haversine公式,适配无人机低空导航场景 + """ + try: + # 地球平均半径(米) + EARTH_RADIUS = 6371008.8 + # 角度转弧度 + lat1_rad = math.radians(lat1) + lon1_rad = math.radians(lon1) + lat2_rad = math.radians(lat2) + lon2_rad = math.radians(lon2) + + # 经纬度差值 + dlat = lat2_rad - lat1_rad + dlon = lon2_rad - lon1_rad + + # Haversine核心计算 + a = math.sin(dlat / 2) ** 2 + math.cos(lat1_rad) * math.cos(lat2_rad) * math.sin(dlon / 2) ** 2 + c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a)) + distance = EARTH_RADIUS * c + + logger.debug(f"距离计算:({lat1:.6f},{lon1:.6f}) → ({lat2:.6f},{lon2:.6f}) = {distance:.2f}米") + return distance + + except Exception as e: + logger.error(f"距离计算失败:{str(e)}") + raise + + def update_uav_state(self, new_lat: float, new_lon: float, new_heading: float = None) -> None: + """ + 更新无人机位置和航向 + :param new_lat: 新纬度 + :param new_lon: 新经度 + :param new_heading: 新航向(可选,不传入则保持原航向) + """ + try: + if not (isinstance(new_lat, (int, float)) and isinstance(new_lon, (int, float))): + raise ValueError("经纬度必须为数字") + + self.current_position = (new_lat, new_lon) + if new_heading is not None: + if not isinstance(new_heading, (int, float)) or new_heading < 0 or new_heading > 360: + raise ValueError("航向需为0-360之间的数字") + self.current_heading = new_heading + + logger.info(f"无人机状态更新:位置({new_lat:.6f},{new_lon:.6f}),航向{self.current_heading:.1f}°") + + except ValueError as e: + logger.error(f"更新无人机状态失败:{str(e)}") + raise + + def update_obstacle_data(self, distance: float) -> None: + """ + 更新障碍物检测数据(模拟激光雷达/超声波传感器输入) + :param distance: 前方障碍物距离(米),None表示未检测到 + """ + if distance is None: + self.is_obstacle_detected = False + self.obstacle_distance = float("inf") + logger.info("未检测到障碍物") return - # 获取当前目标航点 + try: + if not isinstance(distance, (int, float)) or distance < 0: + raise ValueError("障碍物距离需为非负数字") + + self.obstacle_distance = distance + self.is_obstacle_detected = distance < self.safety_distance + + if self.is_obstacle_detected: + logger.warning(f"检测到前方障碍物!距离:{distance:.2f}米(安全阈值:{self.safety_distance}米)") + else: + logger.info(f"前方障碍物距离:{distance:.2f}米(安全)") + + except ValueError as e: + logger.error(f"更新障碍物数据失败:{str(e)}") + raise + + def replan_path(self) -> List[Tuple[float, float]]: + """ + 路径重规划(简化版):遇到障碍时生成绕行航点 + :return: 重规划后的航点列表 + """ + logger.info("触发路径重规划:生成绕行航点") + + # 获取当前位置和目标航点 + current_lat, current_lon = self.current_position target_lat, target_lon = self.waypoints[self.target_waypoint_idx] - # 计算当前位置到目标航点的距离 - distance_to_target = self.calculate_distance( - self.current_lat, self.current_lon, target_lat, target_lon + + # 计算绕行偏移量(向左偏移0.0001度,约11米,适配经纬度坐标系) + offset_lat = (target_lat - current_lat) * 0.1 # 纬度偏移 + offset_lon = (target_lon - current_lon) * 0.1 # 经度偏移 + + # 生成绕行航点(当前位置 → 绕行点 → 原目标航点) + detour_point = ( + current_lat + offset_lon, # 左偏移经度 + current_lon - offset_lat # 左偏移纬度 + ) + + # 重规划航点列表:保留已完成航点 + 绕行点 + 剩余航点 + replanned_waypoints = ( + self.waypoints[:self.target_waypoint_idx] + + [detour_point] + + self.waypoints[self.target_waypoint_idx:] ) - print(f"当前位置:({self.current_lat:.6f}, {self.current_lon:.6f})") - print(f"目标航点{self.target_waypoint_idx+1}:({target_lat:.6f}, {target_lon:.6f})") - print(f"到目标航点距离:{distance_to_target:.2f} 米") + logger.info(f"路径重规划完成:新增绕行航点{detour_point}") + return replanned_waypoints + + def navigate(self) -> None: + """ + 核心导航逻辑: + 1. 检查航点是否为空 + 2. 检测障碍物,必要时重规划路径 + 3. 飞向目标航点,到达后切换下一个 + """ + # 检查航点 + if not self.waypoints: + logger.error("导航终止:未设置航点") + return + + # 检查是否完成所有航点 + if self.target_waypoint_idx >= len(self.waypoints): + logger.info("导航完成:所有航点已到达") + return + + # 障碍物检测与路径重规划 + if self.is_obstacle_detected: + self.waypoints = self.replan_path() + + # 获取目标航点 + target_lat, target_lon = self.waypoints[self.target_waypoint_idx] + current_lat, current_lon = self.current_position - # 判断是否到达当前航点 + # 计算到目标航点的距离 + distance_to_target = self.calculate_haversine_distance( + current_lat, current_lon, target_lat, target_lon + ) + + # 判断是否到达目标航点 if distance_to_target < self.arrival_threshold: - print(f"已到达航点{self.target_waypoint_idx+1}") + logger.info(f"到达航点{self.target_waypoint_idx + 1}:({target_lat:.6f},{target_lon:.6f})") self.target_waypoint_idx += 1 - # 判断是否完成所有航点 - if self.target_waypoint_idx >= len(self.waypoints): - print("所有航点导航完成!") - return - else: - print(f"切换至下一个航点:{self.target_waypoint_idx+1}") + # 重置障碍物状态 + self.is_obstacle_detected = False + self.obstacle_distance = float("inf") else: - # 生成飞行指令(实际场景中需替换为无人机SDK的飞行控制指令) - print("飞行指令:向目标航点飞行(航向/速度需根据实际SDK调整)") + # 生成飞行指令(实际场景替换为无人机SDK API) + logger.info( + f"飞向航点{self.target_waypoint_idx + 1}:" + f"当前距离{distance_to_target:.2f}米,航向{self.current_heading:.1f}°" + ) + # ------------------- 测试代码 ------------------- if __name__ == "__main__": - # 初始化无人机导航实例 - uav = UAVAutonomousNavigation() + # 初始化导航实例 + uav_nav = UAVAutonomousNavigation() - # 设置航点列表(示例:3个航点) - waypoints = [ + # 1. 设置航点(示例:3个真实地理坐标) + waypoints_list = [ (39.908823, 116.397470), # 航点1:天安门 (39.997563, 116.337624), # 航点2:颐和园 - (40.006401, 116.397029) # 航点3:圆明园 + (40.006401, 116.397029) # 航点3:圆明园 ] - uav.set_waypoints(waypoints) + uav_nav.set_waypoints(waypoints_list) + + # 2. 模拟无人机初始状态 + uav_nav.update_uav_state(39.908820, 116.397468, 270.0) # 初始位置靠近航点1,航向270°(正西) + + # 3. 模拟导航过程1:无障碍物,飞向航点1 + logger.info("\n===== 导航阶段1:无障碍物 =====") + uav_nav.update_obstacle_data(20.0) # 障碍物距离20米(安全) + uav_nav.navigate() - # 模拟无人机位置更新与导航过程 - # 模拟初始位置(靠近航点1) - uav.update_position(39.908820, 116.397468) - uav.navigate_to_waypoints() + # 4. 模拟到达航点1,更新位置 + uav_nav.update_uav_state(39.908823, 116.397470) + uav_nav.navigate() - print("-" * 50) + # 5. 模拟导航阶段2:检测到障碍物,触发路径重规划 + logger.info("\n===== 导航阶段2:检测到障碍物 =====") + uav_nav.update_obstacle_data(8.0) # 障碍物距离8米(触发避障) + uav_nav.navigate() - # 模拟无人机飞到航点1,更新位置 - uav.update_position(39.908823, 116.397470) - uav.navigate_to_waypoints() \ No newline at end of file + # 6. 模拟绕开障碍后继续导航 + logger.info("\n===== 导航阶段3:绕开障碍后 =====") + uav_nav.update_obstacle_data(None) # 无障碍物 + uav_nav.update_uav_state(39.950000, 116.360000) # 模拟飞到绕行点 + uav_nav.navigate() \ No newline at end of file From 8867bfac303e182a253c2b11303bb7f9decd1224 Mon Sep 17 00:00:00 2001 From: XYTX0427 <481177497@qq.com> Date: Fri, 19 Dec 2025 22:57:25 +0800 Subject: [PATCH 03/21] =?UTF-8?q?=E8=AF=95=E9=AA=8C=E6=96=B0=E4=BB=A3?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Unmanned_aerial_vehicle/main.py | 354 ++++++++++------------------ 1 file changed, 118 insertions(+), 236 deletions(-) diff --git a/src/Unmanned_aerial_vehicle/main.py b/src/Unmanned_aerial_vehicle/main.py index 3529838050..679e2b45e0 100644 --- a/src/Unmanned_aerial_vehicle/main.py +++ b/src/Unmanned_aerial_vehicle/main.py @@ -1,243 +1,125 @@ import math -import logging -from typing import List, Tuple - -# 配置日志,方便追踪运行状态 -logging.basicConfig( - level=logging.INFO, - format="%(asctime)s - %(levelname)s - %(message)s", - datefmt="%Y-%m-%d %H:%M:%S" -) -logger = logging.getLogger("UAV_Autonomous_Navigation") - - -class UAVAutonomousNavigation: - """无人机自主导航核心类:整合航点导航、避障、路径重规划""" - - def __init__(self): - # 无人机核心状态 - self.current_position: Tuple[float, float] = (0.0, 0.0) # (纬度, 经度) - self.current_heading: float = 0.0 # 当前航向(度,0=正北,90=正东) - self.safety_distance: float = 10.0 # 避障安全距离(米) - self.arrival_threshold: float = 5.0 # 到达航点判定阈值(米) - - # 导航相关参数 - self.waypoints: List[Tuple[float, float]] = [] # 航点列表 - self.target_waypoint_idx: int = 0 # 当前目标航点索引 - self.is_obstacle_detected: bool = False # 是否检测到障碍物 - self.obstacle_distance: float = float("inf") # 障碍物距离(初始为无穷大) - - def set_waypoints(self, waypoints: List[Tuple[float, float]]) -> None: - """ - 设置航点列表,增加输入验证 - :param waypoints: 航点列表,每个元素为(纬度, 经度)元组 - """ - try: - # 验证航点格式 - if not isinstance(waypoints, list): - raise TypeError("航点必须为列表格式") - for idx, wp in enumerate(waypoints): - if not isinstance(wp, tuple) or len(wp) != 2: - raise ValueError(f"第{idx + 1}个航点格式错误,需为(纬度, 经度)元组") - if not (isinstance(wp[0], (int, float)) and isinstance(wp[1], (int, float))): - raise ValueError(f"第{idx + 1}个航点经纬度必须为数字") - - self.waypoints = waypoints - self.target_waypoint_idx = 0 - logger.info(f"成功设置{len(waypoints)}个航点,初始目标航点:1") - - except (TypeError, ValueError) as e: - logger.error(f"设置航点失败:{str(e)}") - raise - - def calculate_haversine_distance(self, lat1: float, lon1: float, lat2: float, lon2: float) -> float: - """ - 高精度计算两个经纬度点的地面距离(米) - 采用Haversine公式,适配无人机低空导航场景 - """ - try: - # 地球平均半径(米) - EARTH_RADIUS = 6371008.8 - # 角度转弧度 - lat1_rad = math.radians(lat1) - lon1_rad = math.radians(lon1) - lat2_rad = math.radians(lat2) - lon2_rad = math.radians(lon2) - - # 经纬度差值 - dlat = lat2_rad - lat1_rad - dlon = lon2_rad - lon1_rad - - # Haversine核心计算 - a = math.sin(dlat / 2) ** 2 + math.cos(lat1_rad) * math.cos(lat2_rad) * math.sin(dlon / 2) ** 2 - c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a)) - distance = EARTH_RADIUS * c - - logger.debug(f"距离计算:({lat1:.6f},{lon1:.6f}) → ({lat2:.6f},{lon2:.6f}) = {distance:.2f}米") - return distance - - except Exception as e: - logger.error(f"距离计算失败:{str(e)}") - raise - - def update_uav_state(self, new_lat: float, new_lon: float, new_heading: float = None) -> None: - """ - 更新无人机位置和航向 - :param new_lat: 新纬度 - :param new_lon: 新经度 - :param new_heading: 新航向(可选,不传入则保持原航向) - """ - try: - if not (isinstance(new_lat, (int, float)) and isinstance(new_lon, (int, float))): - raise ValueError("经纬度必须为数字") - - self.current_position = (new_lat, new_lon) - if new_heading is not None: - if not isinstance(new_heading, (int, float)) or new_heading < 0 or new_heading > 360: - raise ValueError("航向需为0-360之间的数字") - self.current_heading = new_heading - - logger.info(f"无人机状态更新:位置({new_lat:.6f},{new_lon:.6f}),航向{self.current_heading:.1f}°") - - except ValueError as e: - logger.error(f"更新无人机状态失败:{str(e)}") - raise - - def update_obstacle_data(self, distance: float) -> None: - """ - 更新障碍物检测数据(模拟激光雷达/超声波传感器输入) - :param distance: 前方障碍物距离(米),None表示未检测到 - """ - if distance is None: - self.is_obstacle_detected = False - self.obstacle_distance = float("inf") - logger.info("未检测到障碍物") +import random +import time + + +class Drone: + """无人机核心类,模拟无人机的状态和行为""" + + def __init__(self, start_x=0.0, start_y=0.0, start_z=0.0): + # 无人机当前位置 (x, y, z) 坐标 + self.x = start_x + self.y = start_y + self.z = start_z + # 无人机飞行速度 (m/s) + self.speed = 2.0 + # 无人机状态:idle(待机)/flying(飞行)/avoiding(避障) + self.status = "idle" + # 目标位置 + self.target_x = 0.0 + self.target_y = 0.0 + self.target_z = 0.0 + # 避障距离阈值 (米) + self.obstacle_threshold = 3.0 + + def set_target(self, target_x, target_y, target_z): + """设置无人机的目标位置""" + self.target_x = target_x + self.target_y = target_y + self.target_z = target_z + self.status = "flying" + print(f"无人机目标已设置:({target_x}, {target_y}, {target_z}),开始飞行") + + def calculate_distance_to_target(self): + """计算当前位置到目标位置的直线距离""" + dx = self.target_x - self.x + dy = self.target_y - self.y + dz = self.target_z - self.z + return math.sqrt(dx ** 2 + dy ** 2 + dz ** 2) + + def detect_obstacle(self, obstacles): + """模拟障碍物检测:检查是否有障碍物在避障阈值范围内""" + for (ox, oy, oz) in obstacles: + dx = ox - self.x + dy = oy - self.y + dz = oz - self.z + distance = math.sqrt(dx ** 2 + dy ** 2 + dz ** 2) + if distance < self.obstacle_threshold: + return True, (ox, oy, oz) # 检测到障碍物,返回障碍物位置 + return False, None + + def avoid_obstacle(self, obstacle_pos): + """简单避障策略:向障碍物右侧偏移飞行""" + ox, oy, _ = obstacle_pos + # 计算偏移方向(右侧1米) + self.x += (self.x - ox) * 0.5 # 远离障碍物x方向 + self.y += (self.y - oy) * 0.5 # 远离障碍物y方向 + print(f"检测到障碍物({ox}, {oy}),已避障,当前位置:({self.x:.2f}, {self.y:.2f})") + self.status = "avoiding" + + def update_position(self): + """更新无人机位置,向目标点移动""" + if self.status != "flying": return - try: - if not isinstance(distance, (int, float)) or distance < 0: - raise ValueError("障碍物距离需为非负数字") - - self.obstacle_distance = distance - self.is_obstacle_detected = distance < self.safety_distance - - if self.is_obstacle_detected: - logger.warning(f"检测到前方障碍物!距离:{distance:.2f}米(安全阈值:{self.safety_distance}米)") - else: - logger.info(f"前方障碍物距离:{distance:.2f}米(安全)") - - except ValueError as e: - logger.error(f"更新障碍物数据失败:{str(e)}") - raise - - def replan_path(self) -> List[Tuple[float, float]]: - """ - 路径重规划(简化版):遇到障碍时生成绕行航点 - :return: 重规划后的航点列表 - """ - logger.info("触发路径重规划:生成绕行航点") - - # 获取当前位置和目标航点 - current_lat, current_lon = self.current_position - target_lat, target_lon = self.waypoints[self.target_waypoint_idx] - - # 计算绕行偏移量(向左偏移0.0001度,约11米,适配经纬度坐标系) - offset_lat = (target_lat - current_lat) * 0.1 # 纬度偏移 - offset_lon = (target_lon - current_lon) * 0.1 # 经度偏移 - - # 生成绕行航点(当前位置 → 绕行点 → 原目标航点) - detour_point = ( - current_lat + offset_lon, # 左偏移经度 - current_lon - offset_lat # 左偏移纬度 - ) - - # 重规划航点列表:保留已完成航点 + 绕行点 + 剩余航点 - replanned_waypoints = ( - self.waypoints[:self.target_waypoint_idx] + - [detour_point] + - self.waypoints[self.target_waypoint_idx:] - ) - - logger.info(f"路径重规划完成:新增绕行航点{detour_point}") - return replanned_waypoints - - def navigate(self) -> None: - """ - 核心导航逻辑: - 1. 检查航点是否为空 - 2. 检测障碍物,必要时重规划路径 - 3. 飞向目标航点,到达后切换下一个 - """ - # 检查航点 - if not self.waypoints: - logger.error("导航终止:未设置航点") + # 计算方向向量 + dx = self.target_x - self.x + dy = self.target_y - self.y + dz = self.target_z - self.z + distance = self.calculate_distance_to_target() + + # 如果距离小于步长,直接到达目标 + if distance < self.speed: + self.x = self.target_x + self.y = self.target_y + self.z = self.target_z + self.status = "idle" + print(f"已到达目标位置:({self.x:.2f}, {self.y:.2f}, {self.z:.2f})") return - # 检查是否完成所有航点 - if self.target_waypoint_idx >= len(self.waypoints): - logger.info("导航完成:所有航点已到达") - return + # 归一化方向向量,按速度移动 + self.x += (dx / distance) * self.speed + self.y += (dy / distance) * self.speed + self.z += (dz / distance) * self.speed + + def get_status(self): + """获取无人机当前状态和位置""" + return { + "position": (round(self.x, 2), round(self.y, 2), round(self.z, 2)), + "status": self.status, + "distance_to_target": round(self.calculate_distance_to_target(), 2) + } + - # 障碍物检测与路径重规划 - if self.is_obstacle_detected: - self.waypoints = self.replan_path() - - # 获取目标航点 - target_lat, target_lon = self.waypoints[self.target_waypoint_idx] - current_lat, current_lon = self.current_position - - # 计算到目标航点的距离 - distance_to_target = self.calculate_haversine_distance( - current_lat, current_lon, target_lat, target_lon - ) - - # 判断是否到达目标航点 - if distance_to_target < self.arrival_threshold: - logger.info(f"到达航点{self.target_waypoint_idx + 1}:({target_lat:.6f},{target_lon:.6f})") - self.target_waypoint_idx += 1 - # 重置障碍物状态 - self.is_obstacle_detected = False - self.obstacle_distance = float("inf") - else: - # 生成飞行指令(实际场景替换为无人机SDK API) - logger.info( - f"飞向航点{self.target_waypoint_idx + 1}:" - f"当前距离{distance_to_target:.2f}米,航向{self.current_heading:.1f}°" - ) - - -# ------------------- 测试代码 ------------------- +# -------------------------- 主程序:无人机自主导航仿真 -------------------------- if __name__ == "__main__": - # 初始化导航实例 - uav_nav = UAVAutonomousNavigation() - - # 1. 设置航点(示例:3个真实地理坐标) - waypoints_list = [ - (39.908823, 116.397470), # 航点1:天安门 - (39.997563, 116.337624), # 航点2:颐和园 - (40.006401, 116.397029) # 航点3:圆明园 - ] - uav_nav.set_waypoints(waypoints_list) - - # 2. 模拟无人机初始状态 - uav_nav.update_uav_state(39.908820, 116.397468, 270.0) # 初始位置靠近航点1,航向270°(正西) - - # 3. 模拟导航过程1:无障碍物,飞向航点1 - logger.info("\n===== 导航阶段1:无障碍物 =====") - uav_nav.update_obstacle_data(20.0) # 障碍物距离20米(安全) - uav_nav.navigate() - - # 4. 模拟到达航点1,更新位置 - uav_nav.update_uav_state(39.908823, 116.397470) - uav_nav.navigate() - - # 5. 模拟导航阶段2:检测到障碍物,触发路径重规划 - logger.info("\n===== 导航阶段2:检测到障碍物 =====") - uav_nav.update_obstacle_data(8.0) # 障碍物距离8米(触发避障) - uav_nav.navigate() - - # 6. 模拟绕开障碍后继续导航 - logger.info("\n===== 导航阶段3:绕开障碍后 =====") - uav_nav.update_obstacle_data(None) # 无障碍物 - uav_nav.update_uav_state(39.950000, 116.360000) # 模拟飞到绕行点 - uav_nav.navigate() \ No newline at end of file + # 1. 初始化无人机(起点:0,0,10米高度) + drone = Drone(start_x=0.0, start_y=0.0, start_z=10.0) + + # 2. 设置目标位置(终点:20, 15, 10米高度) + drone.set_target(target_x=20.0, target_y=15.0, target_z=10.0) + + # 3. 模拟环境中的障碍物(坐标列表) + obstacles = [(10, 8, 10), (15, 12, 9)] # 两个障碍物位置 + + # 4. 自主导航主循环 + print("\n=== 无人机自主导航开始 ===") + while drone.status != "idle": + # 检测障碍物 + obstacle_detected, obstacle_pos = drone.detect_obstacle(obstacles) + if obstacle_detected: + drone.avoid_obstacle(obstacle_pos) + # 避障后恢复飞行状态 + drone.status = "flying" + + # 更新位置 + drone.update_position() + + # 打印实时状态 + status = drone.get_status() + print(f"当前位置:{status['position']} | 距离目标:{status['distance_to_target']}米 | 状态:{status['status']}") + + # 模拟实时刷新(每秒更新一次位置) + time.sleep(1) + + print("\n=== 无人机自主导航完成 ===") \ No newline at end of file From 0788d1618563fbbc0bd4df80496907161d7b11be Mon Sep 17 00:00:00 2001 From: XYTX0427 <481177497@qq.com> Date: Sun, 21 Dec 2025 16:24:42 +0800 Subject: [PATCH 04/21] =?UTF-8?q?=E8=AF=95=E9=AA=8C=E6=96=B0=E7=8E=AF?= =?UTF-8?q?=E5=A2=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Unmanned_aerial_vehicle/main.py | 275 ++++++++++++++++------------ 1 file changed, 156 insertions(+), 119 deletions(-) diff --git a/src/Unmanned_aerial_vehicle/main.py b/src/Unmanned_aerial_vehicle/main.py index 679e2b45e0..5533b25647 100644 --- a/src/Unmanned_aerial_vehicle/main.py +++ b/src/Unmanned_aerial_vehicle/main.py @@ -1,125 +1,162 @@ import math -import random import time -class Drone: - """无人机核心类,模拟无人机的状态和行为""" - - def __init__(self, start_x=0.0, start_y=0.0, start_z=0.0): - # 无人机当前位置 (x, y, z) 坐标 - self.x = start_x - self.y = start_y - self.z = start_z - # 无人机飞行速度 (m/s) - self.speed = 2.0 - # 无人机状态:idle(待机)/flying(飞行)/avoiding(避障) - self.status = "idle" +class DroneAutonomousNavigation: + def __init__(self): + """初始化无人机导航模拟器(无硬件依赖)""" + # 模拟无人机当前位置 [纬度, 经度, 高度(m)] + self.current_position = [39.908823, 116.397470, 10.0] # 初始位置(天安门附近) # 目标位置 - self.target_x = 0.0 - self.target_y = 0.0 - self.target_z = 0.0 - # 避障距离阈值 (米) - self.obstacle_threshold = 3.0 - - def set_target(self, target_x, target_y, target_z): - """设置无人机的目标位置""" - self.target_x = target_x - self.target_y = target_y - self.target_z = target_z - self.status = "flying" - print(f"无人机目标已设置:({target_x}, {target_y}, {target_z}),开始飞行") - - def calculate_distance_to_target(self): - """计算当前位置到目标位置的直线距离""" - dx = self.target_x - self.x - dy = self.target_y - self.y - dz = self.target_z - self.z - return math.sqrt(dx ** 2 + dy ** 2 + dz ** 2) - - def detect_obstacle(self, obstacles): - """模拟障碍物检测:检查是否有障碍物在避障阈值范围内""" - for (ox, oy, oz) in obstacles: - dx = ox - self.x - dy = oy - self.y - dz = oz - self.z - distance = math.sqrt(dx ** 2 + dy ** 2 + dz ** 2) - if distance < self.obstacle_threshold: - return True, (ox, oy, oz) # 检测到障碍物,返回障碍物位置 - return False, None - - def avoid_obstacle(self, obstacle_pos): - """简单避障策略:向障碍物右侧偏移飞行""" - ox, oy, _ = obstacle_pos - # 计算偏移方向(右侧1米) - self.x += (self.x - ox) * 0.5 # 远离障碍物x方向 - self.y += (self.y - oy) * 0.5 # 远离障碍物y方向 - print(f"检测到障碍物({ox}, {oy}),已避障,当前位置:({self.x:.2f}, {self.y:.2f})") - self.status = "avoiding" - - def update_position(self): - """更新无人机位置,向目标点移动""" - if self.status != "flying": - return - - # 计算方向向量 - dx = self.target_x - self.x - dy = self.target_y - self.y - dz = self.target_z - self.z - distance = self.calculate_distance_to_target() - - # 如果距离小于步长,直接到达目标 - if distance < self.speed: - self.x = self.target_x - self.y = self.target_y - self.z = self.target_z - self.status = "idle" - print(f"已到达目标位置:({self.x:.2f}, {self.y:.2f}, {self.z:.2f})") - return - - # 归一化方向向量,按速度移动 - self.x += (dx / distance) * self.speed - self.y += (dy / distance) * self.speed - self.z += (dz / distance) * self.speed - - def get_status(self): - """获取无人机当前状态和位置""" - return { - "position": (round(self.x, 2), round(self.y, 2), round(self.z, 2)), - "status": self.status, - "distance_to_target": round(self.calculate_distance_to_target(), 2) - } - - -# -------------------------- 主程序:无人机自主导航仿真 -------------------------- + self.target_position = None + # 导航状态 + self.is_navigating = False + + def set_current_position(self, lat, lon, alt): + """手动设置当前位置(模拟GPS更新)""" + self.current_position = [lat, lon, alt] + print(f"✅ 更新当前位置:纬度{lat:.6f}, 经度{lon:.6f}, 高度{alt:.1f}m") + + def calculate_gps_distance(self, pos1, pos2): + """ + 纯Python实现GPS两点距离计算(半正矢公式) + :param pos1: [lat, lon, alt] 起点 + :param pos2: [lat, lon, alt] 终点 + :return: 地面距离(米) + """ + # 地球半径(米) + EARTH_RADIUS = 6371000.0 + + # 转换为弧度 + lat1, lon1 = math.radians(pos1[0]), math.radians(pos1[1]) + lat2, lon2 = math.radians(pos2[0]), math.radians(pos2[1]) + + # 计算经纬度差值 + dlat = lat2 - lat1 + dlon = lon2 - lon1 + + # 半正矢公式核心计算 + a = math.sin(dlat / 2) ** 2 + math.cos(lat1) * math.cos(lat2) * math.sin(dlon / 2) ** 2 + c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a)) + distance = EARTH_RADIUS * c + + return round(distance, 2) + + def generate_straight_path(self, start_pos, target_pos, waypoint_count=5): + """ + 生成直线插值路径(无避障) + :param waypoint_count: 中间航点数量 + :return: 航点列表 [[lat, lon, alt], ...] + """ + path = [] + # 计算每个维度的步长 + lat_step = (target_pos[0] - start_pos[0]) / (waypoint_count + 1) + lon_step = (target_pos[1] - start_pos[1]) / (waypoint_count + 1) + alt_step = (target_pos[2] - start_pos[2]) / (waypoint_count + 1) + + # 生成中间航点 + for i in range(1, waypoint_count + 1): + lat = start_pos[0] + lat_step * i + lon = start_pos[1] + lon_step * i + alt = start_pos[2] + alt_step * i + path.append([round(lat, 6), round(lon, 6), round(alt, 1)]) + + # 添加最终目标点 + path.append([target_pos[0], target_pos[1], target_pos[2]]) + return path + + def simulate_fly_to_waypoint(self, waypoint): + """ + 模拟飞向单个航点(逐步更新位置) + :param waypoint: 目标航点 [lat, lon, alt] + """ + # 每次移动的步长(模拟无人机飞行,每次移动0.00001度经纬度) + LAT_STEP = 0.00001 + LON_STEP = 0.00001 + ALT_STEP = 0.5 # 高度每次移动0.5米 + + # 持续移动直到到达航点(距离<1米) + while True: + distance = self.calculate_gps_distance(self.current_position, waypoint) + if distance < 1.0: + print(f"✅ 到达航点:{waypoint} (距离{distance}m)") + break + + # 计算移动方向并更新位置 + current_lat, current_lon, current_alt = self.current_position + target_lat, target_lon, target_alt = waypoint + + # 纬度调整 + if current_lat < target_lat: + new_lat = current_lat + LAT_STEP + elif current_lat > target_lat: + new_lat = current_lat - LAT_STEP + else: + new_lat = current_lat + + # 经度调整 + if current_lon < target_lon: + new_lon = current_lon + LON_STEP + elif current_lon > target_lon: + new_lon = current_lon - LON_STEP + else: + new_lon = current_lon + + # 高度调整 + if current_alt < target_alt: + new_alt = current_alt + ALT_STEP + elif current_alt > target_alt: + new_alt = current_alt - ALT_STEP + else: + new_alt = current_alt + + # 更新位置 + self.set_current_position(new_lat, new_lon, new_alt) + # 模拟飞行延迟 + time.sleep(0.1) + + def navigate_to_target(self, target_lat, target_lon, target_alt): + """ + 自主导航主函数(纯算法模拟) + """ + self.target_position = [target_lat, target_lon, target_alt] + self.is_navigating = True + + print("\n🚀 开始自主导航任务") + print(f"📌 起点:{self.current_position}") + print(f"🎯 终点:{self.target_position}") + + # 1. 生成路径 + path = self.generate_straight_path(self.current_position, self.target_position) + print(f"\n🗺️ 生成路径完成,共{len(path)}个航点:") + for i, wp in enumerate(path): + print(f" 航点{i + 1}:{wp}") + + # 2. 依次飞向每个航点 + print("\n✈️ 开始飞向目标...") + for i, waypoint in enumerate(path): + print(f"\n--- 飞向第{i + 1}个航点 ---") + self.simulate_fly_to_waypoint(waypoint) + + # 3. 导航完成 + self.is_navigating = False + print("\n🎉 导航任务完成!已到达目标点") + + +# ------------------- 测试代码 ------------------- if __name__ == "__main__": - # 1. 初始化无人机(起点:0,0,10米高度) - drone = Drone(start_x=0.0, start_y=0.0, start_z=10.0) - - # 2. 设置目标位置(终点:20, 15, 10米高度) - drone.set_target(target_x=20.0, target_y=15.0, target_z=10.0) - - # 3. 模拟环境中的障碍物(坐标列表) - obstacles = [(10, 8, 10), (15, 12, 9)] # 两个障碍物位置 - - # 4. 自主导航主循环 - print("\n=== 无人机自主导航开始 ===") - while drone.status != "idle": - # 检测障碍物 - obstacle_detected, obstacle_pos = drone.detect_obstacle(obstacles) - if obstacle_detected: - drone.avoid_obstacle(obstacle_pos) - # 避障后恢复飞行状态 - drone.status = "flying" - - # 更新位置 - drone.update_position() - - # 打印实时状态 - status = drone.get_status() - print(f"当前位置:{status['position']} | 距离目标:{status['distance_to_target']}米 | 状态:{status['status']}") - - # 模拟实时刷新(每秒更新一次位置) - time.sleep(1) - - print("\n=== 无人机自主导航完成 ===") \ No newline at end of file + # 初始化导航模拟器 + drone = DroneAutonomousNavigation() + + # 设置目标点(比如:北京奥林匹克公园,高度50米) + target_lat = 39.990168 + target_lon = 116.397204 + target_alt = 50.0 + + # 执行自主导航 + try: + drone.navigate_to_target(target_lat, target_lon, target_alt) + except KeyboardInterrupt: + print("\n🛑 导航任务被手动终止") + finally: + print("\n🛬 无人机已悬停/降落") \ No newline at end of file From 70ee8802909580025714081f4fbaccd6202fdd0f Mon Sep 17 00:00:00 2001 From: XYTX0427 <481177497@qq.com> Date: Sun, 21 Dec 2025 21:00:21 +0800 Subject: [PATCH 05/21] =?UTF-8?q?=E9=87=8D=E6=96=B0=E6=8F=90=E4=BA=A4?= =?UTF-8?q?=E9=80=89=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Robotic_arm/README.md | 1 + src/{Unmanned_aerial_vehicle => Robotic_arm}/main.py | 0 src/Unmanned_aerial_vehicle/README.md | 1 - 3 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 src/Robotic_arm/README.md rename src/{Unmanned_aerial_vehicle => Robotic_arm}/main.py (100%) delete mode 100644 src/Unmanned_aerial_vehicle/README.md diff --git a/src/Robotic_arm/README.md b/src/Robotic_arm/README.md new file mode 100644 index 0000000000..fc1e2dead9 --- /dev/null +++ b/src/Robotic_arm/README.md @@ -0,0 +1 @@ +机械臂 \ No newline at end of file diff --git a/src/Unmanned_aerial_vehicle/main.py b/src/Robotic_arm/main.py similarity index 100% rename from src/Unmanned_aerial_vehicle/main.py rename to src/Robotic_arm/main.py diff --git a/src/Unmanned_aerial_vehicle/README.md b/src/Unmanned_aerial_vehicle/README.md deleted file mode 100644 index b00460f809..0000000000 --- a/src/Unmanned_aerial_vehicle/README.md +++ /dev/null @@ -1 +0,0 @@ -无人机导航 \ No newline at end of file From 7f88a0b42ac7cf08e71513641db12c145be20c1a Mon Sep 17 00:00:00 2001 From: XYTX0427 <481177497@qq.com> Date: Sun, 21 Dec 2025 21:42:23 +0800 Subject: [PATCH 06/21] =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E5=9F=BA=E7=A1=80?= =?UTF-8?q?=E7=9A=84=E6=9C=BA=E6=A2=B0=E8=87=82=E5=BB=BA=E6=A8=A1.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Robotic_arm/main.py | 314 ++++++++++++++++++++-------------------- 1 file changed, 155 insertions(+), 159 deletions(-) diff --git a/src/Robotic_arm/main.py b/src/Robotic_arm/main.py index 5533b25647..0529a86787 100644 --- a/src/Robotic_arm/main.py +++ b/src/Robotic_arm/main.py @@ -1,162 +1,158 @@ -import math -import time - - -class DroneAutonomousNavigation: - def __init__(self): - """初始化无人机导航模拟器(无硬件依赖)""" - # 模拟无人机当前位置 [纬度, 经度, 高度(m)] - self.current_position = [39.908823, 116.397470, 10.0] # 初始位置(天安门附近) - # 目标位置 - self.target_position = None - # 导航状态 - self.is_navigating = False - - def set_current_position(self, lat, lon, alt): - """手动设置当前位置(模拟GPS更新)""" - self.current_position = [lat, lon, alt] - print(f"✅ 更新当前位置:纬度{lat:.6f}, 经度{lon:.6f}, 高度{alt:.1f}m") - - def calculate_gps_distance(self, pos1, pos2): - """ - 纯Python实现GPS两点距离计算(半正矢公式) - :param pos1: [lat, lon, alt] 起点 - :param pos2: [lat, lon, alt] 终点 - :return: 地面距离(米) - """ - # 地球半径(米) - EARTH_RADIUS = 6371000.0 - - # 转换为弧度 - lat1, lon1 = math.radians(pos1[0]), math.radians(pos1[1]) - lat2, lon2 = math.radians(pos2[0]), math.radians(pos2[1]) - - # 计算经纬度差值 - dlat = lat2 - lat1 - dlon = lon2 - lon1 - - # 半正矢公式核心计算 - a = math.sin(dlat / 2) ** 2 + math.cos(lat1) * math.cos(lat2) * math.sin(dlon / 2) ** 2 - c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a)) - distance = EARTH_RADIUS * c - - return round(distance, 2) - - def generate_straight_path(self, start_pos, target_pos, waypoint_count=5): - """ - 生成直线插值路径(无避障) - :param waypoint_count: 中间航点数量 - :return: 航点列表 [[lat, lon, alt], ...] - """ - path = [] - # 计算每个维度的步长 - lat_step = (target_pos[0] - start_pos[0]) / (waypoint_count + 1) - lon_step = (target_pos[1] - start_pos[1]) / (waypoint_count + 1) - alt_step = (target_pos[2] - start_pos[2]) / (waypoint_count + 1) - - # 生成中间航点 - for i in range(1, waypoint_count + 1): - lat = start_pos[0] + lat_step * i - lon = start_pos[1] + lon_step * i - alt = start_pos[2] + alt_step * i - path.append([round(lat, 6), round(lon, 6), round(alt, 1)]) - - # 添加最终目标点 - path.append([target_pos[0], target_pos[1], target_pos[2]]) - return path - - def simulate_fly_to_waypoint(self, waypoint): - """ - 模拟飞向单个航点(逐步更新位置) - :param waypoint: 目标航点 [lat, lon, alt] - """ - # 每次移动的步长(模拟无人机飞行,每次移动0.00001度经纬度) - LAT_STEP = 0.00001 - LON_STEP = 0.00001 - ALT_STEP = 0.5 # 高度每次移动0.5米 - - # 持续移动直到到达航点(距离<1米) - while True: - distance = self.calculate_gps_distance(self.current_position, waypoint) - if distance < 1.0: - print(f"✅ 到达航点:{waypoint} (距离{distance}m)") - break - - # 计算移动方向并更新位置 - current_lat, current_lon, current_alt = self.current_position - target_lat, target_lon, target_alt = waypoint - - # 纬度调整 - if current_lat < target_lat: - new_lat = current_lat + LAT_STEP - elif current_lat > target_lat: - new_lat = current_lat - LAT_STEP - else: - new_lat = current_lat - - # 经度调整 - if current_lon < target_lon: - new_lon = current_lon + LON_STEP - elif current_lon > target_lon: - new_lon = current_lon - LON_STEP - else: - new_lon = current_lon - - # 高度调整 - if current_alt < target_alt: - new_alt = current_alt + ALT_STEP - elif current_alt > target_alt: - new_alt = current_alt - ALT_STEP - else: - new_alt = current_alt - - # 更新位置 - self.set_current_position(new_lat, new_lon, new_alt) - # 模拟飞行延迟 - time.sleep(0.1) - - def navigate_to_target(self, target_lat, target_lon, target_alt): - """ - 自主导航主函数(纯算法模拟) - """ - self.target_position = [target_lat, target_lon, target_alt] - self.is_navigating = True - - print("\n🚀 开始自主导航任务") - print(f"📌 起点:{self.current_position}") - print(f"🎯 终点:{self.target_position}") - - # 1. 生成路径 - path = self.generate_straight_path(self.current_position, self.target_position) - print(f"\n🗺️ 生成路径完成,共{len(path)}个航点:") - for i, wp in enumerate(path): - print(f" 航点{i + 1}:{wp}") - - # 2. 依次飞向每个航点 - print("\n✈️ 开始飞向目标...") - for i, waypoint in enumerate(path): - print(f"\n--- 飞向第{i + 1}个航点 ---") - self.simulate_fly_to_waypoint(waypoint) - - # 3. 导航完成 - self.is_navigating = False - print("\n🎉 导航任务完成!已到达目标点") - - -# ------------------- 测试代码 ------------------- -if __name__ == "__main__": - # 初始化导航模拟器 - drone = DroneAutonomousNavigation() - - # 设置目标点(比如:北京奥林匹克公园,高度50米) - target_lat = 39.990168 - target_lon = 116.397204 - target_alt = 50.0 +import mujoco +import mujoco.viewer +import numpy as np +import os +import tempfile +import time # 新增:备用的睡眠函数 + +# ====================== 1. 定义机械臂 XML 模型 ====================== +# 6自由度机械臂的 MuJoCo XML 描述 +arm_xml = """ + + + +""" + + +# ====================== 2. 模型加载和仿真控制 ====================== +def create_arm_simulation(): + """创建并运行机械臂仿真""" + # 将XML字符串写入临时文件(MuJoCo需要文件路径加载) + with tempfile.NamedTemporaryFile(mode='w', suffix='.xml', delete=False) as f: + f.write(arm_xml) + xml_path = f.name - # 执行自主导航 try: - drone.navigate_to_target(target_lat, target_lon, target_alt) - except KeyboardInterrupt: - print("\n🛑 导航任务被手动终止") + # 加载模型和数据 + model = mujoco.MjModel.from_xml_path(xml_path) + data = mujoco.MjData(model) + + print("✅ 机械臂模型加载成功!") + print(f"🔧 关节数量:{model.njnt}") + print(f"🔧 执行器数量:{model.nu}") + + # 设置初始关节角度 + initial_joint_angles = [0, 0.2, -0.5, 0, 0.3, 0] + data.qpos[:6] = initial_joint_angles + + # 启动可视化界面 + with mujoco.viewer.launch_passive(model, data) as viewer: + print("\n🎮 仿真已启动!按 Ctrl+C 退出") + print("💡 机械臂会自动缓慢运动,展示关节控制效果") + + # 仿真循环 + step = 0 + while viewer.is_running(): + # 控制频率:每20步更新一次关节目标 + if step % 20 == 0: + # 生成周期性的关节控制指令(让机械臂缓慢摆动) + t = data.time + target_angles = [ + 0.2 * np.sin(t * 0.5), # joint0: 基座旋转 + 0.3 + 0.2 * np.sin(t), # joint1: 肩部 + -0.6 + 0.2 * np.cos(t), # joint2: 肘部 + 0.1 * np.sin(t * 1.2), # joint3: 前臂 + 0.2 * np.cos(t * 0.8), # joint4: 腕部1 + 0.1 * np.sin(t * 1.5) # joint5: 腕部2 + ] + # 设置控制指令 + data.ctrl[:6] = target_angles + + # 运行一步仿真 + mujoco.mj_step(model, data) + + # 更新可视化 + viewer.sync() + + # 修复:兼容不同版本的睡眠函数 + try: + # 尝试调用新版 MuJoCo 的 sleep 函数(归属到 utils) + mujoco.utils.mju_sleep(1 / 60) + except AttributeError: + try: + # 尝试调用旧版 MuJoCo 的 sleep 函数(主模块) + mujoco.mju_sleep(1 / 60) + except AttributeError: + # 终极备用:使用 Python 内置的 time.sleep + time.sleep(1 / 60) + + step += 1 + + except Exception as e: + print(f"❌ 仿真出错:{e}") finally: - print("\n🛬 无人机已悬停/降落") \ No newline at end of file + # 删除临时XML文件 + os.unlink(xml_path) + + +if __name__ == "__main__": + # 检查MuJoCo版本 + print(f"🔍 MuJoCo 版本:{mujoco.__version__}") + + # 启动仿真 + create_arm_simulation() \ No newline at end of file From 7e1c538a21b1fb70bbd8675bda90dfed1e9dbfcb Mon Sep 17 00:00:00 2001 From: XYTX0427 <481177497@qq.com> Date: Mon, 22 Dec 2025 09:35:35 +0800 Subject: [PATCH 07/21] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=9C=BA=E6=A2=B0?= =?UTF-8?q?=E8=87=82=E7=9A=84=E8=BF=90=E5=8A=A8=E8=BD=A8=E8=BF=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Robotic_arm/main.py | 143 ++++++++++++++++++---------------------- 1 file changed, 63 insertions(+), 80 deletions(-) diff --git a/src/Robotic_arm/main.py b/src/Robotic_arm/main.py index 0529a86787..b7ee4eee6a 100644 --- a/src/Robotic_arm/main.py +++ b/src/Robotic_arm/main.py @@ -3,58 +3,56 @@ import numpy as np import os import tempfile -import time # 新增:备用的睡眠函数 +import time +from scipy import interpolate -# ====================== 1. 定义机械臂 XML 模型 ====================== -# 6自由度机械臂的 MuJoCo XML 描述 + +# ====================== 轨迹优化核心(纯原生) ====================== +def quintic_polynomial(start, end, T, t): + """五次多项式插值:保证位置/速度/加速度连续""" + s0, v0, a0 = start, 0, 0 + s1, v1, a1 = end, 0, 0 + + a = s0 + b = v0 + c = a0 / 2 + d = (20 * (s1 - s0) - (8 * v1 + 12 * v0) * T - (3 * a0 - a1) * T ** 2) / (2 * T ** 3) + e = (30 * (s0 - s1) + (14 * v1 + 16 * v0) * T + (3 * a0 - 2 * a1) * T ** 2) / (2 * T ** 4) + f = (12 * (s1 - s0) - (6 * v1 + 6 * v0) * T - (a0 - a1) * T ** 2) / (2 * T ** 5) + + return a + b * t + c * t ** 2 + d * t ** 3 + e * t ** 4 + f * t ** 5 + + +# ====================== 机械臂模型 ====================== arm_xml = """