From cb17a62df359d75b1201964866da52937fa83bc3 Mon Sep 17 00:00:00 2001 From: solfdd <1006434858@qq.com> Date: Sun, 21 Dec 2025 16:01:58 +0800 Subject: [PATCH 01/16] Create README.md --- src/Safe_navigation/README.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 src/Safe_navigation/README.md diff --git a/src/Safe_navigation/README.md b/src/Safe_navigation/README.md new file mode 100644 index 0000000000..e1ca3e8b66 --- /dev/null +++ b/src/Safe_navigation/README.md @@ -0,0 +1,2 @@ +首次提交选题为无人车安全导航 + From 35f609b2655e6d4f7f92a2b4957089102c813508 Mon Sep 17 00:00:00 2001 From: solfdd <1006434858@qq.com> Date: Sun, 21 Dec 2025 21:45:29 +0800 Subject: [PATCH 02/16] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/.gitignore | 5 + .../inspectionProfiles/profiles_settings.xml | 6 + .idea/misc.xml | 7 + .idea/modules.xml | 8 + .idea/nn.iml | 18 + .idea/vcs.xml | 6 + .../car.cpython-312-pytest-9.0.2.pyc | Bin 0 -> 36820 bytes ...onnect_airsim.cpython-312-pytest-9.0.2.pyc | Bin 0 -> 6417 bytes src/Safe_navigation/car.py | 846 ++++++++++++++++++ src/Safe_navigation/check_version.py | 30 + src/Safe_navigation/connect_airsim.py | 51 ++ .../events.out.tfevents.1766316918.YD.1800.0 | Bin 0 -> 88 bytes src/Safe_navigation/run_main.py | 506 +++++++++++ 13 files changed, 1483 insertions(+) create mode 100644 .idea/.gitignore create mode 100644 .idea/inspectionProfiles/profiles_settings.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/nn.iml create mode 100644 .idea/vcs.xml create mode 100644 src/Safe_navigation/__pycache__/car.cpython-312-pytest-9.0.2.pyc create mode 100644 src/Safe_navigation/__pycache__/connect_airsim.cpython-312-pytest-9.0.2.pyc create mode 100644 src/Safe_navigation/car.py create mode 100644 src/Safe_navigation/check_version.py create mode 100644 src/Safe_navigation/connect_airsim.py create mode 100644 src/Safe_navigation/logs/airsim_dqn_20251221_193518/events.out.tfevents.1766316918.YD.1800.0 create mode 100644 src/Safe_navigation/run_main.py diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000000..10b731c518 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,5 @@ +# 默认忽略的文件 +/shelf/ +/workspace.xml +# 基于编辑器的 HTTP 客户端请求 +/httpRequests/ diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000000..105ce2da2d --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000000..77773ffb78 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000000..0e01bed9d6 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/nn.iml b/.idea/nn.iml new file mode 100644 index 0000000000..28462e1238 --- /dev/null +++ b/.idea/nn.iml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000000..35eb1ddfbb --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/src/Safe_navigation/__pycache__/car.cpython-312-pytest-9.0.2.pyc b/src/Safe_navigation/__pycache__/car.cpython-312-pytest-9.0.2.pyc new file mode 100644 index 0000000000000000000000000000000000000000..639510e71852f9ac75bb3e29bfb82d18c606b6e8 GIT binary patch literal 36820 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 Xi^>ZpA}TAahOaT 0: + img1d = np.frombuffer(responses[0].image_data_uint8, dtype=np.uint8) + + if img1d.size > 0: + img_rgb = img1d.reshape(responses[0].height, responses[0].width, 3) + resized = cv2.resize(img_rgb, self.config.image_size) + normalized = resized.astype(np.float32) / 255.0 + normalized = np.transpose(normalized, (2, 0, 1)) + + return normalized + + except Exception as e: + print(f"获取摄像头图像失败: {e}") + + # 返回空白图像 + return np.zeros((3, *self.config.image_size), dtype=np.float32) + + def get_vehicle_state(self): + """获取车辆状态""" + try: + # 获取车辆状态 + car_state = self.client.getCarState() + + # 获取碰撞信息 + collision_info = self.client.simGetCollisionInfo() + + state_info = { + 'speed': car_state.speed, + 'velocity': [ + car_state.kinematics_estimated.linear_velocity.x_val, + car_state.kinematics_estimated.linear_velocity.y_val, + car_state.kinematics_estimated.linear_velocity.z_val + ], + 'position': [ + car_state.kinematics_estimated.position.x_val, + car_state.kinematics_estimated.position.y_val, + car_state.kinematics_estimated.position.z_val + ], + 'collision': collision_info.has_collided, + 'collision_count': collision_info.collision_count, + } + + return state_info + + except Exception as e: + print(f"获取车辆状态失败: {e}") + return None + + def create_state_vector(self, state_info): + """创建状态向量""" + if state_info is None: + return np.zeros(self.config.state_dim, dtype=np.float32) + + state_vector = [] + + # 速度信息 + state_vector.append(state_info['speed'] / self.config.max_speed) + state_vector.extend([v / 10.0 for v in state_info['velocity'][:2]]) + + # 位置信息 + state_vector.extend([p / 100.0 for p in state_info['position'][:2]]) + + # 碰撞信息 + state_vector.append(float(state_info['collision'])) + + # 补全到指定维度 + while len(state_vector) < self.config.state_dim: + state_vector.append(np.random.uniform(-0.1, 0.1)) + + state_vector = state_vector[:self.config.state_dim] + + return np.array(state_vector, dtype=np.float32) + + def get_state(self): + """获取当前状态""" + try: + image_state = self.get_camera_image() + state_info = self.get_vehicle_state() + state_vector = self.create_state_vector(state_info) + + safety_flags = { + 'collision': state_info['collision'] if state_info else False, + } + + return image_state, state_vector, safety_flags + + except Exception as e: + print(f"获取状态失败: {e}") + # 返回默认状态 + image_state = np.zeros((3, *self.config.image_size), dtype=np.float32) + state_vector = np.zeros(self.config.state_dim, dtype=np.float32) + safety_flags = {'collision': False} + return image_state, state_vector, safety_flags + + def apply_action(self, action_idx): + """应用动作到车辆""" + # 简化动作空间 + steer_actions = [-0.3, -0.1, 0.0, 0.1, 0.3] + throttle_actions = [0.0, 0.2, 0.5, 0.8, 1.0] + + # 确保动作索引在范围内 + action_idx = min(action_idx, len(steer_actions) * len(throttle_actions) - 1) + steer_idx = action_idx % len(steer_actions) + throttle_idx = min(action_idx // len(steer_actions), len(throttle_actions) - 1) + + # 创建控制命令 + car_controls = airsim.CarControls() + car_controls.steering = steer_actions[steer_idx] + car_controls.throttle = throttle_actions[throttle_idx] + car_controls.brake = 0.0 + + # 应用控制 + try: + self.client.setCarControls(car_controls) + return car_controls + except Exception as e: + print(f"应用控制命令失败: {e}") + return car_controls + + def calculate_reward(self, current_state_info, safety_flags): + """计算奖励函数""" + if current_state_info is None: + return 0.0 + + reward = 0.0 + speed = current_state_info['speed'] + + # 基础移动奖励 + if speed > 0.1: + reward += 0.1 + + # 碰撞惩罚 + if safety_flags['collision']: + reward += self.config.collision_penalty + self.collisions += 1 + print(f"⚠️ 发生碰撞! 惩罚: {self.config.collision_penalty}") + + # 生存奖励 + reward += 0.01 + + return reward + + def step(self, action_idx): + """执行一步环境交互""" + self.step_count += 1 + + # 获取当前状态 + prev_image, prev_vector, prev_safety = self.get_state() + + # 应用动作 + control = self.apply_action(action_idx) + + # 等待环境响应 + time.sleep(0.1) + + # 获取新状态 + current_image, current_vector, current_safety = self.get_state() + + # 获取状态信息用于计算奖励 + current_state_info = self.get_vehicle_state() + + # 计算奖励 + reward = self.calculate_reward(current_state_info, current_safety) + self.total_reward += reward + + # 检查是否终止 + done = False + if current_safety['collision']: + done = True + print("💥 终止: 发生碰撞") + elif self.step_count >= self.config.max_steps: + done = True + print("⏱️ 终止: 达到最大步数") + + return (current_image, current_vector, reward, + prev_image, prev_vector, done, current_safety) + + def reset(self): + """重置环境""" + self.step_count = 0 + self.total_reward = 0 + self.collisions = 0 + + try: + self.client.reset() + time.sleep(1.0) # 等待重置完成 + except Exception as e: + print(f"重置环境失败: {e}") + + image_state, vector_state, safety_flags = self.get_state() + + return image_state, vector_state, safety_flags + + def close(self): + """关闭环境""" + try: + print("AirSim环境已关闭") + except: + pass + + +# ==================== 训练函数 ==================== +def train_dqn_safety_navigation(resume_model=None): + """主训练函数""" + config = TrainingConfig() + + # 创建TensorBoard记录器 + log_dir = f"./logs/airsim_dqn_{datetime.now().strftime('%Y%m%d_%H%M%S')}" + writer = SummaryWriter(log_dir) + + # 初始化环境和智能体 + env = AirSimSafetyEnv(config) + agent = DQNAgent(config, device='cpu') + + # 恢复训练(如果指定) + if resume_model and os.path.exists(resume_model): + try: + agent.load_model(resume_model) + print(f"从模型恢复训练: {resume_model}") + except: + print("模型加载失败,从头开始训练") + else: + print("从头开始训练") + + # 连接AirSim服务器 + print("\n" + "=" * 60) + print("正在连接AirSim服务器...") + + if not env.connect(): + print("无法连接到AirSim服务器,退出训练") + return + + print("=" * 60) + + # 训练循环 + print(f"\n开始深度强化学习安全导航训练") + print(f"总回合数: {config.total_episodes}") + print(f"最大步数: {config.max_steps}") + print(f"设备: {agent.device}") + print("=" * 60) + + for episode in range(config.total_episodes): + # 重置环境 + try: + image_state, vector_state, safety_flags = env.reset() + except Exception as e: + print(f"重置环境失败: {e}") + break + + episode_reward = 0 + episode_steps = 0 + episode_losses = [] + episode_start_time = time.time() + + # 回合循环 + done = False + while not done and episode_steps < config.max_steps: + try: + # 选择动作 + action = agent.select_action(image_state, vector_state) + + # 执行动作,获取新状态和奖励 + (next_image, next_vector, reward, + prev_image, prev_vector, done, next_safety) = env.step(action) + + # 存储经验 + experience = ( + prev_image, prev_vector, action, reward, + next_image, next_vector, done + ) + agent.memory.push(experience) + + # 训练智能体 + if agent.steps_done % config.update_every == 0: + loss = agent.train_step() + if loss > 0: + episode_losses.append(loss) + + # 更新状态 + image_state, vector_state = next_image, next_vector + episode_reward += reward + episode_steps += 1 + agent.steps_done += 1 + + # 简单进度显示 + if episode_steps % 10 == 0: + print(f" 步数: {episode_steps}, 奖励: {episode_reward:.2f}, 探索率: {agent.epsilon:.3f}") + + except Exception as e: + print(f"回合执行出错: {e}") + done = True + + # 计算回合统计 + episode_time = time.time() - episode_start_time + avg_loss = np.mean(episode_losses) if episode_losses else 0 + + # 记录训练数据 + writer.add_scalar('Reward/Episode', episode_reward, episode) + writer.add_scalar('Loss/Episode', avg_loss, episode) + writer.add_scalar('Exploration/Epsilon', agent.epsilon, episode) + writer.add_scalar('Steps/Episode_Steps', episode_steps, episode) + + # 打印回合总结 + print(f"\n回合 {episode + 1}/{config.total_episodes}") + print(f" 总奖励: {episode_reward:.2f}") + print(f" 步数: {episode_steps}") + print(f" 时间: {episode_time:.1f}s") + print(f" 平均损失: {avg_loss:.4f}") + print(f" 碰撞次数: {env.collisions}") + print(f" 探索率: {agent.epsilon:.3f}") + + # 保存模型 + if (episode + 1) % config.save_interval == 0: + agent.save_model(episode + 1) + + # 更新目标网络 + if (episode + 1) % 5 == 0: + agent.update_target_network() + + # 保存最终模型 + agent.save_model(config.total_episodes) + + # 关闭环境 + env.close() + writer.close() + + print("\n" + "=" * 60) + print("🎉 训练完成!") + print(f"模型已保存至: {config.model_save_path}") + print(f"训练日志: {log_dir}") + print("=" * 60) + + +# ==================== 评估函数 ==================== +def evaluate_model(model_path, eval_episodes=3): + """评估训练好的模型""" + config = TrainingConfig() + env = AirSimSafetyEnv(config) + agent = DQNAgent(config, device='cpu') + + # 加载模型 + try: + agent.load_model(model_path) + agent.epsilon = 0.01 # 评估时探索率低 + except Exception as e: + print(f"模型加载失败: {e}") + return + + # 连接环境 + if not env.connect(): + print("无法连接到AirSim服务器") + return + + results = [] + + for episode in range(eval_episodes): + # 重置环境 + image_state, vector_state, _ = env.reset() + + episode_reward = 0 + episode_steps = 0 + + done = False + while not done and episode_steps < config.max_steps: + try: + # 选择动作(评估模式) + action = agent.select_action(image_state, vector_state, eval_mode=True) + + # 执行动作 + (next_image, next_vector, reward, + _, _, done, _) = env.step(action) + + # 更新 + image_state, vector_state = next_image, next_vector + episode_reward += reward + episode_steps += 1 + + # 简单显示 + if episode_steps % 10 == 0: + print(f" 评估步数: {episode_steps}, 奖励: {episode_reward:.2f}") + + except Exception as e: + print(f"评估出错: {e}") + done = True + + results.append({ + 'episode': episode + 1, + 'reward': episode_reward, + 'steps': episode_steps, + }) + + print(f"评估回合 {episode + 1}/{eval_episodes}: 奖励={episode_reward:.2f}") + + # 计算平均指标 + if results: + avg_reward = np.mean([r['reward'] for r in results]) + + print("\n" + "=" * 60) + print("评估结果总结:") + print(f"平均回合奖励: {avg_reward:.2f}") + print("=" * 60) + + env.close() + + +# ==================== 主程序入口 ==================== +if __name__ == "__main__": + import warnings + warnings.filterwarnings('ignore') + + print("=" * 70) + print("基于深度强化学习的AirSim自动驾驶安全导航系统") + print("版本:兼容旧版AirSim服务器 (1.2.6)") + print("=" * 70) + + # 创建必要的目录 + os.makedirs('./models', exist_ok=True) + os.makedirs('./logs', exist_ok=True) + + # 检查PyTorch + print(f"PyTorch版本: {torch.__version__}") + if torch.cuda.is_available(): + print(f"检测到GPU: {torch.cuda.get_device_name(0)}") + else: + print("将使用CPU运行") + + # 用户选择 + choice = None + valid_choices = ['1', '2', '3'] + + while choice not in valid_choices: + print("\n请选择运行模式:") + print("1. 训练新模型 (推荐先测试连接)") + print("2. 恢复训练") + print("3. 评估模型") + + user_input = input("\n请输入选择 (1-3): ").strip() + + if user_input: + first_char = user_input[0] + if first_char in valid_choices: + choice = first_char + else: + print(f"错误: 输入 '{user_input}' 无效。请输入 1, 2 或 3。") + else: + print("错误: 输入不能为空。请输入 1, 2 或 3。") + + # 根据选择执行 + if choice == '1': + print("\n" + "=" * 60) + print("重要提示:") + print("1. 请确保AirSim仿真环境正在运行") + print("2. 已选择汽车模式 (Car Mode)") + print("3. 初始训练只有50回合,用于测试连接") + print("=" * 60) + + confirm = input("\n确认AirSim环境已启动?(y/n): ").strip().lower() + if confirm == 'y': + train_dqn_safety_navigation() + else: + print("请先启动AirSim环境再运行程序") + elif choice == '2': + model_path = None + while not model_path: + model_path = input("请输入模型路径 (例如: ./models/airsim_dqn_episode_10.pth): ").strip() + if not model_path: + print("错误: 输入不能为空。") + continue + + if os.path.exists(model_path): + print(f"从模型恢复训练: {model_path}") + train_dqn_safety_navigation(resume_model=model_path) + else: + print(f"错误: 模型文件不存在: {model_path}") + model_path = None + elif choice == '3': + model_path = None + while not model_path: + model_path = input("请输入要评估的模型路径: ").strip() + if not model_path: + print("错误: 输入不能为空。") + continue + + if os.path.exists(model_path): + print(f"评估模型: {model_path}") + evaluate_model(model_path) + else: + print(f"错误: 模型文件不存在: {model_path}") + model_path = None + + + # 在代码开头添加测试函数 + def test_airsim_connection(): + """测试AirSim连接""" + try: + import airsim + client = airsim.CarClient() + client.confirmConnection() + print("✓ 成功连接到AirSim服务器!") + + # 获取车辆状态 + state = client.getCarState() + print(f"车辆速度: {state.speed}") + + client.enableApiControl(True) + print("API控制已启用") + + return True + except Exception as e: + print(f"❌ 连接失败: {e}") + print("\n请确保:") + print("1. AirSim仿真环境正在运行") + print("2. 已选择汽车模式") + print("3. AirSim服务器IP地址正确") + return False + + + # 在主程序中调用 + if __name__ == "__main__": + print("测试AirSim连接...") + if test_airsim_connection(): + print("\n连接测试通过!可以开始训练。") + else: + print("\n连接测试失败,请检查AirSim环境。") \ No newline at end of file diff --git a/src/Safe_navigation/check_version.py b/src/Safe_navigation/check_version.py new file mode 100644 index 0000000000..d36e7ce000 --- /dev/null +++ b/src/Safe_navigation/check_version.py @@ -0,0 +1,30 @@ +import airsim +import pkg_resources +import inspect + +print("=== AirSim 环境诊断 ===") + +# 1. 检查安装的版本 +try: + version = pkg_resources.get_distribution("airsim").version + print(f"1. 已安装的 airsim 包版本: {version}") +except Exception as e: + print(f"1. 无法获取版本: {e}") + +# 2. 查看 CarClient 的构造函数签名 +print("\n2. CarClient.__init__ 接受的参数:") +try: + # 获取构造函数签名,跳过第一个参数'self' + sig = inspect.signature(airsim.CarClient.__init__) + params = list(sig.parameters.keys())[1:] # 移除'self' + print(" ", params) +except Exception as e: + print(f" 获取失败: {e}") + +# 3. 尝试导入其他可能相关的模块 +print("\n3. 尝试直接导入常用客户端...") +try: + from airsim import CarClient + print(" ✓ 成功从 airsim 导入 CarClient") +except ImportError as e: + print(f" ✗ 导入失败: {e}") \ No newline at end of file diff --git a/src/Safe_navigation/connect_airsim.py b/src/Safe_navigation/connect_airsim.py new file mode 100644 index 0000000000..f1561402f2 --- /dev/null +++ b/src/Safe_navigation/connect_airsim.py @@ -0,0 +1,51 @@ +import airsim +import time + + +def main(): + print("=== 尝试连接 AirSimNH (使用 airsim 1.8.1) ===") + print("重要:请先确保虚幻引擎中的 AirSimNH 已点击播放(Play)!\n") + + try: + # 1. 创建客户端(1.8.1版本的唯一正确方式) + client = airsim.CarClient() + print("✓ 客户端对象创建成功") + + # 2. 确认连接(这会尝试与仿真器通信) + client.confirmConnection() + print("✓ 已连接到AirSim仿真服务器") + + # 3. 启用控制 + client.enableApiControl(True) + print("✓ API控制已启用") + + # 4. 获取车辆状态,验证一切正常 + car_state = client.getCarState() + print(f"✓ 车辆状态获取成功 - 速度: {car_state.speed} km/h") + + # 5. 【可选】简单控制演示 + print("\n>>> 连接成功!开始简单控制演示...") + controls = airsim.CarControls() + controls.throttle = 0.5 + client.setCarControls(controls) + time.sleep(2) + controls.brake = 1.0 + controls.throttle = 0.0 + client.setCarControls(controls) + time.sleep(1) + print("演示结束。") + # 6. 释放控制 + client.enableApiControl(False) + print("控制权已释放。") + + except ConnectionRefusedError: + print("\n✗ 连接被拒绝。") + print(" 最可能的原因:虚幻引擎中的 AirSimNH 仿真没有启动。") + print(" 请打开虚幻引擎,加载AirSimNH项目,并点击顶部工具栏的蓝色【播放】(▶)按钮。") + except Exception as e: + print(f"\n✗ 连接过程中出错: {e}") + print(" 其他可能原因:防火墙阻止、端口占用或配置文件错误。") + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/src/Safe_navigation/logs/airsim_dqn_20251221_193518/events.out.tfevents.1766316918.YD.1800.0 b/src/Safe_navigation/logs/airsim_dqn_20251221_193518/events.out.tfevents.1766316918.YD.1800.0 new file mode 100644 index 0000000000000000000000000000000000000000..039f139958d42e73ad137673c1b26c7bd8a465b0 GIT binary patch literal 88 zcmeZZfPjCKJmzx#6rOYUTi`86Dc+=_#LPTB*Rs^S5-X!1JuaP+)V$*SqNM!9q7=R2 h(%js{qDsB;qRf)iBE3|Qs`#|boYZ)T$m5PPM*w1oA|n6* literal 0 HcmV?d00001 diff --git a/src/Safe_navigation/run_main.py b/src/Safe_navigation/run_main.py new file mode 100644 index 0000000000..ba4c30b1ac --- /dev/null +++ b/src/Safe_navigation/run_main.py @@ -0,0 +1,506 @@ +#!/usr/bin/env python3 +""" +AirSimNH 无人车完整仿真控制脚本 +功能:连接仿真器、手动控制车辆、采集传感器数据、监控车辆状态 +""" + +import airsim +import time +import numpy as np +import cv2 +import json +import os +from datetime import datetime +import threading +from collections import deque + + +class AirSimNHCarSimulator: + """AirSim无人车仿真主类""" + + def __init__(self, ip="127.0.0.1", port=41451, vehicle_name="PhysXCar"): + """ + 初始化仿真器连接 + + 参数: + ip: AirSim服务器IP地址 + port: AirSim服务器端口 + vehicle_name: 车辆名称,需与settings.json中一致 + """ + self.ip = ip + self.port = port + self.vehicle_name = vehicle_name + self.client = None + self.is_connected = False + self.is_api_control_enabled = False + self.running = False + self.data_log = [] + self.data_file = None + + # 传感器数据缓存 + self.sensor_data = { + "camera": deque(maxlen=100), + "imu": deque(maxlen=1000), + "gps": deque(maxlen=1000), + "lidar": deque(maxlen=100) + } + + # 创建数据保存目录 + timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") + self.data_dir = f"simulation_data_{timestamp}" + os.makedirs(self.data_dir, exist_ok=True) + + print(f"数据保存目录: {self.data_dir}") + + def connect(self): + """连接到AirSim仿真器""" + try: + print(f"正在连接到AirSim仿真器 {self.ip}:{self.port}...") + + # 创建客户端连接 + self.client = airsim.CarClient(ip=self.ip, port=self.port) + self.client.confirmConnection() + + # 检查车辆是否存在 + vehicles = self.client.listVehicles() + if self.vehicle_name not in vehicles: + print(f"警告: 车辆 '{self.vehicle_name}' 未找到,可用车辆: {vehicles}") + # 尝试使用找到的第一个车辆 + if vehicles: + self.vehicle_name = vehicles[0] + print(f"使用车辆: {self.vehicle_name}") + + self.is_connected = True + print("✓ 成功连接到AirSim仿真器!") + return True + + except Exception as e: + print(f"✗ 连接失败: {e}") + print("请确保:") + print("1. AirSimNH环境正在运行 (在虚幻引擎中启动)") + print("2. settings.json配置正确") + print("3. 网络连接正常") + return False + + def enable_api_control(self, enable=True): + """启用/禁用API控制""" + try: + self.client.enableApiControl(enable, vehicle_name=self.vehicle_name) + self.is_api_control_enabled = enable + + if enable: + print("✓ API控制已启用") + # 重置控制到初始状态 + controls = airsim.CarControls() + controls.throttle = 0 + controls.steering = 0 + controls.brake = 0 + controls.handbrake = False + self.client.setCarControls(controls, vehicle_name=self.vehicle_name) + else: + print("✓ API控制已禁用") + + return True + + except Exception as e: + print(f"✗ API控制设置失败: {e}") + return False + + def get_vehicle_state(self): + """获取完整的车辆状态信息""" + try: + state = self.client.getCarState(vehicle_name=self.vehicle_name) + + # 获取车辆物理信息 + kinematics = self.client.simGetVehiclePose(vehicle_name=self.vehicle_name) + + state_info = { + "timestamp": time.time(), + "speed_kmh": state.speed, + "speed_ms": state.speed / 3.6, + "position": { + "x": kinematics.position.x_val, + "y": kinematics.position.y_val, + "z": kinematics.position.z_val + }, + "orientation": { + "w": kinematics.orientation.w_val, + "x": kinematics.orientation.x_val, + "y": kinematics.orientation.y_val, + "z": kinematics.orientation.z_val + }, + "gear": state.gear, + "rpm": state.rpm, + "max_rpm": state.maxrpm, + "handbrake": state.handbrake, + "collision": state.collision.has_collided, + "collision_count": state.collision.collision_count + } + + return state_info + + except Exception as e: + print(f"获取车辆状态失败: {e}") + return None + + def capture_camera_images(self, camera_names=["front", "back", "left", "right"]): + """从多个摄像头捕获图像""" + images = {} + + for cam_name in camera_names: + try: + # 请求RGB图像 + responses = self.client.simGetImages([ + airsim.ImageRequest(cam_name, airsim.ImageType.Scene, False, False) + ], vehicle_name=self.vehicle_name) + + if responses and responses[0]: + img_response = responses[0] + + # 将图像数据转换为numpy数组 + img1d = np.frombuffer(img_response.image_data_uint8, dtype=np.uint8) + img_rgb = img1d.reshape(img_response.height, img_response.width, 3) + + # 保存图像到文件 + timestamp = datetime.now().strftime("%H%M%S_%f")[:-3] + filename = f"{self.data_dir}/{cam_name}_{timestamp}.png" + cv2.imwrite(filename, cv2.cvtColor(img_rgb, cv2.COLOR_RGB2BGR)) + + images[cam_name] = { + "filename": filename, + "shape": img_rgb.shape, + "timestamp": time.time() + } + + # 缓存数据 + self.sensor_data["camera"].append({ + "camera": cam_name, + "timestamp": time.time(), + "filename": filename + }) + + except Exception as e: + print(f"摄像头 '{cam_name}' 捕获失败: {e}") + + return images + + def get_imu_data(self): + """获取IMU传感器数据""" + try: + imu_data = self.client.getImuData(imu_name="Imu", vehicle_name=self.vehicle_name) + + data = { + "timestamp": time.time(), + "linear_acceleration": { + "x": imu_data.linear_acceleration.x_val, + "y": imu_data.linear_acceleration.y_val, + "z": imu_data.linear_acceleration.z_val + }, + "angular_velocity": { + "x": imu_data.angular_velocity.x_val, + "y": imu_data.angular_velocity.y_val, + "z": imu_data.angular_velocity.z_val + }, + "orientation": { + "w": imu_data.orientation.w_val, + "x": imu_data.orientation.x_val, + "y": imu_data.orientation.y_val, + "z": imu_data.orientation.z_val + } + } + + self.sensor_data["imu"].append(data) + return data + + except Exception as e: + print(f"获取IMU数据失败: {e}") + return None + + def get_gps_data(self): + """获取GPS数据""" + try: + gps_data = self.client.getGpsData(gps_name="Gps", vehicle_name=self.vehicle_name) + + data = { + "timestamp": time.time(), + "latitude": gps_data.gnss.geopoint.latitude, + "longitude": gps_data.gnss.geopoint.longitude, + "altitude": gps_data.gnss.geopoint.altitude, + "velocity": { + "x": gps_data.gnss.velocity.x_val, + "y": gps_data.gnss.velocity.y_val, + "z": gps_data.gnss.velocity.z_val + } + } + + self.sensor_data["gps"].append(data) + return data + + except Exception as e: + print(f"获取GPS数据失败: {e}") + return None + + def manual_control_demo(self, duration=10): + """ + 手动控制演示:前进、转向、停止 + + 参数: + duration: 演示总时长(秒) + """ + if not self.is_connected or not self.is_api_control_enabled: + print("错误: 请先连接并启用API控制") + return False + + print(f"\n开始手动控制演示 ({duration}秒)...") + print("操作序列: 加速 → 左转 → 右转 → 刹车停止") + + start_time = time.time() + sequence = 0 + + try: + while time.time() - start_time < duration: + elapsed = time.time() - start_time + + # 根据时间执行不同控制序列 + if elapsed < duration * 0.25: # 第一阶段:直线加速 + controls = airsim.CarControls() + controls.throttle = 0.7 + controls.steering = 0.0 + self.client.setCarControls(controls, vehicle_name=self.vehicle_name) + if sequence < 1: + print(" 阶段1: 直线加速") + sequence = 1 + + elif elapsed < duration * 0.5: # 第二阶段:左转 + controls = airsim.CarControls() + controls.throttle = 0.5 + controls.steering = 0.3 # 左转 + self.client.setCarControls(controls, vehicle_name=self.vehicle_name) + if sequence < 2: + print(" 阶段2: 左转") + sequence = 2 + + elif elapsed < duration * 0.75: # 第三阶段:右转 + controls = airsim.CarControls() + controls.throttle = 0.5 + controls.steering = -0.3 # 右转 + self.client.setCarControls(controls, vehicle_name=self.vehicle_name) + if sequence < 3: + print(" 阶段3: 右转") + sequence = 3 + + else: # 第四阶段:减速停止 + controls = airsim.CarControls() + controls.throttle = 0.0 + controls.brake = 1.0 + controls.steering = 0.0 + self.client.setCarControls(controls, vehicle_name=self.vehicle_name) + if sequence < 4: + print(" 阶段4: 刹车停止") + sequence = 4 + + # 实时显示车辆状态 + state = self.get_vehicle_state() + if state: + print(f"\r速度: {state['speed_kmh']:.1f} km/h | " + f"位置: ({state['position']['x']:.1f}, " + f"{state['position']['y']:.1f})", end="") + + # 采集传感器数据 + self.capture_camera_images(["front"]) # 只采集前摄像头 + self.get_imu_data() + self.get_gps_data() + + time.sleep(0.1) # 控制频率 10Hz + + print("\n✓ 手动控制演示完成") + return True + + except Exception as e: + print(f"\n✗ 控制演示出错: {e}") + return False + + def data_collection_demo(self, duration=5): + """数据采集演示:采集所有传感器数据""" + print(f"\n开始数据采集演示 ({duration}秒)...") + + start_time = time.time() + frame_count = 0 + + try: + while time.time() - start_time < duration: + frame_count += 1 + + # 采集所有摄像头图像 + images = self.capture_camera_images() + + # 采集IMU数据 + imu_data = self.get_imu_data() + + # 采集GPS数据 + gps_data = self.get_gps_data() + + # 获取车辆状态 + vehicle_state = self.get_vehicle_state() + + # 记录到日志 + log_entry = { + "frame": frame_count, + "timestamp": time.time(), + "images": len(images), + "imu_data": imu_data is not None, + "gps_data": gps_data is not None, + "vehicle_state": vehicle_state is not None + } + self.data_log.append(log_entry) + + print(f"\r采集帧: {frame_count} | " + f"图像: {len(images)} | " + f"速度: {vehicle_state['speed_kmh'] if vehicle_state else 'N/A':.1f} km/h", end="") + + time.sleep(0.2) # 5Hz采集频率 + + print(f"\n✓ 数据采集完成,共采集 {frame_count} 帧") + return True + + except Exception as e: + print(f"\n✗ 数据采集出错: {e}") + return False + + def save_simulation_data(self): + """保存所有仿真数据到文件""" + try: + # 保存车辆状态日志 + log_file = f"{self.data_dir}/simulation_log.json" + with open(log_file, 'w') as f: + json.dump(self.data_log, f, indent=2) + + # 保存传感器数据统计 + stats = { + "timestamp": datetime.now().isoformat(), + "vehicle_name": self.vehicle_name, + "camera_frames": len(self.sensor_data["camera"]), + "imu_samples": len(self.sensor_data["imu"]), + "gps_samples": len(self.sensor_data["gps"]), + "total_log_entries": len(self.data_log) + } + + stats_file = f"{self.data_dir}/simulation_stats.json" + with open(stats_file, 'w') as f: + json.dump(stats, f, indent=2) + + # 生成数据报告 + report_file = f"{self.data_dir}/report.txt" + with open(report_file, 'w') as f: + f.write("=" * 50 + "\n") + f.write("AirSim无人车仿真数据报告\n") + f.write("=" * 50 + "\n\n") + f.write(f"仿真时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n") + f.write(f"车辆名称: {self.vehicle_name}\n") + f.write(f"摄像头帧数: {stats['camera_frames']}\n") + f.write(f"IMU采样数: {stats['imu_samples']}\n") + f.write(f"GPS采样数: {stats['gps_samples']}\n") + f.write(f"日志条目: {stats['total_log_entries']}\n\n") + f.write("数据文件:\n") + for file in os.listdir(self.data_dir): + f.write(f" - {file}\n") + + print(f"\n✓ 仿真数据已保存到: {self.data_dir}") + print(f" 日志文件: {log_file}") + print(f" 统计数据: {stats_file}") + print(f" 报告文件: {report_file}") + + return True + + except Exception as e: + print(f"✗ 保存数据失败: {e}") + return False + + def run_full_demo(self, control_duration=15, data_duration=8): + """运行完整演示""" + print("=" * 60) + print("AirSimNH 无人车完整仿真演示") + print("=" * 60) + + # 步骤1: 连接仿真器 + if not self.connect(): + return False + + try: + # 步骤2: 启用API控制 + if not self.enable_api_control(True): + return False + + # 步骤3: 手动控制演示 + if not self.manual_control_demo(control_duration): + print("手动控制演示失败,继续其他演示...") + + # 短暂暂停,让车辆完全停止 + time.sleep(2) + + # 步骤4: 数据采集演示 + if not self.data_collection_demo(data_duration): + print("数据采集演示失败,继续保存数据...") + + # 步骤5: 保存数据 + self.save_simulation_data() + + return True + + finally: + # 步骤6: 清理和退出 + self.cleanup() + + def cleanup(self): + """清理资源""" + print("\n正在清理资源...") + + # 停止车辆 + if self.is_api_control_enabled: + controls = airsim.CarControls() + controls.brake = 1.0 + controls.handbrake = True + try: + self.client.setCarControls(controls, vehicle_name=self.vehicle_name) + except: + pass + + # 禁用API控制 + try: + self.enable_api_control(False) + except: + pass + + print("✓ 清理完成") + + +def main(): + """主函数""" + # 创建仿真器实例 + simulator = AirSimNHCarSimulator( + ip="127.0.0.1", + port=41451, + vehicle_name="PhysXCar" + ) + + # 运行完整演示 + try: + simulator.run_full_demo( + control_duration=20, # 控制演示时长(秒) + data_duration=10 # 数据采集时长(秒) + ) + + print("\n" + "=" * 60) + print("仿真演示完成!") + print("=" * 60) + + except KeyboardInterrupt: + print("\n\n仿真被用户中断") + simulator.cleanup() + except Exception as e: + print(f"\n仿真出错: {e}") + simulator.cleanup() + + +if __name__ == "__main__": + main() \ No newline at end of file From 6e69898fc21c5077088db77ab8bc5a2b266f2429 Mon Sep 17 00:00:00 2001 From: solfdd <1006434858@qq.com> Date: Mon, 22 Dec 2025 09:46:35 +0800 Subject: [PATCH 03/16] =?UTF-8?q?=E6=8F=90=E4=BA=A4=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E5=B9=B6=E5=88=A0=E9=99=A4.idea=E5=92=8C=5Fpycache?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/.gitignore | 5 -- .../inspectionProfiles/profiles_settings.xml | 6 -- .idea/misc.xml | 7 -- .idea/modules.xml | 8 -- .idea/nn.iml | 18 ----- .idea/vcs.xml | 6 -- .idea/workspace.xml | 75 ++++++++++++++++++ .../car.cpython-312-pytest-9.0.2.pyc | Bin 36820 -> 0 bytes ...onnect_airsim.cpython-312-pytest-9.0.2.pyc | Bin 6417 -> 0 bytes 9 files changed, 75 insertions(+), 50 deletions(-) delete mode 100644 .idea/.gitignore delete mode 100644 .idea/inspectionProfiles/profiles_settings.xml delete mode 100644 .idea/misc.xml delete mode 100644 .idea/modules.xml delete mode 100644 .idea/nn.iml delete mode 100644 .idea/vcs.xml create mode 100644 .idea/workspace.xml delete mode 100644 src/Safe_navigation/__pycache__/car.cpython-312-pytest-9.0.2.pyc delete mode 100644 src/Safe_navigation/__pycache__/connect_airsim.cpython-312-pytest-9.0.2.pyc diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index 10b731c518..0000000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -# 默认忽略的文件 -/shelf/ -/workspace.xml -# 基于编辑器的 HTTP 客户端请求 -/httpRequests/ diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml deleted file mode 100644 index 105ce2da2d..0000000000 --- a/.idea/inspectionProfiles/profiles_settings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index 77773ffb78..0000000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index 0e01bed9d6..0000000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/nn.iml b/.idea/nn.iml deleted file mode 100644 index 28462e1238..0000000000 --- a/.idea/nn.iml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 35eb1ddfbb..0000000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml new file mode 100644 index 0000000000..ee967e3f4d --- /dev/null +++ b/.idea/workspace.xml @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + { + "associatedIndex": 3 +} + + + + { + "keyToString": { + "ModuleVcsDetector.initialDetectionPerformed": "true", + "Python 测试.pytest (car.py 内).executor": "Run", + "Python 测试.pytest (connect_airsim.py 内).executor": "Run", + "Python 测试.pytest (test_airsim.py 内).executor": "Run", + "Python.car.executor": "Run", + "Python.check_version.executor": "Run", + "Python.connect_airsim.executor": "Run", + "Python.run_main.executor": "Run", + "Python.代码.executor": "Run", + "RunOnceActivity.ShowReadmeOnStart": "true", + "RunOnceActivity.TerminalTabsStorage.copyFrom.TerminalArrangementManager.252": "true", + "RunOnceActivity.git.unshallow": "true", + "git-widget-placeholder": "github", + "ignore.virus.scanning.warn.message": "true", + "last_opened_file_path": "C:/nn", + "settings.editor.selected.configurable": "reference.settings.ide.settings.file-colors" + } +} + + + + + + + + + + 1766305867927 + + + + \ No newline at end of file diff --git a/src/Safe_navigation/__pycache__/car.cpython-312-pytest-9.0.2.pyc b/src/Safe_navigation/__pycache__/car.cpython-312-pytest-9.0.2.pyc deleted file mode 100644 index 639510e71852f9ac75bb3e29bfb82d18c606b6e8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 36820 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 Xi^>ZpA}TAahOaT Date: Mon, 22 Dec 2025 11:08:02 +0800 Subject: [PATCH 04/16] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E5=B9=B6=E8=BF=90=E8=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/workspace.xml | 9 +- src/Safe_navigation/car.py | 846 ------------------ src/Safe_navigation/check_version.py | 30 - .../events.out.tfevents.1766316918.YD.1800.0 | Bin 88 -> 0 bytes .../report.txt | 15 + .../simulation_log.json | 10 + .../simulation_stats.json | 8 + 7 files changed, 36 insertions(+), 882 deletions(-) delete mode 100644 src/Safe_navigation/car.py delete mode 100644 src/Safe_navigation/check_version.py delete mode 100644 src/Safe_navigation/logs/airsim_dqn_20251221_193518/events.out.tfevents.1766316918.YD.1800.0 create mode 100644 src/Safe_navigation/simulation_data_20251222_110207/report.txt create mode 100644 src/Safe_navigation/simulation_data_20251222_110207/simulation_log.json create mode 100644 src/Safe_navigation/simulation_data_20251222_110207/simulation_stats.json diff --git a/.idea/workspace.xml b/.idea/workspace.xml index ee967e3f4d..30e0b698e5 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -5,12 +5,9 @@ - - - - - - + + + - - - - - +