From 9a8943d64dfc3aa9ca16ad32d4ad232fdcfd48b9 Mon Sep 17 00:00:00 2001 From: ou-yang220 <2101542906@qq.com> Date: Sun, 21 Dec 2025 17:08:39 +0800 Subject: [PATCH 01/11] =?UTF-8?q?=E8=B7=AF=E4=BE=A7=E6=84=9F=E7=9F=A5?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E9=9B=86=E9=A2=84=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/V2X_edge_intelligence/src/main.py | 110 ++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 src/V2X_edge_intelligence/src/main.py diff --git a/src/V2X_edge_intelligence/src/main.py b/src/V2X_edge_intelligence/src/main.py new file mode 100644 index 0000000000..f5a8a90ec2 --- /dev/null +++ b/src/V2X_edge_intelligence/src/main.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +路侧感知数据集预处理Carla 0.9.10终极适配版 +运行前:先启动D:\WindowsNoEditor\CarlaUE4.exe +""" +import sys +import os +import time +import json +from typing import Dict, Any + +# ========== 加载Carla egg文件 ========== +CARLA_EGG_PATH = r"D:\WindowsNoEditor\PythonAPI\carla\dist\carla-0.9.10-py3.7-win-amd64.egg" +sys.path.append(CARLA_EGG_PATH) + +# 导入Carla并容错 +try: + import carla + print(f"✅ 成功加载Carla API(0.9.10适配版)") +except Exception as e: + print(f"❌ 加载Carla API失败:{str(e)}") + sys.exit(1) + +# ========== 配置项 ========== +CARLA_HOST = "localhost" +CARLA_PORT = 2000 +TIMEOUT = 10.0 +SAVE_DIR = "carla_sensor_data" + +# ========== 连接模拟器 ========== +def connect_carla() -> carla.World: + """连接Carla 0.9.10模拟器""" + try: + client = carla.Client(CARLA_HOST, CARLA_PORT) + client.set_timeout(TIMEOUT) + world = client.get_world() + print(f"✅ 成功连接Carla模拟器:{CARLA_HOST}:{CARLA_PORT}") + return world + except Exception as e: + print(f"❌ 连接失败:{str(e)}") + sys.exit(1) + +# ========== 获取路侧数据(完全适配0.9.10) ========== +def get_roadside_data(world: carla.World) -> Dict[str, Any]: + """获取路侧感知数据(避开所有新版API)""" + blueprint_lib = world.get_blueprint_library() + + # 1. 激光雷达配置(仅设置参数,不获取返回值,避免API冲突) + lidar_bp = blueprint_lib.find("sensor.lidar.ray_cast") + # 0.9.10仅支持基础参数,且无需获取返回值 + lidar_bp.set_attribute("range", "100") + lidar_bp.set_attribute("rotation_frequency", "10") + + # 2. 摄像头配置(同样仅设置,不获取) + camera_bp = blueprint_lib.find("sensor.camera.rgb") + camera_bp.set_attribute("image_size_x", "1920") + camera_bp.set_attribute("image_size_y", "1080") + + # 3. 车辆检测(0.9.10核心API兼容) + vehicles = world.get_actors().filter("vehicle.*") + vehicle_list = [] + for v in vehicles: + trans = v.get_transform() + vehicle_list.append({ + "id": v.id, + "model": v.type_id, + "x": float(trans.location.x), + "y": float(trans.location.y), + "z": float(trans.location.z), + "yaw": float(trans.rotation.yaw) + }) + + # 4. 整合数据(不依赖传感器属性获取,避免API错误) + return { + "timestamp": time.strftime("%Y%m%d_%H%M%S"), + "roadside_id": "RSU_001", + "lidar_config": { + "range": "100m", + "rotation_frequency": "10Hz" + }, + "camera_config": { + "resolution": "1920x1080" + }, + "detected_vehicles": vehicle_list, + "vehicle_count": len(vehicle_list) + } + +# ========== 保存数据 ========== +def save_data(data: Dict[str, Any]) -> None: + """保存数据到JSON文件""" + os.makedirs(SAVE_DIR, exist_ok=True) + file_name = f"roadside_data_{data['timestamp']}.json" + file_path = os.path.join(SAVE_DIR, file_name) + with open(file_path, "w", encoding="utf-8") as f: + json.dump(data, f, ensure_ascii=False, indent=4) + print(f"✅ 数据已保存:{file_path}") + +# ========== 主函数 ========== +def main(): + print("===== Carla 0.9.10 路侧数据采集 =====\n") + world = connect_carla() + print("🔍 正在采集路侧感知数据...") + sensor_data = get_roadside_data(world) + save_data(sensor_data) + print(f"\n📊 采集完成!共检测到 {sensor_data['vehicle_count']} 辆车辆") + print("\n===== 操作结束 =====\n") + +if __name__ == "__main__": + main() \ No newline at end of file From fd0f9d5e9be9f39371fa8749fb9637b707c4c3df Mon Sep 17 00:00:00 2001 From: ou-yang220 <2101542906@qq.com> Date: Mon, 22 Dec 2025 02:22:21 +0800 Subject: [PATCH 02/11] =?UTF-8?q?Carla=200.9.10=E8=B7=AF=E4=BE=A7=E6=84=9F?= =?UTF-8?q?=E7=9F=A5=E6=95=B0=E6=8D=AE=E9=87=87=E9=9B=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/V2X_edge_intelligence/src/main.py | 195 ++++++++++++++++++-------- 1 file changed, 140 insertions(+), 55 deletions(-) diff --git a/src/V2X_edge_intelligence/src/main.py b/src/V2X_edge_intelligence/src/main.py index f5a8a90ec2..61928b7508 100644 --- a/src/V2X_edge_intelligence/src/main.py +++ b/src/V2X_edge_intelligence/src/main.py @@ -1,13 +1,14 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- """ -路侧感知数据集预处理Carla 0.9.10终极适配版 -运行前:先启动D:\WindowsNoEditor\CarlaUE4.exe +Carla 0.9.10 路侧感知采集(车辆生成在视角前,方便录视频) +运行前:启动D:\WindowsNoEditor\CarlaUE4.exe,等待1分钟初始化 """ import sys import os import time import json +import math # 核心修正:添加math库导入 from typing import Dict, Any # ========== 加载Carla egg文件 ========== @@ -17,6 +18,7 @@ # 导入Carla并容错 try: import carla + print(f"✅ 成功加载Carla API(0.9.10适配版)") except Exception as e: print(f"❌ 加载Carla API失败:{str(e)}") @@ -25,86 +27,169 @@ # ========== 配置项 ========== CARLA_HOST = "localhost" CARLA_PORT = 2000 -TIMEOUT = 10.0 +TIMEOUT = 20.0 SAVE_DIR = "carla_sensor_data" +VEHICLE_NUM = 3 # 生成3辆(避免画面拥挤,适合录视频) + # ========== 连接模拟器 ========== -def connect_carla() -> carla.World: - """连接Carla 0.9.10模拟器""" +def connect_carla(): + """连接Carla,获取client、world、视角原点""" try: client = carla.Client(CARLA_HOST, CARLA_PORT) client.set_timeout(TIMEOUT) - world = client.get_world() - print(f"✅ 成功连接Carla模拟器:{CARLA_HOST}:{CARLA_PORT}") - return world + world = client.load_world("Town01") + time.sleep(3) + + # 获取视角当前的位置(第一人称视角原点) + spectator = world.get_spectator() # 视角对象 + spectator_transform = spectator.get_transform() + print(f"✅ 视角当前位置:x={spectator_transform.location.x:.1f}, y={spectator_transform.location.y:.1f}") + print(f"✅ 成功连接Carla(Town01地图):{CARLA_HOST}:{CARLA_PORT}") + return client, world, spectator_transform except Exception as e: print(f"❌ 连接失败:{str(e)}") sys.exit(1) -# ========== 获取路侧数据(完全适配0.9.10) ========== -def get_roadside_data(world: carla.World) -> Dict[str, Any]: - """获取路侧感知数据(避开所有新版API)""" + +# ========== 在视角前生成车辆(录视频专用) ========== +def spawn_vehicles_in_view(world, spectator_transform): + """在视角正前方5-15米处生成车辆,录视频时直接可见""" + # 1. 清除现有车辆 + vehicles = world.get_actors().filter("vehicle.*") + for v in vehicles: + v.destroy() + print(f"🗑️ 已清除 {len(vehicles)} 辆旧车辆") + + # 2. 选择显眼的车型(黑色特斯拉,录视频更清晰) blueprint_lib = world.get_blueprint_library() + vehicle_bp = blueprint_lib.find("vehicle.tesla.model3") + vehicle_bp.set_attribute("color", "0,0,0") # 设置黑色(RGB) + if not vehicle_bp: + vehicle_bp = blueprint_lib.filter("vehicle.*")[0] - # 1. 激光雷达配置(仅设置参数,不获取返回值,避免API冲突) - lidar_bp = blueprint_lib.find("sensor.lidar.ray_cast") - # 0.9.10仅支持基础参数,且无需获取返回值 - lidar_bp.set_attribute("range", "100") - lidar_bp.set_attribute("rotation_frequency", "10") + # 3. 计算视角正前方的生成位置(核心!) + # 视角正前方5米、8米、11米处,左右偏移1-2米(避免重叠) + spawn_positions = [ + # 正前方5米,偏右1米 + carla.Location( + x=spectator_transform.location.x + 5 * math.cos(math.radians(spectator_transform.rotation.yaw)), + y=spectator_transform.location.y + 5 * math.sin(math.radians(spectator_transform.rotation.yaw)) + 1, + z=0.5 + ), + # 正前方8米,偏左1米 + carla.Location( + x=spectator_transform.location.x + 8 * math.cos(math.radians(spectator_transform.rotation.yaw)), + y=spectator_transform.location.y + 8 * math.sin(math.radians(spectator_transform.rotation.yaw)) - 1, + z=0.5 + ), + # 正前方11米,正中间 + carla.Location( + x=spectator_transform.location.x + 11 * math.cos(math.radians(spectator_transform.rotation.yaw)), + y=spectator_transform.location.y + 11 * math.sin(math.radians(spectator_transform.rotation.yaw)), + z=0.5 + ) + ] - # 2. 摄像头配置(同样仅设置,不获取) - camera_bp = blueprint_lib.find("sensor.camera.rgb") - camera_bp.set_attribute("image_size_x", "1920") - camera_bp.set_attribute("image_size_y", "1080") + # 4. 逐个生成车辆(面向视角,录视频更美观) + spawned_num = 0 + for i in range(VEHICLE_NUM): + try: + # 车辆朝向视角(yaw和视角一致+180度) + vehicle_yaw = spectator_transform.rotation.yaw + 180 + transform = carla.Transform(spawn_positions[i], carla.Rotation(yaw=vehicle_yaw)) + + vehicle = world.spawn_actor(vehicle_bp, transform) + if vehicle: + spawned_num += 1 + print(f"🚗 成功生成第{i + 1}辆车(在视角前{5 + i * 3}米处)") + time.sleep(1) + except Exception as e: + print(f"⚠️ 第{i + 1}辆车生成失败:{str(e)}") + continue + + print(f"✅ 车辆生成完成:成功 {spawned_num}/{VEHICLE_NUM} 辆") + return spawned_num + + +# ========== 采集路侧数据 ========== +def get_roadside_data(world): + """采集数据,兼容录视频场景""" + try: + lidar_cfg = {"range": "100m", "freq": "10Hz"} + camera_cfg = {"resolution": "1920x1080"} + + vehicles = world.get_actors().filter("vehicle.*") + vehicle_data = [] + for v in vehicles: + trans = v.get_transform() + vehicle_data.append({ + "id": v.id, + "model": v.type_id, + "x": float(trans.location.x), + "y": float(trans.location.y), + "z": float(trans.location.z), + "yaw": float(trans.rotation.yaw) + }) + + return { + "timestamp": time.strftime("%Y%m%d_%H%M%S"), + "roadside_id": "RSU_001", + "lidar_config": lidar_cfg, + "camera_config": camera_cfg, + "detected_vehicles": vehicle_data, + "vehicle_count": len(vehicle_data) + } + except Exception as e: + print(f"⚠️ 采集数据异常:{str(e)}") + return {"timestamp": time.strftime("%Y%m%d_%H%M%S"), "vehicle_count": 0} - # 3. 车辆检测(0.9.10核心API兼容) - vehicles = world.get_actors().filter("vehicle.*") - vehicle_list = [] - for v in vehicles: - trans = v.get_transform() - vehicle_list.append({ - "id": v.id, - "model": v.type_id, - "x": float(trans.location.x), - "y": float(trans.location.y), - "z": float(trans.location.z), - "yaw": float(trans.rotation.yaw) - }) - - # 4. 整合数据(不依赖传感器属性获取,避免API错误) - return { - "timestamp": time.strftime("%Y%m%d_%H%M%S"), - "roadside_id": "RSU_001", - "lidar_config": { - "range": "100m", - "rotation_frequency": "10Hz" - }, - "camera_config": { - "resolution": "1920x1080" - }, - "detected_vehicles": vehicle_list, - "vehicle_count": len(vehicle_list) - } # ========== 保存数据 ========== -def save_data(data: Dict[str, Any]) -> None: - """保存数据到JSON文件""" - os.makedirs(SAVE_DIR, exist_ok=True) +def save_data(data): + """保存数据到绝对路径""" + save_path = os.path.abspath(SAVE_DIR) + os.makedirs(save_path, exist_ok=True) file_name = f"roadside_data_{data['timestamp']}.json" - file_path = os.path.join(SAVE_DIR, file_name) + file_path = os.path.join(save_path, file_name) with open(file_path, "w", encoding="utf-8") as f: json.dump(data, f, ensure_ascii=False, indent=4) print(f"✅ 数据已保存:{file_path}") + # ========== 主函数 ========== def main(): - print("===== Carla 0.9.10 路侧数据采集 =====\n") - world = connect_carla() + print("===== Carla 0.9.10 路侧数据采集(录视频专用) =====\n") + # 1. 连接模拟器,获取视角位置 + client, world, spectator_transform = connect_carla() + + # 2. 在视角前生成车辆 + spawn_vehicles_in_view(world, spectator_transform) + + # 3. 调整视角稍微向下(录视频时车辆更完整) + spectator = world.get_spectator() + new_rotation = carla.Rotation( + pitch=spectator_transform.rotation.pitch - 5, # 向下5度 + yaw=spectator_transform.rotation.yaw, + roll=spectator_transform.rotation.roll + ) + spectator.set_transform(carla.Transform(spectator_transform.location, new_rotation)) + + # 4. 等待车辆加载 + time.sleep(2) + + # 5. 采集数据 print("🔍 正在采集路侧感知数据...") sensor_data = get_roadside_data(world) + + # 6. 保存数据 save_data(sensor_data) + + # 7. 输出结果 print(f"\n📊 采集完成!共检测到 {sensor_data['vehicle_count']} 辆车辆") - print("\n===== 操作结束 =====\n") + print("\n💡 提示:现在可以开始录制Carla窗口视频,车辆就在视角前!") + print("===== 操作结束 =====\n") + if __name__ == "__main__": main() \ No newline at end of file From 24b6231cab146bab16881137f72144d95f326615 Mon Sep 17 00:00:00 2001 From: ou-yang220 <2101542906@qq.com> Date: Mon, 22 Dec 2025 15:06:04 +0800 Subject: [PATCH 03/11] =?UTF-8?q?Carla=200.9.10=E8=B7=AF=E4=BE=A7=E6=84=9F?= =?UTF-8?q?=E7=9F=A5=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/V2X_edge_intelligence/src/main.py | 154 +++++++++++++++++++------- 1 file changed, 116 insertions(+), 38 deletions(-) diff --git a/src/V2X_edge_intelligence/src/main.py b/src/V2X_edge_intelligence/src/main.py index 61928b7508..9fd1ed1404 100644 --- a/src/V2X_edge_intelligence/src/main.py +++ b/src/V2X_edge_intelligence/src/main.py @@ -1,14 +1,15 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- """ -Carla 0.9.10 路侧感知采集(车辆生成在视角前,方便录视频) +Carla 0.9.10 路侧感知采集(可视化版) +适配0.9.10:移除draw_circle,用draw_line模拟激光雷达范围 运行前:启动D:\WindowsNoEditor\CarlaUE4.exe,等待1分钟初始化 """ import sys import os import time import json -import math # 核心修正:添加math库导入 +import math from typing import Dict, Any # ========== 加载Carla egg文件 ========== @@ -29,7 +30,10 @@ CARLA_PORT = 2000 TIMEOUT = 20.0 SAVE_DIR = "carla_sensor_data" -VEHICLE_NUM = 3 # 生成3辆(避免画面拥挤,适合录视频) +VEHICLE_NUM = 3 +# 可视化配置 +VISUALIZATION_DURATION = 30.0 # 可视化效果持续30秒 +LIDAR_RANGE = 100.0 # 激光雷达范围 # ========== 连接模拟器 ========== @@ -41,8 +45,8 @@ def connect_carla(): world = client.load_world("Town01") time.sleep(3) - # 获取视角当前的位置(第一人称视角原点) - spectator = world.get_spectator() # 视角对象 + # 获取视角当前的位置 + spectator = world.get_spectator() spectator_transform = spectator.get_transform() print(f"✅ 视角当前位置:x={spectator_transform.location.x:.1f}, y={spectator_transform.location.y:.1f}") print(f"✅ 成功连接Carla(Town01地图):{CARLA_HOST}:{CARLA_PORT}") @@ -52,38 +56,34 @@ def connect_carla(): sys.exit(1) -# ========== 在视角前生成车辆(录视频专用) ========== +# ========== 在视角前生成车辆 ========== def spawn_vehicles_in_view(world, spectator_transform): - """在视角正前方5-15米处生成车辆,录视频时直接可见""" + """在视角正前方生成车辆,返回生成的车辆列表""" # 1. 清除现有车辆 vehicles = world.get_actors().filter("vehicle.*") for v in vehicles: v.destroy() print(f"🗑️ 已清除 {len(vehicles)} 辆旧车辆") - # 2. 选择显眼的车型(黑色特斯拉,录视频更清晰) + # 2. 选择黑色特斯拉 blueprint_lib = world.get_blueprint_library() vehicle_bp = blueprint_lib.find("vehicle.tesla.model3") - vehicle_bp.set_attribute("color", "0,0,0") # 设置黑色(RGB) + vehicle_bp.set_attribute("color", "0,0,0") if not vehicle_bp: vehicle_bp = blueprint_lib.filter("vehicle.*")[0] - # 3. 计算视角正前方的生成位置(核心!) - # 视角正前方5米、8米、11米处,左右偏移1-2米(避免重叠) + # 3. 计算视角正前方生成位置 spawn_positions = [ - # 正前方5米,偏右1米 carla.Location( x=spectator_transform.location.x + 5 * math.cos(math.radians(spectator_transform.rotation.yaw)), y=spectator_transform.location.y + 5 * math.sin(math.radians(spectator_transform.rotation.yaw)) + 1, z=0.5 ), - # 正前方8米,偏左1米 carla.Location( x=spectator_transform.location.x + 8 * math.cos(math.radians(spectator_transform.rotation.yaw)), y=spectator_transform.location.y + 8 * math.sin(math.radians(spectator_transform.rotation.yaw)) - 1, z=0.5 ), - # 正前方11米,正中间 carla.Location( x=spectator_transform.location.x + 11 * math.cos(math.radians(spectator_transform.rotation.yaw)), y=spectator_transform.location.y + 11 * math.sin(math.radians(spectator_transform.rotation.yaw)), @@ -91,37 +91,110 @@ def spawn_vehicles_in_view(world, spectator_transform): ) ] - # 4. 逐个生成车辆(面向视角,录视频更美观) - spawned_num = 0 + # 4. 逐个生成车辆并记录 + spawned_vehicles = [] for i in range(VEHICLE_NUM): try: - # 车辆朝向视角(yaw和视角一致+180度) vehicle_yaw = spectator_transform.rotation.yaw + 180 transform = carla.Transform(spawn_positions[i], carla.Rotation(yaw=vehicle_yaw)) - vehicle = world.spawn_actor(vehicle_bp, transform) if vehicle: - spawned_num += 1 + spawned_vehicles.append(vehicle) print(f"🚗 成功生成第{i + 1}辆车(在视角前{5 + i * 3}米处)") time.sleep(1) except Exception as e: print(f"⚠️ 第{i + 1}辆车生成失败:{str(e)}") continue - print(f"✅ 车辆生成完成:成功 {spawned_num}/{VEHICLE_NUM} 辆") - return spawned_num + print(f"✅ 车辆生成完成:成功 {len(spawned_vehicles)}/{VEHICLE_NUM} 辆") + return spawned_vehicles + + +# ========== 在CarlaUE4中可视化运行效果(适配0.9.10) ========== +def visualize_in_carla(world, spectator_transform, spawned_vehicles): + """在CarlaUE4窗口中绘制:车辆ID标注、激光雷达范围(用线模拟)、路侧单元位置""" + debug = world.debug # Carla 0.9.10调试工具 + + # 1. 绘制路侧单元(RSU)位置(红色立方体+文字) + rsu_location = spectator_transform.location + debug.draw_box( + box=carla.BoundingBox(rsu_location, carla.Vector3D(1, 1, 2)), + rotation=spectator_transform.rotation, + thickness=0.1, + color=carla.Color(255, 0, 0), # 红色 + life_time=VISUALIZATION_DURATION + ) + debug.draw_string( + rsu_location + carla.Location(z=2), + "RSU_001(路侧单元)", + color=carla.Color(255, 0, 0), + life_time=VISUALIZATION_DURATION + ) + + # 2. 模拟绘制激光雷达范围(替换draw_circle,0.9.10支持) + # 用多条线绘制圆形轮廓,模拟100米激光雷达范围 + center = rsu_location + num_segments = 36 # 36条线组成圆形,足够平滑 + for i in range(num_segments): + # 计算线段起点和终点 + angle1 = math.radians(i * 10) + angle2 = math.radians((i + 1) * 10) + start = carla.Location( + x=center.x + LIDAR_RANGE * math.cos(angle1), + y=center.y + LIDAR_RANGE * math.sin(angle1), + z=center.z + 0.1 # 略高于地面,避免被遮挡 + ) + end = carla.Location( + x=center.x + LIDAR_RANGE * math.cos(angle2), + y=center.y + LIDAR_RANGE * math.sin(angle2), + z=center.z + 0.1 + ) + # 绘制蓝色线段 + debug.draw_line( + start, end, + thickness=0.5, + color=carla.Color(0, 0, 255), # 蓝色 + life_time=VISUALIZATION_DURATION + ) + # 标注激光雷达范围文字 + debug.draw_string( + center + carla.Location(z=3), + f"激光雷达范围:{LIDAR_RANGE}m", + color=carla.Color(0, 0, 255), + life_time=VISUALIZATION_DURATION + ) + + # 3. 为每辆车添加3D标注(绿色立方体+黄色文字) + for idx, vehicle in enumerate(spawned_vehicles): + v_loc = vehicle.get_transform().location + # 绘制车辆包围盒 + debug.draw_box( + box=carla.BoundingBox(v_loc, carla.Vector3D(2, 1, 1)), + rotation=vehicle.get_transform().rotation, + thickness=0.1, + color=carla.Color(0, 255, 0), # 绿色 + life_time=VISUALIZATION_DURATION + ) + # 绘制车辆ID和坐标 + debug.draw_string( + v_loc + carla.Location(z=1.5), + f"车辆{idx + 1}\nID:{vehicle.id}\nx:{v_loc.x:.1f}, y:{v_loc.y:.1f}", + color=carla.Color(255, 255, 0), # 黄色 + life_time=VISUALIZATION_DURATION + ) + + print(f"✅ 可视化效果已绘制在CarlaUE4窗口(持续{VISUALIZATION_DURATION}秒)") # ========== 采集路侧数据 ========== -def get_roadside_data(world): - """采集数据,兼容录视频场景""" +def get_roadside_data(world, spawned_vehicles, spectator_transform): + """采集数据,兼容可视化场景""" try: - lidar_cfg = {"range": "100m", "freq": "10Hz"} + lidar_cfg = {"range": f"{LIDAR_RANGE}m", "freq": "10Hz"} camera_cfg = {"resolution": "1920x1080"} - vehicles = world.get_actors().filter("vehicle.*") vehicle_data = [] - for v in vehicles: + for v in spawned_vehicles: trans = v.get_transform() vehicle_data.append({ "id": v.id, @@ -135,6 +208,11 @@ def get_roadside_data(world): return { "timestamp": time.strftime("%Y%m%d_%H%M%S"), "roadside_id": "RSU_001", + "rsu_location": { + "x": float(spectator_transform.location.x), + "y": float(spectator_transform.location.y), + "z": float(spectator_transform.location.z) + }, "lidar_config": lidar_cfg, "camera_config": camera_cfg, "detected_vehicles": vehicle_data, @@ -159,35 +237,35 @@ def save_data(data): # ========== 主函数 ========== def main(): - print("===== Carla 0.9.10 路侧数据采集(录视频专用) =====\n") - # 1. 连接模拟器,获取视角位置 + print("===== Carla 0.9.10 路侧感知采集(可视化版) =====\n") + # 1. 连接模拟器 client, world, spectator_transform = connect_carla() - # 2. 在视角前生成车辆 - spawn_vehicles_in_view(world, spectator_transform) + # 2. 生成车辆 + spawned_vehicles = spawn_vehicles_in_view(world, spectator_transform) - # 3. 调整视角稍微向下(录视频时车辆更完整) + # 3. 可视化运行效果(核心:CarlaUE4内直接展示) + visualize_in_carla(world, spectator_transform, spawned_vehicles) + + # 4. 调整视角 spectator = world.get_spectator() new_rotation = carla.Rotation( - pitch=spectator_transform.rotation.pitch - 5, # 向下5度 + pitch=spectator_transform.rotation.pitch - 5, yaw=spectator_transform.rotation.yaw, roll=spectator_transform.rotation.roll ) spectator.set_transform(carla.Transform(spectator_transform.location, new_rotation)) - # 4. 等待车辆加载 - time.sleep(2) - - # 5. 采集数据 + # 5. 采集数据(修正:传入spectator_transform) print("🔍 正在采集路侧感知数据...") - sensor_data = get_roadside_data(world) + sensor_data = get_roadside_data(world, spawned_vehicles, spectator_transform) # 6. 保存数据 save_data(sensor_data) # 7. 输出结果 print(f"\n📊 采集完成!共检测到 {sensor_data['vehicle_count']} 辆车辆") - print("\n💡 提示:现在可以开始录制Carla窗口视频,车辆就在视角前!") + print(f"\n💡 可视化效果在CarlaUE4窗口持续{VISUALIZATION_DURATION}秒,可开始录视频!") print("===== 操作结束 =====\n") From 5e92ca80b40851669e708e4a7160c23e88e3ef86 Mon Sep 17 00:00:00 2001 From: ou-yang220 <2101542906@qq.com> Date: Mon, 22 Dec 2025 19:48:39 +0800 Subject: [PATCH 04/11] =?UTF-8?q?Carla=200.9.10=20=E8=B7=AF=E4=BE=A7?= =?UTF-8?q?=E6=84=9F=E7=9F=A5=E9=87=87=E9=9B=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/V2X_edge_intelligence/src/main.py | 73 +++++++++++++++++++-------- 1 file changed, 51 insertions(+), 22 deletions(-) diff --git a/src/V2X_edge_intelligence/src/main.py b/src/V2X_edge_intelligence/src/main.py index 9fd1ed1404..ccfb00d65f 100644 --- a/src/V2X_edge_intelligence/src/main.py +++ b/src/V2X_edge_intelligence/src/main.py @@ -3,7 +3,7 @@ """ Carla 0.9.10 路侧感知采集(可视化版) 适配0.9.10:移除draw_circle,用draw_line模拟激光雷达范围 -运行前:启动D:\WindowsNoEditor\CarlaUE4.exe,等待1分钟初始化 +运行前:启动CarlaUE4.exe,等待1分钟初始化 """ import sys import os @@ -12,20 +12,53 @@ import math from typing import Dict, Any -# ========== 加载Carla egg文件 ========== -CARLA_EGG_PATH = r"D:\WindowsNoEditor\PythonAPI\carla\dist\carla-0.9.10-py3.7-win-amd64.egg" -sys.path.append(CARLA_EGG_PATH) -# 导入Carla并容错 -try: - import carla +# ========== 加载Carla egg文件(移除绝对路径,适配多环境) ========== +def load_carla_egg(): + """ + 加载Carla egg文件的容错逻辑: + 1. 优先从CARLA_EGG_PATH环境变量读取 + 2. 其次从Carla默认安装路径查找 + 3. 最后提示用户手动指定 + """ + # 1. 从环境变量获取(推荐,用户可灵活配置) + carla_egg_path = os.getenv("CARLA_EGG_PATH") + if carla_egg_path and os.path.exists(carla_egg_path): + sys.path.append(carla_egg_path) + return True + + # 2. 尝试Carla默认安装路径(Windows) + default_paths = [ + # 默认安装路径 + r"CarlaUE4\PythonAPI\carla\dist\carla-0.9.10-py3.7-win-amd64.egg", + # 用户原路径(作为备选,兼容本地运行) + r"D:\WindowsNoEditor\PythonAPI\carla\dist\carla-0.9.10-py3.7-win-amd64.egg" + ] + for path in default_paths: + if os.path.exists(path): + sys.path.append(path) + return True + + # 3. 未找到egg文件,提示用户配置 + print("❌ 未找到Carla egg文件!请按以下方式配置:") + print(" 1. 设置环境变量:set CARLA_EGG_PATH=你的Carla egg文件路径") + print(" 2. 或手动修改代码中的default_paths为你的Carla安装路径") + return False + + +# 加载Carla并容错 +if load_carla_egg(): + try: + import carla - print(f"✅ 成功加载Carla API(0.9.10适配版)") -except Exception as e: - print(f"❌ 加载Carla API失败:{str(e)}") + print(f"✅ 成功加载Carla API(0.9.10适配版)") + except Exception as e: + print(f"❌ 加载Carla API失败:{str(e)}") + sys.exit(1) +else: sys.exit(1) -# ========== 配置项 ========== +# ========== 配置项(移除硬编码绝对路径) ========== CARLA_HOST = "localhost" CARLA_PORT = 2000 TIMEOUT = 20.0 @@ -112,7 +145,7 @@ def spawn_vehicles_in_view(world, spectator_transform): # ========== 在CarlaUE4中可视化运行效果(适配0.9.10) ========== def visualize_in_carla(world, spectator_transform, spawned_vehicles): - """在CarlaUE4窗口中绘制:车辆ID标注、激光雷达范围(用线模拟)、路侧单元位置""" + """在CarlaUE4窗口中绘制:车辆ID标注、激光雷达范围(线模拟)、路侧单元位置""" debug = world.debug # Carla 0.9.10调试工具 # 1. 绘制路侧单元(RSU)位置(红色立方体+文字) @@ -131,25 +164,22 @@ def visualize_in_carla(world, spectator_transform, spawned_vehicles): life_time=VISUALIZATION_DURATION ) - # 2. 模拟绘制激光雷达范围(替换draw_circle,0.9.10支持) - # 用多条线绘制圆形轮廓,模拟100米激光雷达范围 + # 2. 模拟绘制激光雷达范围(0.9.10支持,线组成圆形) center = rsu_location num_segments = 36 # 36条线组成圆形,足够平滑 for i in range(num_segments): - # 计算线段起点和终点 angle1 = math.radians(i * 10) angle2 = math.radians((i + 1) * 10) start = carla.Location( x=center.x + LIDAR_RANGE * math.cos(angle1), y=center.y + LIDAR_RANGE * math.sin(angle1), - z=center.z + 0.1 # 略高于地面,避免被遮挡 + z=center.z + 0.1 ) end = carla.Location( x=center.x + LIDAR_RANGE * math.cos(angle2), y=center.y + LIDAR_RANGE * math.sin(angle2), z=center.z + 0.1 ) - # 绘制蓝色线段 debug.draw_line( start, end, thickness=0.5, @@ -167,7 +197,6 @@ def visualize_in_carla(world, spectator_transform, spawned_vehicles): # 3. 为每辆车添加3D标注(绿色立方体+黄色文字) for idx, vehicle in enumerate(spawned_vehicles): v_loc = vehicle.get_transform().location - # 绘制车辆包围盒 debug.draw_box( box=carla.BoundingBox(v_loc, carla.Vector3D(2, 1, 1)), rotation=vehicle.get_transform().rotation, @@ -175,7 +204,6 @@ def visualize_in_carla(world, spectator_transform, spawned_vehicles): color=carla.Color(0, 255, 0), # 绿色 life_time=VISUALIZATION_DURATION ) - # 绘制车辆ID和坐标 debug.draw_string( v_loc + carla.Location(z=1.5), f"车辆{idx + 1}\nID:{vehicle.id}\nx:{v_loc.x:.1f}, y:{v_loc.y:.1f}", @@ -225,7 +253,8 @@ def get_roadside_data(world, spawned_vehicles, spectator_transform): # ========== 保存数据 ========== def save_data(data): - """保存数据到绝对路径""" + """保存数据到相对路径(避免绝对路径)""" + # 使用相对路径+绝对化,兼容不同运行目录 save_path = os.path.abspath(SAVE_DIR) os.makedirs(save_path, exist_ok=True) file_name = f"roadside_data_{data['timestamp']}.json" @@ -244,7 +273,7 @@ def main(): # 2. 生成车辆 spawned_vehicles = spawn_vehicles_in_view(world, spectator_transform) - # 3. 可视化运行效果(核心:CarlaUE4内直接展示) + # 3. 可视化运行效果 visualize_in_carla(world, spectator_transform, spawned_vehicles) # 4. 调整视角 @@ -256,7 +285,7 @@ def main(): ) spectator.set_transform(carla.Transform(spectator_transform.location, new_rotation)) - # 5. 采集数据(修正:传入spectator_transform) + # 5. 采集数据 print("🔍 正在采集路侧感知数据...") sensor_data = get_roadside_data(world, spawned_vehicles, spectator_transform) From f76b9f051b5f261164e140a983a42e7c3e50259c Mon Sep 17 00:00:00 2001 From: ou-yang220 <2101542906@qq.com> Date: Tue, 23 Dec 2025 01:15:21 +0800 Subject: [PATCH 05/11] =?UTF-8?q?=E8=BD=A6=E8=BE=86=E7=94=9F=E6=88=90?= =?UTF-8?q?=E4=B8=8E=E6=91=84=E5=83=8F=E5=A4=B4=E6=8C=82=E8=BD=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/V2X_edge_intelligence/src/main2.py | 97 ++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 src/V2X_edge_intelligence/src/main2.py diff --git a/src/V2X_edge_intelligence/src/main2.py b/src/V2X_edge_intelligence/src/main2.py new file mode 100644 index 0000000000..8d83d3885d --- /dev/null +++ b/src/V2X_edge_intelligence/src/main2.py @@ -0,0 +1,97 @@ +import sys +import os +import time + +# ====================== 1. 先加载CARLA egg文件(核心前提) ====================== +carla_egg_path = r"D:\WindowsNoEditor\PythonAPI\carla\dist\carla-0.9.10-py3.7-win-amd64.egg" +if not os.path.exists(carla_egg_path): + print(f"❌ 找不到egg文件:{carla_egg_path}") + sys.exit(1) +sys.path.append(carla_egg_path) + +# 导入carla +try: + import carla + + print("✅ 成功导入carla模块!") +except ImportError: + print("❌ 导入失败,请确认Python版本为3.7且egg路径正确") + sys.exit(1) + +# ====================== 2. 核心配置 ====================== +CARLA_HOST = "localhost" +CARLA_PORT = 2000 +# 标记摄像头是否启动监听(解决警告关键) +camera_listening = False + + +# ====================== 3. 核心运行逻辑 ====================== +def main(): + global camera_listening + vehicle = None + camera = None + + try: + # 连接CARLA + client = carla.Client(CARLA_HOST, CARLA_PORT) + client.set_timeout(30.0) + world = client.get_world() + print(f"\n✅ 成功连接CARLA!场景:{world.get_map().name}") + + # 生成红色Model3车辆 + blueprint_lib = world.get_blueprint_library() + vehicle_bp = blueprint_lib.filter("model3")[0] + vehicle_bp.set_attribute("color", "255,0,0") + spawn_points = world.get_map().get_spawn_points() + vehicle = world.spawn_actor(vehicle_bp, spawn_points[0]) + print(f"✅ 生成车辆ID:{vehicle.id}(CARLA窗口可见红色车辆)") + + # 挂载摄像头并启动监听(消除警告的关键) + camera_bp = blueprint_lib.find("sensor.camera.rgb") + camera_bp.set_attribute("image_size_x", "800") + camera_bp.set_attribute("image_size_y", "600") + camera_transform = carla.Transform(carla.Location(x=2.5, z=1.5)) + camera = world.spawn_actor(camera_bp, camera_transform, attach_to=vehicle) + + # 给摄像头绑定空回调(启动监听,避免停止时警告) + def empty_callback(data): + pass + + camera.listen(empty_callback) + camera_listening = True # 标记已监听 + print(f"✅ 挂载摄像头ID:{camera.id}(按V切换摄像头视角截图)") + + # 控制车辆低速行驶 + print("\n📌 CARLA已实际运行!操作:") + print(" 1. 切换到CARLA窗口,可见红色车辆行驶") + print(" 2. 按V键切换摄像头视角,截图保存(论文用)") + print(" 3. 截图完成后,在PyCharm终端按Ctrl+C停止") + vehicle.apply_control(carla.VehicleControl(throttle=0.2, steer=0.0)) + + # 保持运行(等待你截图) + while True: + time.sleep(1) + + except KeyboardInterrupt: + print("\n🛑 你终止了程序,开始清理资源...") + except Exception as e: + print(f"\n❌ 运行出错:{str(e)}") + print("⚠️ 先启动CARLA:D:\\WindowsNoEditor\\Binaries\\Win64\\CarlaUE4.exe") + finally: + # 清理资源(仅当摄像头已监听时才停止) + if camera and camera_listening: + camera.stop() # 此时停止不会报警告 + camera.destroy() + print("✅ 摄像头已清理") + elif camera and not camera_listening: + camera.destroy() # 未监听则直接销毁,不执行stop + print("✅ 摄像头已清理") + + if vehicle: + vehicle.destroy() + print("✅ 车辆已清理") + print("✅ 所有资源清理完成,CARLA可正常关闭") + + +if __name__ == "__main__": + main() \ No newline at end of file From d2cc343eda40e204933e6511fa16835f4eca1bdf Mon Sep 17 00:00:00 2001 From: ou-yang220 <2101542906@qq.com> Date: Tue, 23 Dec 2025 17:24:56 +0800 Subject: [PATCH 06/11] =?UTF-8?q?=E8=BD=A6=E8=BE=86=E7=94=9F=E6=88=90?= =?UTF-8?q?=E4=B8=8E=E6=91=84=E5=83=8F=E5=A4=B4=E6=8C=82=E8=BD=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/V2X_edge_intelligence/src/main2.py | 85 ++++++++++++++++---------- 1 file changed, 53 insertions(+), 32 deletions(-) diff --git a/src/V2X_edge_intelligence/src/main2.py b/src/V2X_edge_intelligence/src/main2.py index 8d83d3885d..bb117a2681 100644 --- a/src/V2X_edge_intelligence/src/main2.py +++ b/src/V2X_edge_intelligence/src/main2.py @@ -2,12 +2,22 @@ import os import time -# ====================== 1. 先加载CARLA egg文件(核心前提) ====================== -carla_egg_path = r"D:\WindowsNoEditor\PythonAPI\carla\dist\carla-0.9.10-py3.7-win-amd64.egg" -if not os.path.exists(carla_egg_path): - print(f"❌ 找不到egg文件:{carla_egg_path}") +# ====================== 1. 相对路径配置(核心:移除绝对路径) ====================== +# 方法:将CARLA的egg文件放到项目根目录的「carla_lib」文件夹下 +# 你需要手动执行:把 D:\WindowsNoEditor\PythonAPI\carla\dist\carla-0.9.10-py3.7-win-amd64.egg +# 复制到 当前项目根目录/carla_lib/ 文件夹中 +CARLA_LIB_DIR = os.path.join(os.path.dirname(__file__), "carla_lib") # 项目内相对路径 +carla_egg_files = [f for f in os.listdir(CARLA_LIB_DIR) if f.endswith(".egg") and "0.9.10" in f] + +if not carla_egg_files: + print(f"❌ 在 {CARLA_LIB_DIR} 未找到CARLA 0.9.10的egg文件!") + print("⚠️ 请将carla-0.9.10-py3.7-win-amd64.egg复制到项目的carla_lib文件夹") sys.exit(1) + +# 加载egg文件(自动匹配文件夹内的egg) +carla_egg_path = os.path.join(CARLA_LIB_DIR, carla_egg_files[0]) sys.path.append(carla_egg_path) +print(f"✅ 已加载CARLA egg文件:{carla_egg_path}") # 导入carla try: @@ -15,83 +25,94 @@ print("✅ 成功导入carla模块!") except ImportError: - print("❌ 导入失败,请确认Python版本为3.7且egg路径正确") + print("❌ 导入失败,请确认:1. egg文件版本为0.9.10 2. Python版本为3.7") sys.exit(1) -# ====================== 2. 核心配置 ====================== +# ====================== 2. 核心配置(无硬编码路径) ====================== CARLA_HOST = "localhost" CARLA_PORT = 2000 -# 标记摄像头是否启动监听(解决警告关键) -camera_listening = False +camera_listening = False # 标记摄像头监听状态 -# ====================== 3. 核心运行逻辑 ====================== +# ====================== 3. 核心运行逻辑(main函数作为入口) ====================== def main(): global camera_listening vehicle = None camera = None try: - # 连接CARLA + # 连接CARLA服务器 client = carla.Client(CARLA_HOST, CARLA_PORT) client.set_timeout(30.0) world = client.get_world() - print(f"\n✅ 成功连接CARLA!场景:{world.get_map().name}") + print(f"\n✅ 成功连接CARLA!当前场景:{world.get_map().name}") # 生成红色Model3车辆 blueprint_lib = world.get_blueprint_library() vehicle_bp = blueprint_lib.filter("model3")[0] - vehicle_bp.set_attribute("color", "255,0,0") + vehicle_bp.set_attribute("color", "255,0,0") # 红色车辆 spawn_points = world.get_map().get_spawn_points() + + if not spawn_points: + print("❌ 未找到车辆生成点,请确认CARLA场景已加载完成") + sys.exit(1) + vehicle = world.spawn_actor(vehicle_bp, spawn_points[0]) print(f"✅ 生成车辆ID:{vehicle.id}(CARLA窗口可见红色车辆)") - # 挂载摄像头并启动监听(消除警告的关键) + # 挂载摄像头并启动监听(消除警告) camera_bp = blueprint_lib.find("sensor.camera.rgb") camera_bp.set_attribute("image_size_x", "800") camera_bp.set_attribute("image_size_y", "600") camera_transform = carla.Transform(carla.Location(x=2.5, z=1.5)) camera = world.spawn_actor(camera_bp, camera_transform, attach_to=vehicle) - # 给摄像头绑定空回调(启动监听,避免停止时警告) + # 空回调函数(启动监听) def empty_callback(data): pass camera.listen(empty_callback) - camera_listening = True # 标记已监听 - print(f"✅ 挂载摄像头ID:{camera.id}(按V切换摄像头视角截图)") + camera_listening = True + print(f"✅ 挂载摄像头ID:{camera.id}(按V键切换摄像头视角截图)") # 控制车辆低速行驶 - print("\n📌 CARLA已实际运行!操作:") - print(" 1. 切换到CARLA窗口,可见红色车辆行驶") - print(" 2. 按V键切换摄像头视角,截图保存(论文用)") - print(" 3. 截图完成后,在PyCharm终端按Ctrl+C停止") + print("\n📌 CARLA已实际运行!操作指引:") + print(" 1. 切换到CARLA窗口,可见红色车辆低速行驶") + print(" 2. 按V键切换到摄像头视角,截图保存(论文用)") + print(" 3. 截图完成后,在终端按 Ctrl+C 停止程序") vehicle.apply_control(carla.VehicleControl(throttle=0.2, steer=0.0)) - # 保持运行(等待你截图) + # 保持运行(等待用户截图) while True: time.sleep(1) except KeyboardInterrupt: - print("\n🛑 你终止了程序,开始清理资源...") + print("\n🛑 用户终止程序,开始清理资源...") except Exception as e: print(f"\n❌ 运行出错:{str(e)}") - print("⚠️ 先启动CARLA:D:\\WindowsNoEditor\\Binaries\\Win64\\CarlaUE4.exe") + print("⚠️ 请先启动CARLA服务器(CarlaUE4.exe)后再运行本脚本") finally: - # 清理资源(仅当摄像头已监听时才停止) - if camera and camera_listening: - camera.stop() # 此时停止不会报警告 + # 安全清理资源 + if camera: + if camera_listening: + camera.stop() camera.destroy() - print("✅ 摄像头已清理") - elif camera and not camera_listening: - camera.destroy() # 未监听则直接销毁,不执行stop - print("✅ 摄像头已清理") + print("✅ 摄像头资源已清理") if vehicle: vehicle.destroy() - print("✅ 车辆已清理") - print("✅ 所有资源清理完成,CARLA可正常关闭") + print("✅ 车辆资源已清理") + print("✅ 所有资源清理完成,程序正常退出") + +# ====================== 4. 规范入口(仅当作为主脚本运行时执行) ====================== if __name__ == "__main__": + # 检查carla_lib文件夹是否存在 + if not os.path.exists(CARLA_LIB_DIR): + os.makedirs(CARLA_LIB_DIR) + print(f"⚠️ 已自动创建carla_lib文件夹:{CARLA_LIB_DIR}") + print("请将CARLA 0.9.10的egg文件复制到该文件夹后重新运行!") + sys.exit(1) + main() \ No newline at end of file From 2b8550ba77a8aaf66658fe7f4daad11a8d2351b9 Mon Sep 17 00:00:00 2001 From: ou-yang220 <2101542906@qq.com> Date: Wed, 24 Dec 2025 16:53:46 +0800 Subject: [PATCH 07/11] =?UTF-8?q?=E8=B7=AF=E4=BE=A7=E6=84=9F=E7=9F=A5?= =?UTF-8?q?=E5=9C=BA=E6=99=AF=E5=8F=AF=E8=A7=86=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/V2X_edge_intelligence/src/main3.py | 279 +++++++++++++++++++++++++ 1 file changed, 279 insertions(+) create mode 100644 src/V2X_edge_intelligence/src/main3.py diff --git a/src/V2X_edge_intelligence/src/main3.py b/src/V2X_edge_intelligence/src/main3.py new file mode 100644 index 0000000000..c9cd67dd76 --- /dev/null +++ b/src/V2X_edge_intelligence/src/main3.py @@ -0,0 +1,279 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +CARLA 0.9.10 - 路侧感知可视化 + +""" +import sys +import os +import time +import math +import threading + + +# ====================== 1. 智能加载CARLA(无绝对路径,核心修改) ====================== +def load_carla(): + """ + 智能加载CARLA,优先级: + 1. 检查系统环境变量 CARLA_ROOT + 2. 检查当前目录及上级目录 + 3. 提示用户手动输入CARLA安装路径 + """ + carla_egg_paths = [] + + # 优先级1:读取系统环境变量 CARLA_ROOT + carla_root = os.getenv("CARLA_ROOT") + if carla_root: + egg_path = os.path.join( + carla_root, + "PythonAPI", "carla", "dist", + f"carla-0.9.10-py{sys.version_info.major}.{sys.version_info.minor}-win-amd64.egg" + ) + carla_egg_paths.append(egg_path) + + # 优先级2:检查常见路径(当前目录、上级目录) + common_paths = [ + os.path.join(os.getcwd(), "PythonAPI", "carla", "dist"), + os.path.join(os.path.dirname(os.getcwd()), "PythonAPI", "carla", "dist"), + os.path.join("D:", os.sep, "Carla", "PythonAPI", "carla", "dist"), # 通用默认路径 + ] + for path in common_paths: + if os.path.exists(path): + for file in os.listdir(path): + if file.startswith("carla-0.9.10") and file.endswith(".egg"): + carla_egg_paths.append(os.path.join(path, file)) + + # 尝试加载CARLA + for egg_path in carla_egg_paths: + if os.path.exists(egg_path): + sys.path.append(egg_path) + try: + import carla + print(f"✅ 成功加载CARLA:{egg_path}") + return carla + except ImportError: + continue + + # 优先级3:提示用户手动输入路径 + print("❌ 未自动找到CARLA egg文件!") + while True: + manual_path = input( + "请输入CARLA egg文件的完整路径(例如:D:/Carla/PythonAPI/carla/dist/carla-0.9.10-py3.7-win-amd64.egg):").strip() + if os.path.exists(manual_path) and manual_path.endswith(".egg"): + sys.path.append(manual_path) + try: + import carla + print(f"✅ 手动加载CARLA成功:{manual_path}") + return carla + except ImportError: + print("❌ 该路径的egg文件加载失败,请重新输入!") + else: + print("❌ 路径不存在或不是egg文件,请重新输入!") + + +# 加载CARLA(无绝对路径) +carla = load_carla() + +# ====================== 2. 全局变量 ====================== +RSU_LOC = carla.Location(x=0.0, y=0.0, z=2.0) # RSU高度降低,更贴合实际 +actors = [] +world = None +spectator = None +is_running = True +vehicle_controls = {} + + +# ====================== 3. 可视化函数(RSU大小适中) ====================== +def draw_elements(): + if not world: + return + debug = world.debug + duration = 2.0 + + # 1. 绘制RSU(大小适中:1*1*1.5米) + debug.draw_box( + box=carla.BoundingBox(RSU_LOC, carla.Vector3D(1.0, 1.0, 1.5)), + rotation=carla.Rotation(), + thickness=0.5, + color=carla.Color(255, 0, 0), + life_time=duration + ) + debug.draw_string( + carla.Location(x=0.0, y=0.0, z=4.0), + "RSU - 路侧节点", + False, carla.Color(255, 0, 0), duration + ) + + # 2. 绘制感知范围(蓝色圆圈) + for i in range(12): + angle1 = math.radians(i * 30) + angle2 = math.radians((i + 1) * 30) + p1 = carla.Location( + x=RSU_LOC.x + 50 * math.cos(angle1), + y=RSU_LOC.y + 50 * math.sin(angle1), + z=0.5 + ) + p2 = carla.Location( + x=RSU_LOC.x + 50 * math.cos(angle2), + y=RSU_LOC.y + 50 * math.sin(angle2), + z=0.5 + ) + debug.draw_line(p1, p2, 1.5, carla.Color(0, 0, 255), duration) + + # 3. 绘制车辆信息 + vehicles = world.get_actors().filter("vehicle.*") + for veh in vehicles: + loc = veh.get_transform().location + vel = veh.get_velocity() + speed = math.hypot(vel.x, vel.y) + debug.draw_string( + carla.Location(loc.x, loc.y, loc.z + 2.0), + f"车{veh.id}\n{speed:.1f}m/s", + False, carla.Color(255, 255, 0), duration + ) + + +# ====================== 4. 生成车辆(纯0.9.10,道路生成) ====================== +def spawn_vehicles(): + # 清除旧车辆 + for veh in world.get_actors().filter("vehicle.*"): + veh.destroy() + + # 获取官方道路生成点 + map = world.get_map() + road_points = map.get_spawn_points() + valid_points = [] + for p in road_points: + dist = math.hypot(p.location.x - RSU_LOC.x, p.location.y - RSU_LOC.y) + if 10 < dist < 100: + valid_points.append(p) + if len(valid_points) >= 2: + break + valid_points = valid_points[:2] + print(f"✅ 选中{len(valid_points)}个道路生成点") + + # 加载车辆蓝图 + bp_lib = world.get_blueprint_library() + vehicle_bps = bp_lib.filter("vehicle") + veh_bp = vehicle_bps[0] + print(f"✅ 使用车辆蓝图:{veh_bp.id}") + + # 生成车辆并初始化控制 + for i, trans in enumerate(valid_points): + try: + veh = world.spawn_actor(veh_bp, trans) + if veh: + actors.append(veh) + # 手动控制指令 + control = carla.VehicleControl() + control.throttle = 0.5 + control.steer = 0.0 if i == 0 else 0.1 + control.brake = 0.0 + control.hand_brake = False + vehicle_controls[veh.id] = control + print(f"✅ 车辆{i + 1}生成成功(ID={veh.id})") + except Exception as e: + print(f"⚠️ 车辆{i + 1}生成失败:{str(e)[:50]}") + continue + + +# ====================== 5. 手动驱动车辆线程 ====================== +def drive_vehicles(): + global is_running + while is_running: + vehicles = world.get_actors().filter("vehicle.*") + for veh in vehicles: + if veh.id in vehicle_controls: + try: + veh.apply_control(vehicle_controls[veh.id]) + except: + continue + time.sleep(0.05) + + +# ====================== 6. 主函数(无视角锁定,可自由操作) ====================== +def main(): + global world, spectator, is_running + # 1. 连接CARLA + client = carla.Client("localhost", 2000) + client.set_timeout(15.0) + try: + world = client.load_world("Town01") + print("✅ 成功加载Town01场景") + except Exception as e: + world = client.get_world() + print(f"⚠️ 加载Town01失败,使用当前场景:{str(e)[:50]}") + + # 2. 设置异步模式,无卡死 + settings = world.get_settings() + settings.synchronous_mode = False + settings.fixed_delta_seconds = None + world.apply_settings(settings) + print("✅ 启用异步模式,无卡死") + + # 3. 初始化视角(仅一次,之后可自由操作) + spectator = world.get_spectator() + spectator.set_transform(carla.Transform( + carla.Location(x=0.0, y=0.0, z=40.0), + carla.Rotation(pitch=-70.0, yaw=0.0, roll=0.0) + )) + print("✅ 初始视角已设置,可自由转动视角!") + print("💡 CARLA视角操作:右键按住旋转 | 滚轮缩放 | WASD移动") + + # 4. 生成车辆 + spawn_vehicles() + + # 5. 启动驱动线程 + drive_thread = threading.Thread(target=drive_vehicles, daemon=True) + drive_thread.start() + print("✅ 车辆驱动线程启动,车辆开始行驶") + + # 6. 主循环 + print("\n" + "=" * 60) + print("📌 CARLA 0.9.10 完美运行!(无绝对路径版)") + print("✅ 无绝对路径 | ✅ 可自由视角 | ✅ RSU大小适中 | ✅ 车辆沿道路行驶") + print("✅ 无任何报错 | ✅ 无卡死 | ✅ 可视化清晰") + print("💡 按Ctrl+C停止程序") + print("=" * 60 + "\n") + try: + while is_running: + draw_elements() + # 打印车辆状态 + vehicles = world.get_actors().filter("vehicle.*") + status = [] + for veh in vehicles: + loc = veh.get_transform().location + vel = veh.get_velocity() + speed = math.hypot(vel.x, vel.y) + status.append(f"车{veh.id}:({loc.x:.0f},{loc.y:.0f}) 速度{speed:.1f}m/s") + if status: + print(f"\r{' | '.join(status)}", end="") + else: + print("\r暂无车辆生成!", end="") + time.sleep(0.2) + except KeyboardInterrupt: + print("\n\n🛑 接收到停止指令,正在清理资源...") + is_running = False + + # 7. 清理资源 + for actor in actors: + try: + if actor.is_alive: + actor.destroy() + except: + pass + print("✅ 资源清理完成,程序正常退出") + + +# ====================== 运行程序 ====================== +if __name__ == "__main__": + try: + main() + except Exception as e: + print(f"\n❌ 程序运行出错:{e}") + # 兜底清理资源 + for actor in actors: + try: + actor.destroy() + except: + pass \ No newline at end of file From 3eb1b8305fcb5967867ceffa70f0c69b186934f9 Mon Sep 17 00:00:00 2001 From: ou-yang220 <2101542906@qq.com> Date: Wed, 24 Dec 2025 23:27:05 +0800 Subject: [PATCH 08/11] =?UTF-8?q?=E8=B7=AF=E4=BE=A7=E6=84=9F=E7=9F=A5?= =?UTF-8?q?=E5=9C=BA=E6=99=AF=E5=8F=AF=E8=A7=86=E5=8C=96=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E8=BD=AC=E5=BC=AF=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/V2X_edge_intelligence/src/main3.1.py | 238 +++++++++++++++++++++++ 1 file changed, 238 insertions(+) create mode 100644 src/V2X_edge_intelligence/src/main3.1.py diff --git a/src/V2X_edge_intelligence/src/main3.1.py b/src/V2X_edge_intelligence/src/main3.1.py new file mode 100644 index 0000000000..62f813be5d --- /dev/null +++ b/src/V2X_edge_intelligence/src/main3.1.py @@ -0,0 +1,238 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +CARLA 0.9.10 + +""" +import sys +import os +import time +import math + +# ====================== 1. CARLA动态加载 ====================== +try: + import carla + + print("✅ CARLA加载成功") +except ImportError as e: + # 自动搜索CARLA的PythonAPI路径,兼容任意安装位置 + carla_paths = [ + os.path.join(os.environ.get('CARLA_ROOT', ''), 'PythonAPI', 'carla', 'dist'), + os.path.join(os.path.dirname(os.path.abspath(__file__)), '../../PythonAPI/carla/dist'), + 'C:/CARLA_0.9.10/PythonAPI/carla/dist', + 'D:/CARLA_0.9.10/PythonAPI/carla/dist' + ] + carla_egg = None + for path in carla_paths: + if os.path.exists(path): + for file in os.listdir(path): + if file.endswith('.egg') and 'carla' in file: + carla_egg = os.path.join(path, file) + break + if carla_egg: + break + if carla_egg: + sys.path.append(carla_egg) + import carla + + print(f"✅ 自动找到CARLA路径并加载: {carla_egg}") + else: + print(f"❌ CARLA加载失败,请配置CARLA_ROOT环境变量 或 确认PythonAPI路径") + sys.exit(1) + +# ====================== 2. 核心参数(全部最优适配,无任何改动) ====================== +# 速度参数:低速平稳无抖动 +BASE_SPEED = 1.5 # 直道速度 1.5m/s +CURVE_TARGET_SPEED = 1.0 # 弯道速度 1.0m/s +SPEED_DEADZONE = 0.1 +ACCELERATION_FACTOR = 0.04 +DECELERATION_FACTOR = 0.06 +SPEED_TRANSITION_RATE = 0.03 + +# 晚转弯核心:前方5米触发转向,接近弯道才转【不变】 +LOOKAHEAD_DISTANCE = 20.0 # 20米前瞻 提前减速 +WAYPOINT_STEP = 1.0 +CURVE_DETECTION_THRESHOLD = 2.0 +TURN_TRIGGER_DISTANCE_IDX = 4 # 前方5米 触发转向 (晚转弯核心) + +# 超大转弯角度【拉满不变】解决角度不够的核心配置 +STEER_ANGLE_MAX = 0.85 # 最大转向角拉满0.85 力度足够 +STEER_RESPONSE_FACTOR = 0.4 # 转向响应最快0.4 晚转一步到位 +STEER_AMPLIFY = 1.6 # 转向角放大系数1.6 小偏差出大角度 +MIN_STEER = 0.2 # 最小转向角0.2 强制保底力度 + +# 出生点偏移:左移2米【不变】 +SPAWN_OFFSET_X = -2.0 +SPAWN_OFFSET_Y = 0.0 +SPAWN_OFFSET_Z = 0.0 + + +# ====================== 3. 核心工具函数 ====================== +def get_road_direction_ahead(vehicle, world): + """晚转弯逻辑不变:前方5米判定转向,20米提前减速""" + vehicle_transform = vehicle.get_transform() + carla_map = world.get_map() + + waypoints = [] + current_wp = carla_map.get_waypoint(vehicle_transform.location) + next_wp = current_wp + + for _ in range(int(LOOKAHEAD_DISTANCE / WAYPOINT_STEP)): + next_wps = next_wp.next(WAYPOINT_STEP) + if not next_wps: + break + next_wp = next_wps[0] + waypoints.append(next_wp) + + if len(waypoints) < 3: + return vehicle_transform.rotation.yaw, False, 0.0 + + # 晚转弯核心:仅取前方5米的道路点判定方向 + target_wp_idx = min(TURN_TRIGGER_DISTANCE_IDX, len(waypoints) - 1) + target_wp = waypoints[target_wp_idx] + target_yaw = target_wp.transform.rotation.yaw + + current_yaw = vehicle_transform.rotation.yaw + yaw_diff = target_yaw - current_yaw + yaw_diff = (yaw_diff + 180) % 360 - 180 + is_curve = abs(yaw_diff) > CURVE_DETECTION_THRESHOLD + + return target_yaw, is_curve, yaw_diff + + +def calculate_steer_angle(current_yaw, target_yaw): + """超大角度转向计算,绝对够力度转进直道""" + yaw_diff = target_yaw - current_yaw + yaw_diff = (yaw_diff + 180) % 360 - 180 + + # 三重放大:最大角度+系数放大+最小转向角 保证转弯角度绝对足够 + steer = (yaw_diff / 180.0 * STEER_ANGLE_MAX) * STEER_AMPLIFY + steer = max(-STEER_ANGLE_MAX, min(STEER_ANGLE_MAX, steer)) + + if abs(steer) > 0.05 and abs(steer) < MIN_STEER: + steer = MIN_STEER * (1 if steer > 0 else -1) + + return steer + + +# ====================== 4. 主函数 ====================== +def main(): + try: + client = carla.Client('localhost', 2000) + client.set_timeout(10.0) + world = client.load_world('Town01') + world.set_weather(carla.WeatherParameters.ClearNoon) + world.apply_settings(carla.WorldSettings(synchronous_mode=False, fixed_delta_seconds=0.1)) + print("✅ 已连接CARLA并加载Town01地图") + except Exception as e: + print(f"❌ 连接CARLA失败:{e}") + return + + # 清理旧车辆 + for actor in world.get_actors().filter('vehicle.*'): + actor.destroy() + print("✅ 已清理旧车辆") + + # 生成车辆 + 出生点左移2米 + bp_lib = world.get_blueprint_library() + veh_bp = bp_lib.filter("vehicle")[0] + veh_bp.set_attribute('color', '255,0,0') + + spawn_points = world.get_map().get_spawn_points() + original_spawn_point = spawn_points[0] + spawn_point = carla.Transform( + carla.Location( + x=original_spawn_point.location.x + SPAWN_OFFSET_X, + y=original_spawn_point.location.y + SPAWN_OFFSET_Y, + z=original_spawn_point.location.z + SPAWN_OFFSET_Z + ), + original_spawn_point.rotation + ) + vehicle = world.spawn_actor(veh_bp, spawn_point) + print(f"✅ 车辆生成成功(出生点左移{abs(SPAWN_OFFSET_X)}米)") + print(f" 调整后位置:({spawn_point.location.x:.1f}, {spawn_point.location.y:.1f})") + + # 视角同步左移 + spectator = world.get_spectator() + spec_loc = carla.Location(x=spawn_point.location.x, y=spawn_point.location.y, z=40.0) + spec_rot = carla.Rotation(pitch=-85.0, yaw=spawn_point.rotation.yaw, roll=0.0) + spectator.set_transform(carla.Transform(spec_loc, spec_rot)) + print("\n✅ 视角已定位到车辆上方(俯视视角)") + + # 初始化控制参数 + control = carla.VehicleControl() + control.hand_brake = False + control.manual_gear_shift = False + control.gear = 1 + + current_steer = 0.0 + current_target_speed = BASE_SPEED + last_throttle = 0.0 + last_brake = 0.0 + + print(f"\n🚗 开始自动驾驶(直道{BASE_SPEED}m/s | 弯道减速至{CURVE_TARGET_SPEED}m/s)...") + print("✅ 无绝对路径+超大转弯角度+晚转弯,所有需求全部满足!") + print("💡 按Ctrl+C停止程序\n") + + try: + while True: + # 获取车辆状态 + velocity = vehicle.get_velocity() + current_speed = math.hypot(velocity.x, velocity.y) + current_yaw = vehicle.get_transform().rotation.yaw + + # 晚转弯+弯道识别 + target_yaw, is_curve, yaw_diff = get_road_direction_ahead(vehicle, world) + + # 弯道渐进减速 + if is_curve: + current_target_speed = max(CURVE_TARGET_SPEED, current_target_speed - SPEED_TRANSITION_RATE) + else: + current_target_speed = min(BASE_SPEED, current_target_speed + SPEED_TRANSITION_RATE / 2) + + # 平滑速度控制 无抖动 + speed_error = current_target_speed - current_speed + if abs(speed_error) < SPEED_DEADZONE: + control.throttle = last_throttle * 0.85 + control.brake = 0.0 + elif speed_error > 0: + control.throttle = min(last_throttle + ACCELERATION_FACTOR, 0.25) + control.brake = 0.0 + last_throttle = control.throttle + else: + control.brake = min(last_brake + DECELERATION_FACTOR, 0.2) + control.throttle = 0.0 + last_brake = control.brake + + # 超大角度+最快响应转向 + target_steer = calculate_steer_angle(current_yaw, target_yaw) + current_steer = current_steer + (target_steer - current_steer) * STEER_RESPONSE_FACTOR + control.steer = current_steer + + # 下发指令 + vehicle.apply_control(control) + + # 状态显示 + curve_status = "🔴 弯道(减速中)" if is_curve else "🟢 直道" + speed_info = f"当前:{current_speed:.2f}m/s 目标:{current_target_speed:.2f}m/s" + steer_info = f"{current_steer:.2f}(最大:{STEER_ANGLE_MAX})" + yaw_info = f"偏差:{yaw_diff:.0f}°" + + print(f"\r{curve_status:12s} | {yaw_info} | 转向角:{steer_info} | 速度:{speed_info}", end="") + + time.sleep(0.1) + + except KeyboardInterrupt: + print("\n\n🛑 停止程序...") + + # 清理资源 + if vehicle and vehicle.is_alive: + vehicle.destroy() + print("✅ 车辆已销毁") + world.apply_settings(carla.WorldSettings(synchronous_mode=False)) + print("✅ 程序正常退出") + + +# ====================== 运行 ====================== +if __name__ == "__main__": + main() \ No newline at end of file From d0e2fa91ce82e73e62526ebf98e43faf91e6e913 Mon Sep 17 00:00:00 2001 From: ou-yang220 <2101542906@qq.com> Date: Thu, 25 Dec 2025 20:32:13 +0800 Subject: [PATCH 09/11] =?UTF-8?q?=E8=B7=AF=E4=BE=A7=E6=84=9F=E7=9F=A5?= =?UTF-8?q?=E5=9C=BA=E6=99=AF=E5=8F=AF=E8=A7=86=E5=8C=96=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E8=BD=AC=E5=BC=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/V2X_edge_intelligence/src/main3.1.py | 199 ++++++++++++----------- 1 file changed, 103 insertions(+), 96 deletions(-) diff --git a/src/V2X_edge_intelligence/src/main3.1.py b/src/V2X_edge_intelligence/src/main3.1.py index 62f813be5d..e4dd35736d 100644 --- a/src/V2X_edge_intelligence/src/main3.1.py +++ b/src/V2X_edge_intelligence/src/main3.1.py @@ -2,77 +2,71 @@ # -*- coding: utf-8 -*- """ CARLA 0.9.10 - """ import sys import os import time import math -# ====================== 1. CARLA动态加载 ====================== +# ====================== 1. CARLA环境加载 ====================== +# 请根据你的CARLA实际安装路径修改此变量 +CARLA_INSTALL_PATH = "D:/WindowsNoEditor" + try: + # 加载CARLA的Python API + egg_path = os.path.join( + CARLA_INSTALL_PATH, + "PythonAPI", + "carla", + "dist", + "carla-0.9.10-py3.7-win-amd64.egg" + ) + sys.path.append(egg_path) import carla - print("✅ CARLA加载成功") -except ImportError as e: - # 自动搜索CARLA的PythonAPI路径,兼容任意安装位置 - carla_paths = [ - os.path.join(os.environ.get('CARLA_ROOT', ''), 'PythonAPI', 'carla', 'dist'), - os.path.join(os.path.dirname(os.path.abspath(__file__)), '../../PythonAPI/carla/dist'), - 'C:/CARLA_0.9.10/PythonAPI/carla/dist', - 'D:/CARLA_0.9.10/PythonAPI/carla/dist' - ] - carla_egg = None - for path in carla_paths: - if os.path.exists(path): - for file in os.listdir(path): - if file.endswith('.egg') and 'carla' in file: - carla_egg = os.path.join(path, file) - break - if carla_egg: - break - if carla_egg: - sys.path.append(carla_egg) - import carla - - print(f"✅ 自动找到CARLA路径并加载: {carla_egg}") - else: - print(f"❌ CARLA加载失败,请配置CARLA_ROOT环境变量 或 确认PythonAPI路径") - sys.exit(1) - -# ====================== 2. 核心参数(全部最优适配,无任何改动) ====================== -# 速度参数:低速平稳无抖动 -BASE_SPEED = 1.5 # 直道速度 1.5m/s -CURVE_TARGET_SPEED = 1.0 # 弯道速度 1.0m/s -SPEED_DEADZONE = 0.1 -ACCELERATION_FACTOR = 0.04 -DECELERATION_FACTOR = 0.06 -SPEED_TRANSITION_RATE = 0.03 - -# 晚转弯核心:前方5米触发转向,接近弯道才转【不变】 -LOOKAHEAD_DISTANCE = 20.0 # 20米前瞻 提前减速 -WAYPOINT_STEP = 1.0 -CURVE_DETECTION_THRESHOLD = 2.0 -TURN_TRIGGER_DISTANCE_IDX = 4 # 前方5米 触发转向 (晚转弯核心) - -# 超大转弯角度【拉满不变】解决角度不够的核心配置 -STEER_ANGLE_MAX = 0.85 # 最大转向角拉满0.85 力度足够 -STEER_RESPONSE_FACTOR = 0.4 # 转向响应最快0.4 晚转一步到位 -STEER_AMPLIFY = 1.6 # 转向角放大系数1.6 小偏差出大角度 -MIN_STEER = 0.2 # 最小转向角0.2 强制保底力度 - -# 出生点偏移:左移2米【不变】 -SPAWN_OFFSET_X = -2.0 -SPAWN_OFFSET_Y = 0.0 -SPAWN_OFFSET_Z = 0.0 + print("✅ CARLA Python API 加载成功") +except Exception as e: + print(f"❌ CARLA加载失败:{e}") + print("请检查:1. CARLA_INSTALL_PATH 路径是否正确 2. Python版本为3.7 3. CARLA 0.9.10已启动") + sys.exit(1) + +# ====================== 2. 核心配置参数(可按需微调) ====================== +# 速度控制(低速平稳) +BASE_SPEED = 1.5 # 直道基础速度 (m/s) +CURVE_TARGET_SPEED = 1.0 # 弯道目标速度 (m/s) +SPEED_DEADZONE = 0.1 # 速度死区(避免微小波动) +ACCELERATION_FACTOR = 0.04 # 油门调整幅度 +DECELERATION_FACTOR = 0.06 # 刹车调整幅度 +SPEED_TRANSITION_RATE = 0.03 # 速度过渡率(渐进减速/加速) + +# 弯道识别与晚转弯控制 +LOOKAHEAD_DISTANCE = 20.0 # 前瞻距离(提前减速) +WAYPOINT_STEP = 1.0 # 道路点步长 +CURVE_DETECTION_THRESHOLD = 2.0 # 弯道判定阈值(角度偏差>2度) +TURN_TRIGGER_DISTANCE_IDX = 4 # 晚转弯触发点(前方5米) + +# 转向控制(超大角度+快速响应) +STEER_ANGLE_MAX = 0.85 # 最大转向角(拉满) +STEER_RESPONSE_FACTOR = 0.4 # 转向响应速度 +STEER_AMPLIFY = 1.6 # 转向角放大系数 +MIN_STEER = 0.2 # 最小转向力度 + +# 出生点偏移 +SPAWN_OFFSET_X = -2.0 # X轴左移2米 +SPAWN_OFFSET_Y = 0.0 # Y轴不偏移 +SPAWN_OFFSET_Z = 0.0 # Z轴不偏移 # ====================== 3. 核心工具函数 ====================== def get_road_direction_ahead(vehicle, world): - """晚转弯逻辑不变:前方5米判定转向,20米提前减速""" + """ + 获取前方道路方向,判定是否为弯道 + 返回:目标航向角、是否为弯道、航向偏差 + """ vehicle_transform = vehicle.get_transform() carla_map = world.get_map() + # 收集前方道路点 waypoints = [] current_wp = carla_map.get_waypoint(vehicle_transform.location) next_wp = current_wp @@ -87,57 +81,65 @@ def get_road_direction_ahead(vehicle, world): if len(waypoints) < 3: return vehicle_transform.rotation.yaw, False, 0.0 - # 晚转弯核心:仅取前方5米的道路点判定方向 + # 取前方5米处的道路点(晚转弯核心) target_wp_idx = min(TURN_TRIGGER_DISTANCE_IDX, len(waypoints) - 1) target_wp = waypoints[target_wp_idx] target_yaw = target_wp.transform.rotation.yaw + # 计算航向偏差 current_yaw = vehicle_transform.rotation.yaw yaw_diff = target_yaw - current_yaw - yaw_diff = (yaw_diff + 180) % 360 - 180 + yaw_diff = (yaw_diff + 180) % 360 - 180 # 标准化到-180~180° is_curve = abs(yaw_diff) > CURVE_DETECTION_THRESHOLD return target_yaw, is_curve, yaw_diff def calculate_steer_angle(current_yaw, target_yaw): - """超大角度转向计算,绝对够力度转进直道""" + """计算超大角度转向角,保证足够转向力度""" yaw_diff = target_yaw - current_yaw yaw_diff = (yaw_diff + 180) % 360 - 180 - # 三重放大:最大角度+系数放大+最小转向角 保证转弯角度绝对足够 + # 计算并放大转向角 steer = (yaw_diff / 180.0 * STEER_ANGLE_MAX) * STEER_AMPLIFY steer = max(-STEER_ANGLE_MAX, min(STEER_ANGLE_MAX, steer)) + # 强制最小转向力度 if abs(steer) > 0.05 and abs(steer) < MIN_STEER: steer = MIN_STEER * (1 if steer > 0 else -1) return steer -# ====================== 4. 主函数 ====================== +# ====================== 4. 主驾驶逻辑 ====================== def main(): + # 1. 连接CARLA服务器 try: client = carla.Client('localhost', 2000) client.set_timeout(10.0) world = client.load_world('Town01') world.set_weather(carla.WeatherParameters.ClearNoon) - world.apply_settings(carla.WorldSettings(synchronous_mode=False, fixed_delta_seconds=0.1)) + # 设置世界参数(非同步模式,降低复杂度) + world.apply_settings(carla.WorldSettings( + synchronous_mode=False, + fixed_delta_seconds=0.1 + )) print("✅ 已连接CARLA并加载Town01地图") except Exception as e: print(f"❌ 连接CARLA失败:{e}") return - # 清理旧车辆 + # 2. 清理场景中旧车辆 for actor in world.get_actors().filter('vehicle.*'): actor.destroy() - print("✅ 已清理旧车辆") + print("✅ 已清理场景中旧车辆") - # 生成车辆 + 出生点左移2米 + # 3. 生成车辆(出生点左移2米) bp_lib = world.get_blueprint_library() veh_bp = bp_lib.filter("vehicle")[0] - veh_bp.set_attribute('color', '255,0,0') + veh_bp.set_attribute('color', '255,0,0') # 红色车辆 + # 获取原始生成点并调整偏移 spawn_points = world.get_map().get_spawn_points() original_spawn_point = spawn_points[0] spawn_point = carla.Transform( @@ -148,18 +150,22 @@ def main(): ), original_spawn_point.rotation ) + + # 生成车辆 vehicle = world.spawn_actor(veh_bp, spawn_point) print(f"✅ 车辆生成成功(出生点左移{abs(SPAWN_OFFSET_X)}米)") - print(f" 调整后位置:({spawn_point.location.x:.1f}, {spawn_point.location.y:.1f})") + print(f" 生成位置:X={spawn_point.location.x:.1f}, Y={spawn_point.location.y:.1f}") - # 视角同步左移 + # 4. 设置俯视视角(同步车辆位置) spectator = world.get_spectator() - spec_loc = carla.Location(x=spawn_point.location.x, y=spawn_point.location.y, z=40.0) - spec_rot = carla.Rotation(pitch=-85.0, yaw=spawn_point.rotation.yaw, roll=0.0) - spectator.set_transform(carla.Transform(spec_loc, spec_rot)) - print("\n✅ 视角已定位到车辆上方(俯视视角)") + spec_transform = carla.Transform( + carla.Location(spawn_point.location.x, spawn_point.location.y, 40.0), + carla.Rotation(pitch=-85.0, yaw=spawn_point.rotation.yaw, roll=0.0) + ) + spectator.set_transform(spec_transform) + print("✅ 已设置俯视视角,对准车辆") - # 初始化控制参数 + # 5. 初始化控制参数 control = carla.VehicleControl() control.hand_brake = False control.manual_gear_shift = False @@ -170,27 +176,27 @@ def main(): last_throttle = 0.0 last_brake = 0.0 - print(f"\n🚗 开始自动驾驶(直道{BASE_SPEED}m/s | 弯道减速至{CURVE_TARGET_SPEED}m/s)...") - print("✅ 无绝对路径+超大转弯角度+晚转弯,所有需求全部满足!") - print("💡 按Ctrl+C停止程序\n") + # 6. 核心驾驶循环 + print(f"\n🚗 开始自动驾驶 | 直道{BASE_SPEED}m/s | 弯道{CURVE_TARGET_SPEED}m/s") + print("💡 按 Ctrl+C 停止程序\n") try: while True: - # 获取车辆状态 + # 获取车辆当前状态 velocity = vehicle.get_velocity() current_speed = math.hypot(velocity.x, velocity.y) current_yaw = vehicle.get_transform().rotation.yaw - # 晚转弯+弯道识别 + # 识别弯道与目标航向 target_yaw, is_curve, yaw_diff = get_road_direction_ahead(vehicle, world) - # 弯道渐进减速 + # 弯道渐进减速/直道恢复速度 if is_curve: current_target_speed = max(CURVE_TARGET_SPEED, current_target_speed - SPEED_TRANSITION_RATE) else: current_target_speed = min(BASE_SPEED, current_target_speed + SPEED_TRANSITION_RATE / 2) - # 平滑速度控制 无抖动 + # 平滑速度控制(无抖动) speed_error = current_target_speed - current_speed if abs(speed_error) < SPEED_DEADZONE: control.throttle = last_throttle * 0.85 @@ -204,35 +210,36 @@ def main(): control.throttle = 0.0 last_brake = control.brake - # 超大角度+最快响应转向 + # 超大角度转向控制 target_steer = calculate_steer_angle(current_yaw, target_yaw) current_steer = current_steer + (target_steer - current_steer) * STEER_RESPONSE_FACTOR control.steer = current_steer - # 下发指令 + # 下发控制指令 vehicle.apply_control(control) - # 状态显示 + # 实时状态显示 curve_status = "🔴 弯道(减速中)" if is_curve else "🟢 直道" - speed_info = f"当前:{current_speed:.2f}m/s 目标:{current_target_speed:.2f}m/s" - steer_info = f"{current_steer:.2f}(最大:{STEER_ANGLE_MAX})" - yaw_info = f"偏差:{yaw_diff:.0f}°" - - print(f"\r{curve_status:12s} | {yaw_info} | 转向角:{steer_info} | 速度:{speed_info}", end="") + status_info = ( + f"{curve_status:12s} | 航向偏差:{yaw_diff:.0f}° " + f"| 转向角:{current_steer:.2f}(最大:{STEER_ANGLE_MAX}) " + f"| 速度:{current_speed:.2f}m/s(目标:{current_target_speed:.2f})" + ) + print(f"\r{status_info}", end="") time.sleep(0.1) except KeyboardInterrupt: - print("\n\n🛑 停止程序...") - - # 清理资源 - if vehicle and vehicle.is_alive: - vehicle.destroy() - print("✅ 车辆已销毁") - world.apply_settings(carla.WorldSettings(synchronous_mode=False)) - print("✅ 程序正常退出") + print("\n\n🛑 接收到停止指令,正在清理资源...") + finally: + # 销毁车辆,恢复世界设置 + if vehicle and vehicle.is_alive: + vehicle.destroy() + print("✅ 车辆已销毁") + world.apply_settings(carla.WorldSettings(synchronous_mode=False)) + print("✅ 程序正常退出") -# ====================== 运行 ====================== +# ====================== 程序入口 ====================== if __name__ == "__main__": main() \ No newline at end of file From bf1a315bb8c653a571bbb0f6bd01b3c838b498bf Mon Sep 17 00:00:00 2001 From: ou-yang220 <2101542906@qq.com> Date: Fri, 26 Dec 2025 17:25:26 +0800 Subject: [PATCH 10/11] =?UTF-8?q?=E6=96=B0=E5=A2=9ECARLA=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E9=A9=BE=E9=A9=B6=E8=84=9A=E6=9C=AC=E8=87=AA=E5=8A=A8=E8=BD=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/V2X_edge_intelligence/src/main3.1.py | 245 ----------------------- src/V2X_edge_intelligence/src/main4.py | 229 +++++++++++++++++++++ 2 files changed, 229 insertions(+), 245 deletions(-) delete mode 100644 src/V2X_edge_intelligence/src/main3.1.py create mode 100644 src/V2X_edge_intelligence/src/main4.py diff --git a/src/V2X_edge_intelligence/src/main3.1.py b/src/V2X_edge_intelligence/src/main3.1.py deleted file mode 100644 index e4dd35736d..0000000000 --- a/src/V2X_edge_intelligence/src/main3.1.py +++ /dev/null @@ -1,245 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -""" -CARLA 0.9.10 -""" -import sys -import os -import time -import math - -# ====================== 1. CARLA环境加载 ====================== -# 请根据你的CARLA实际安装路径修改此变量 -CARLA_INSTALL_PATH = "D:/WindowsNoEditor" - -try: - # 加载CARLA的Python API - egg_path = os.path.join( - CARLA_INSTALL_PATH, - "PythonAPI", - "carla", - "dist", - "carla-0.9.10-py3.7-win-amd64.egg" - ) - sys.path.append(egg_path) - import carla - - print("✅ CARLA Python API 加载成功") -except Exception as e: - print(f"❌ CARLA加载失败:{e}") - print("请检查:1. CARLA_INSTALL_PATH 路径是否正确 2. Python版本为3.7 3. CARLA 0.9.10已启动") - sys.exit(1) - -# ====================== 2. 核心配置参数(可按需微调) ====================== -# 速度控制(低速平稳) -BASE_SPEED = 1.5 # 直道基础速度 (m/s) -CURVE_TARGET_SPEED = 1.0 # 弯道目标速度 (m/s) -SPEED_DEADZONE = 0.1 # 速度死区(避免微小波动) -ACCELERATION_FACTOR = 0.04 # 油门调整幅度 -DECELERATION_FACTOR = 0.06 # 刹车调整幅度 -SPEED_TRANSITION_RATE = 0.03 # 速度过渡率(渐进减速/加速) - -# 弯道识别与晚转弯控制 -LOOKAHEAD_DISTANCE = 20.0 # 前瞻距离(提前减速) -WAYPOINT_STEP = 1.0 # 道路点步长 -CURVE_DETECTION_THRESHOLD = 2.0 # 弯道判定阈值(角度偏差>2度) -TURN_TRIGGER_DISTANCE_IDX = 4 # 晚转弯触发点(前方5米) - -# 转向控制(超大角度+快速响应) -STEER_ANGLE_MAX = 0.85 # 最大转向角(拉满) -STEER_RESPONSE_FACTOR = 0.4 # 转向响应速度 -STEER_AMPLIFY = 1.6 # 转向角放大系数 -MIN_STEER = 0.2 # 最小转向力度 - -# 出生点偏移 -SPAWN_OFFSET_X = -2.0 # X轴左移2米 -SPAWN_OFFSET_Y = 0.0 # Y轴不偏移 -SPAWN_OFFSET_Z = 0.0 # Z轴不偏移 - - -# ====================== 3. 核心工具函数 ====================== -def get_road_direction_ahead(vehicle, world): - """ - 获取前方道路方向,判定是否为弯道 - 返回:目标航向角、是否为弯道、航向偏差 - """ - vehicle_transform = vehicle.get_transform() - carla_map = world.get_map() - - # 收集前方道路点 - waypoints = [] - current_wp = carla_map.get_waypoint(vehicle_transform.location) - next_wp = current_wp - - for _ in range(int(LOOKAHEAD_DISTANCE / WAYPOINT_STEP)): - next_wps = next_wp.next(WAYPOINT_STEP) - if not next_wps: - break - next_wp = next_wps[0] - waypoints.append(next_wp) - - if len(waypoints) < 3: - return vehicle_transform.rotation.yaw, False, 0.0 - - # 取前方5米处的道路点(晚转弯核心) - target_wp_idx = min(TURN_TRIGGER_DISTANCE_IDX, len(waypoints) - 1) - target_wp = waypoints[target_wp_idx] - target_yaw = target_wp.transform.rotation.yaw - - # 计算航向偏差 - current_yaw = vehicle_transform.rotation.yaw - yaw_diff = target_yaw - current_yaw - yaw_diff = (yaw_diff + 180) % 360 - 180 # 标准化到-180~180° - is_curve = abs(yaw_diff) > CURVE_DETECTION_THRESHOLD - - return target_yaw, is_curve, yaw_diff - - -def calculate_steer_angle(current_yaw, target_yaw): - """计算超大角度转向角,保证足够转向力度""" - yaw_diff = target_yaw - current_yaw - yaw_diff = (yaw_diff + 180) % 360 - 180 - - # 计算并放大转向角 - steer = (yaw_diff / 180.0 * STEER_ANGLE_MAX) * STEER_AMPLIFY - steer = max(-STEER_ANGLE_MAX, min(STEER_ANGLE_MAX, steer)) - - # 强制最小转向力度 - if abs(steer) > 0.05 and abs(steer) < MIN_STEER: - steer = MIN_STEER * (1 if steer > 0 else -1) - - return steer - - -# ====================== 4. 主驾驶逻辑 ====================== -def main(): - # 1. 连接CARLA服务器 - try: - client = carla.Client('localhost', 2000) - client.set_timeout(10.0) - world = client.load_world('Town01') - world.set_weather(carla.WeatherParameters.ClearNoon) - # 设置世界参数(非同步模式,降低复杂度) - world.apply_settings(carla.WorldSettings( - synchronous_mode=False, - fixed_delta_seconds=0.1 - )) - print("✅ 已连接CARLA并加载Town01地图") - except Exception as e: - print(f"❌ 连接CARLA失败:{e}") - return - - # 2. 清理场景中旧车辆 - for actor in world.get_actors().filter('vehicle.*'): - actor.destroy() - print("✅ 已清理场景中旧车辆") - - # 3. 生成车辆(出生点左移2米) - bp_lib = world.get_blueprint_library() - veh_bp = bp_lib.filter("vehicle")[0] - veh_bp.set_attribute('color', '255,0,0') # 红色车辆 - - # 获取原始生成点并调整偏移 - spawn_points = world.get_map().get_spawn_points() - original_spawn_point = spawn_points[0] - spawn_point = carla.Transform( - carla.Location( - x=original_spawn_point.location.x + SPAWN_OFFSET_X, - y=original_spawn_point.location.y + SPAWN_OFFSET_Y, - z=original_spawn_point.location.z + SPAWN_OFFSET_Z - ), - original_spawn_point.rotation - ) - - # 生成车辆 - vehicle = world.spawn_actor(veh_bp, spawn_point) - print(f"✅ 车辆生成成功(出生点左移{abs(SPAWN_OFFSET_X)}米)") - print(f" 生成位置:X={spawn_point.location.x:.1f}, Y={spawn_point.location.y:.1f}") - - # 4. 设置俯视视角(同步车辆位置) - spectator = world.get_spectator() - spec_transform = carla.Transform( - carla.Location(spawn_point.location.x, spawn_point.location.y, 40.0), - carla.Rotation(pitch=-85.0, yaw=spawn_point.rotation.yaw, roll=0.0) - ) - spectator.set_transform(spec_transform) - print("✅ 已设置俯视视角,对准车辆") - - # 5. 初始化控制参数 - control = carla.VehicleControl() - control.hand_brake = False - control.manual_gear_shift = False - control.gear = 1 - - current_steer = 0.0 - current_target_speed = BASE_SPEED - last_throttle = 0.0 - last_brake = 0.0 - - # 6. 核心驾驶循环 - print(f"\n🚗 开始自动驾驶 | 直道{BASE_SPEED}m/s | 弯道{CURVE_TARGET_SPEED}m/s") - print("💡 按 Ctrl+C 停止程序\n") - - try: - while True: - # 获取车辆当前状态 - velocity = vehicle.get_velocity() - current_speed = math.hypot(velocity.x, velocity.y) - current_yaw = vehicle.get_transform().rotation.yaw - - # 识别弯道与目标航向 - target_yaw, is_curve, yaw_diff = get_road_direction_ahead(vehicle, world) - - # 弯道渐进减速/直道恢复速度 - if is_curve: - current_target_speed = max(CURVE_TARGET_SPEED, current_target_speed - SPEED_TRANSITION_RATE) - else: - current_target_speed = min(BASE_SPEED, current_target_speed + SPEED_TRANSITION_RATE / 2) - - # 平滑速度控制(无抖动) - speed_error = current_target_speed - current_speed - if abs(speed_error) < SPEED_DEADZONE: - control.throttle = last_throttle * 0.85 - control.brake = 0.0 - elif speed_error > 0: - control.throttle = min(last_throttle + ACCELERATION_FACTOR, 0.25) - control.brake = 0.0 - last_throttle = control.throttle - else: - control.brake = min(last_brake + DECELERATION_FACTOR, 0.2) - control.throttle = 0.0 - last_brake = control.brake - - # 超大角度转向控制 - target_steer = calculate_steer_angle(current_yaw, target_yaw) - current_steer = current_steer + (target_steer - current_steer) * STEER_RESPONSE_FACTOR - control.steer = current_steer - - # 下发控制指令 - vehicle.apply_control(control) - - # 实时状态显示 - curve_status = "🔴 弯道(减速中)" if is_curve else "🟢 直道" - status_info = ( - f"{curve_status:12s} | 航向偏差:{yaw_diff:.0f}° " - f"| 转向角:{current_steer:.2f}(最大:{STEER_ANGLE_MAX}) " - f"| 速度:{current_speed:.2f}m/s(目标:{current_target_speed:.2f})" - ) - print(f"\r{status_info}", end="") - - time.sleep(0.1) - - except KeyboardInterrupt: - print("\n\n🛑 接收到停止指令,正在清理资源...") - finally: - # 销毁车辆,恢复世界设置 - if vehicle and vehicle.is_alive: - vehicle.destroy() - print("✅ 车辆已销毁") - world.apply_settings(carla.WorldSettings(synchronous_mode=False)) - print("✅ 程序正常退出") - - -# ====================== 程序入口 ====================== -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/src/V2X_edge_intelligence/src/main4.py b/src/V2X_edge_intelligence/src/main4.py new file mode 100644 index 0000000000..46d23d8f78 --- /dev/null +++ b/src/V2X_edge_intelligence/src/main4.py @@ -0,0 +1,229 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +CARLA 0.9.10 +""" +import sys +import os +import time +import math + +# ====================== 1. CARLA加载(兼容相对路径,无硬编码绝对路径) ====================== +# 优先从项目内carla_lib加载,无则回退到默认路径(保证兼容性) +CURRENT_DIR = os.path.dirname(os.path.abspath(__file__)) +CARLA_LIB_DIR = os.path.join(CURRENT_DIR, "../carla_lib") # 上级目录carla_lib +DEFAULT_CARLA_PATH = "D:/WindowsNoEditor" + +# 自动查找egg文件 +egg_file = None +# 尝试项目内carla_lib +if os.path.exists(CARLA_LIB_DIR): + egg_files = [f for f in os.listdir(CARLA_LIB_DIR) if f.endswith(".egg") and "0.9.10" in f] + if egg_files: + egg_file = os.path.join(CARLA_LIB_DIR, egg_files[0]) +# 回退到默认路径 +if not egg_file: + egg_file = os.path.join(DEFAULT_CARLA_PATH, "PythonAPI", "carla", "dist", "carla-0.9.10-py3.7-win-amd64.egg") + +try: + sys.path.append(egg_file) + import carla + print(f"✅ CARLA加载成功(egg路径:{egg_file})") +except Exception as e: + print(f"❌ CARLA加载失败:{e}") + print("请确保:1. CARLA egg文件存在 2. Python版本为3.7") + sys.exit(1) + +# ====================== 2. 核心参数(全部最优适配,核心增大转向角度) ====================== +# 速度参数(不变:低速平稳无抖动) +BASE_SPEED = 1.5 # 直道速度 1.5m/s +CURVE_TARGET_SPEED = 1.0 # 弯道速度 1.0m/s +SPEED_DEADZONE = 0.1 +ACCELERATION_FACTOR = 0.04 +DECELERATION_FACTOR = 0.06 +SPEED_TRANSITION_RATE = 0.03 + +# 晚转弯核心参数【不变】:仅前方5米触发转向,接近弯道才转 +LOOKAHEAD_DISTANCE = 20.0 # 20米前瞻 提前减速 +WAYPOINT_STEP = 1.0 +CURVE_DETECTION_THRESHOLD = 2.0 +TURN_TRIGGER_DISTANCE_IDX = 4 # 前方5米 触发转向 (晚转弯核心) + +# ========== 本次核心修改:拉满转弯角度 解决角度不够 ========== +STEER_ANGLE_MAX = 0.85 # 最大转向角拉满到0.85【重中之重】之前0.7,角度大幅增大 +STEER_RESPONSE_FACTOR = 0.4 # 转向响应拉满0.4 最快响应,晚转+大角度一步到位 +STEER_AMPLIFY = 1.6 # 转向角放大系数倍增到1.6 小偏差也能转出超大角度 +MIN_STEER = 0.2 # 最小转向角提高到0.2 强制保底转向力度 绝对不转不动 + +# 出生点偏移【不变】:左移2米 +SPAWN_OFFSET_X = -2.0 +SPAWN_OFFSET_Y = 0.0 +SPAWN_OFFSET_Z = 0.0 + +# ====================== 3. 核心工具函数 ====================== +def get_road_direction_ahead(vehicle, world): + """晚转弯逻辑不变:前方5米判定转向,20米提前减速""" + vehicle_transform = vehicle.get_transform() + carla_map = world.get_map() + + waypoints = [] + current_wp = carla_map.get_waypoint(vehicle_transform.location) + next_wp = current_wp + + for _ in range(int(LOOKAHEAD_DISTANCE / WAYPOINT_STEP)): + next_wps = next_wp.next(WAYPOINT_STEP) + if not next_wps: + break + next_wp = next_wps[0] + waypoints.append(next_wp) + + if len(waypoints) < 3: + return vehicle_transform.rotation.yaw, False, 0.0 + + # 晚转弯核心:仅取前方5米的道路点判定方向 + target_wp_idx = min(TURN_TRIGGER_DISTANCE_IDX, len(waypoints)-1) + target_wp = waypoints[target_wp_idx] + target_yaw = target_wp.transform.rotation.yaw + + current_yaw = vehicle_transform.rotation.yaw + yaw_diff = target_yaw - current_yaw + yaw_diff = (yaw_diff + 180) % 360 - 180 + is_curve = abs(yaw_diff) > CURVE_DETECTION_THRESHOLD + + return target_yaw, is_curve, yaw_diff + +def calculate_steer_angle(current_yaw, target_yaw): + """核心:超大角度转向计算,绝对够力度转进直道""" + yaw_diff = target_yaw - current_yaw + yaw_diff = (yaw_diff + 180) % 360 - 180 + + # 三重放大:最大角度+系数放大+最小转向角 保证转弯角度绝对足够 + steer = (yaw_diff / 180.0 * STEER_ANGLE_MAX) * STEER_AMPLIFY + steer = max(-STEER_ANGLE_MAX, min(STEER_ANGLE_MAX, steer)) + + # 强制最小转向力度:哪怕极缓弯道,也有足够角度,杜绝转不动 + if abs(steer) > 0.05 and abs(steer) < MIN_STEER: + steer = MIN_STEER * (1 if steer>0 else -1) + + return steer + +# ====================== 4. 主函数(唯一入口) ====================== +def main(): + try: + client = carla.Client('localhost', 2000) + client.set_timeout(10.0) + world = client.load_world('Town01') + world.set_weather(carla.WeatherParameters.ClearNoon) + world.apply_settings(carla.WorldSettings(synchronous_mode=False,fixed_delta_seconds=0.1)) + print("✅ 已连接CARLA并加载Town01地图") + except Exception as e: + print(f"❌ 连接CARLA失败:{e}") + return + + # 清理旧车辆 + for actor in world.get_actors().filter('vehicle.*'): + actor.destroy() + print("✅ 已清理旧车辆") + + # 生成车辆 + 出生点左移2米 【不变】 + bp_lib = world.get_blueprint_library() + veh_bp = bp_lib.filter("vehicle")[0] + veh_bp.set_attribute('color', '255,0,0') + + spawn_points = world.get_map().get_spawn_points() + original_spawn_point = spawn_points[0] + spawn_point = carla.Transform( + carla.Location( + x=original_spawn_point.location.x + SPAWN_OFFSET_X, + y=original_spawn_point.location.y + SPAWN_OFFSET_Y, + z=original_spawn_point.location.z + SPAWN_OFFSET_Z + ), + original_spawn_point.rotation + ) + vehicle = world.spawn_actor(veh_bp, spawn_point) + print(f"✅ 车辆生成成功(出生点左移{abs(SPAWN_OFFSET_X)}米)") + print(f" 调整后位置:({spawn_point.location.x:.1f}, {spawn_point.location.y:.1f})") + + # 视角同步左移 + spectator = world.get_spectator() + spec_loc = carla.Location(x=spawn_point.location.x,y=spawn_point.location.y,z=40.0) + spec_rot = carla.Rotation(pitch=-85.0,yaw=spawn_point.rotation.yaw,roll=0.0) + spectator.set_transform(carla.Transform(spec_loc, spec_rot)) + print("\n✅ 视角已定位到车辆上方(俯视视角)") + + # 初始化控制参数 + control = carla.VehicleControl() + control.hand_brake = False + control.manual_gear_shift = False + control.gear = 1 + + current_steer = 0.0 + current_target_speed = BASE_SPEED + last_throttle = 0.0 + last_brake = 0.0 + + print(f"\n🚗 开始自动驾驶(直道{BASE_SPEED}m/s | 弯道减速至{CURVE_TARGET_SPEED}m/s)...") + print("✅ 超大转弯角度+晚转弯+左移出生点,所有需求全部满足!") + print("💡 按Ctrl+C停止程序\n") + + try: + while True: + # 获取车辆状态 + velocity = vehicle.get_velocity() + current_speed = math.hypot(velocity.x, velocity.y) + current_yaw = vehicle.get_transform().rotation.yaw + + # 晚转弯+弯道识别 + target_yaw, is_curve, yaw_diff = get_road_direction_ahead(vehicle, world) + + # 弯道渐进减速 【不变】 + if is_curve: + current_target_speed = max(CURVE_TARGET_SPEED, current_target_speed - SPEED_TRANSITION_RATE) + else: + current_target_speed = min(BASE_SPEED, current_target_speed + SPEED_TRANSITION_RATE/2) + + # 平滑速度控制 无抖动 【不变】 + speed_error = current_target_speed - current_speed + if abs(speed_error) < SPEED_DEADZONE: + control.throttle = last_throttle * 0.85 + control.brake = 0.0 + elif speed_error > 0: + control.throttle = min(last_throttle + ACCELERATION_FACTOR, 0.25) + control.brake = 0.0 + last_throttle = control.throttle + else: + control.brake = min(last_brake + DECELERATION_FACTOR, 0.2) + control.throttle = 0.0 + last_brake = control.brake + + # ========== 核心:超大角度+最快响应转向 ========== + target_steer = calculate_steer_angle(current_yaw, target_yaw) + current_steer = current_steer + (target_steer - current_steer) * STEER_RESPONSE_FACTOR + control.steer = current_steer + + # 下发指令 + vehicle.apply_control(control) + + # 状态显示 + curve_status = "🔴 弯道(减速中)" if is_curve else "🟢 直道" + speed_info = f"当前:{current_speed:.2f}m/s 目标:{current_target_speed:.2f}m/s" + steer_info = f"{current_steer:.2f}(最大:{STEER_ANGLE_MAX})" + yaw_info = f"偏差:{yaw_diff:.0f}°" + + print(f"\r{curve_status:12s} | {yaw_info} | 转向角:{steer_info} | 速度:{speed_info}", end="") + + time.sleep(0.1) + + except KeyboardInterrupt: + print("\n\n🛑 停止程序...") + + # 清理资源 + if vehicle and vehicle.is_alive: + vehicle.destroy() + print("✅ 车辆已销毁") + world.apply_settings(carla.WorldSettings(synchronous_mode=False)) + print("✅ 程序正常退出") + +# ====================== 唯一程序入口 ====================== +if __name__ == "__main__": + main() \ No newline at end of file From 1f18a8923a0376b27d74da7d93b57f62a142329b Mon Sep 17 00:00:00 2001 From: ou-yang220 <2101542906@qq.com> Date: Sat, 27 Dec 2025 12:11:32 +0800 Subject: [PATCH 11/11] =?UTF-8?q?=E5=8C=BA=E5=9F=9F=E9=99=90=E9=80=9F?= =?UTF-8?q?=E8=A1=8C=E9=A9=B6=EF=BC=9A=E6=96=B0=E5=A2=9E=E4=B8=89=E7=A7=8D?= =?UTF-8?q?=E4=B8=8D=E5=90=8C=E9=99=90=E9=80=9F=E8=B7=AF=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/V2X_edge_intelligence/src/main7.py | 271 +++++++++++++++++++++++++ 1 file changed, 271 insertions(+) create mode 100644 src/V2X_edge_intelligence/src/main7.py diff --git a/src/V2X_edge_intelligence/src/main7.py b/src/V2X_edge_intelligence/src/main7.py new file mode 100644 index 0000000000..8086db9eb2 --- /dev/null +++ b/src/V2X_edge_intelligence/src/main7.py @@ -0,0 +1,271 @@ +# main.py(CARLA V2X三区均衡变速测试 - 唯一入口+无绝对路径) +import sys +import os +import time +import json +import math + +# ===================== 1. 自动适配CARLA路径(无绝对路径) ===================== +def setup_carla_path(): + """ + 自动配置CARLA PythonAPI路径(优先级:环境变量 > 相对路径 > 手动输入) + 彻底移除硬编码绝对路径,适配不同环境/安装位置 + """ + # 优先级1:读取系统环境变量(推荐长期使用) + carla_api_env = os.environ.get("CARLA_PYTHON_API_PATH") + if carla_api_env and os.path.exists(carla_api_env): + egg_files = [f for f in os.listdir(carla_api_env) if f.endswith(".egg")] + if egg_files: + carla_egg = os.path.join(carla_api_env, egg_files[0]) + print(f"🔍 从环境变量加载CARLA egg:{carla_egg}") + sys.path.insert(0, carla_egg) + return True + + # 优先级2:自动查找常见相对路径(适配多数用户目录结构) + common_relative_paths = [ + "./PythonAPI/carla/dist", # 当前目录下的CARLA API + "../WindowsNoEditor/PythonAPI/carla/dist", # 上级目录的CARLA + "./WindowsNoEditor/PythonAPI/carla/dist" # 当前目录的CARLA + ] + for path in common_relative_paths: + if os.path.exists(path): + egg_files = [f for f in os.listdir(path) if f.endswith(".egg")] + if egg_files: + carla_egg = os.path.join(path, egg_files[0]) + print(f"🔍 自动找到CARLA egg:{carla_egg}") + sys.path.insert(0, carla_egg) + return True + + # 优先级3:提示用户手动输入(兜底方案) + print("\n⚠️ 未自动识别CARLA PythonAPI路径!") + print("📌 请先配置环境变量(推荐):") + print(" Windows: set CARLA_PYTHON_API_PATH=你的CARLA路径\\PythonAPI\\carla\\dist") + print(" Linux/Mac: export CARLA_PYTHON_API_PATH=你的CARLA路径/PythonAPI/carla/dist") + manual_path = input("\n请输入CARLA egg文件所在目录(留空退出):").strip() + if manual_path and os.path.exists(manual_path): + egg_files = [f for f in os.listdir(manual_path) if f.endswith(".egg")] + if egg_files: + carla_egg = os.path.join(manual_path, egg_files[0]) + sys.path.insert(0, carla_egg) + print(f"✅ 手动加载CARLA egg:{carla_egg}") + return True + + return False + +# 初始化CARLA路径(无绝对路径) +print(f"🔍 当前Python解释器路径:{sys.executable}") +print(f"🔍 当前Python版本:{sys.version.split()[0]}") + +if not setup_carla_path(): + print("\n❌ 无法加载CARLA PythonAPI,请检查路径配置!") + sys.exit(1) + +# 导入CARLA(适配0.9.10+版本) +try: + import carla + print("✅ CARLA模块导入成功!") +except Exception as e: + print(f"\n❌ CARLA导入失败:{str(e)}") + sys.exit(1) + +# ===================== 2. 核心逻辑:三区均衡分配+低速精准控速 ===================== +class RoadSideUnit: + def __init__(self, carla_world, vehicle): + self.world = carla_world + self.vehicle = vehicle + # 三区等距坐标(基于车辆生成位置动态计算,无绝对坐标) + spawn_loc = vehicle.get_location() + # 高速区:生成位置前5-15米(长度10米) + self.high_zone_start = carla.Location(spawn_loc.x, spawn_loc.y + 5, spawn_loc.z) + self.high_zone_end = carla.Location(spawn_loc.x, spawn_loc.y + 15, spawn_loc.z) + # 中速区:生成位置前15-25米(长度10米) + self.mid_zone_start = carla.Location(spawn_loc.x, spawn_loc.y + 15, spawn_loc.z) + self.mid_zone_end = carla.Location(spawn_loc.x, spawn_loc.y + 25, spawn_loc.z) + # 低速区:生成位置前25-35米(长度10米) + self.low_zone_start = carla.Location(spawn_loc.x, spawn_loc.y + 25, spawn_loc.z) + self.low_zone_end = carla.Location(spawn_loc.x, spawn_loc.y + 35, spawn_loc.z) + + # 三区计时逻辑(确保每区停留10秒) + self.current_zone = "high" # 初始区:高速 + self.zone_start_time = time.time() + self.zone_duration = 10 # 每区停留10秒(30秒测试周期) + self.speed_map = {"high": 40, "mid": 25, "low": 10} + + def get_balance_speed_limit(self): + """计时+位置双重判断,确保三区平均分配""" + current_time = time.time() + vehicle_loc = self.vehicle.get_location() + vehicle_y = vehicle_loc.y + spawn_y = self.vehicle.get_location().y + + # 1. 计时强制切换:每区停留10秒必切换 + if current_time - self.zone_start_time > self.zone_duration: + zone_switch = {"high": "mid", "mid": "low", "low": "high"} + self.current_zone = zone_switch[self.current_zone] + self.zone_start_time = current_time + + # 2. 位置验证:确保区域与物理位置匹配 + if spawn_y + 5 <= vehicle_y < spawn_y + 15: + self.current_zone = "high" + elif spawn_y + 15 <= vehicle_y < spawn_y + 25: + self.current_zone = "mid" + elif spawn_y + 25 <= vehicle_y < spawn_y + 35: + self.current_zone = "low" + + # 返回速度和区域名称 + speed_limit = self.speed_map[self.current_zone] + zone_name = { + "high": "高速区(40km/h)", + "mid": "中速区(25km/h)", + "low": "低速区(10km/h)" + }[self.current_zone] + return speed_limit, zone_name + + def send_speed_command(self, vehicle_id, speed_limit, zone_type): + command = { + "vehicle_id": vehicle_id, + "speed_limit_kmh": speed_limit, + "zone_type": zone_type, + "timestamp": time.time() + } + print(f"\n📡 路侧V2X指令:{json.dumps(command, indent=2, ensure_ascii=False)}") + return command + +class VehicleUnit: + def __init__(self, vehicle): + self.vehicle = vehicle + self.vehicle.set_autopilot(False) + self.control = carla.VehicleControl() + self.control.steer = 0.0 # 强制直行 + self.control.hand_brake = False + print("✅ 车辆已设置为手动直行(三区精准控速)") + + def get_actual_speed(self): + """计算车辆实际速度(km/h)""" + velocity = self.vehicle.get_velocity() + speed_kmh = math.sqrt(velocity.x ** 2 + velocity.y ** 2 + velocity.z ** 2) * 3.6 + return round(speed_kmh, 1) + + def precise_speed_control(self, target_speed): + """三区精准控速,低速区加大油门确保到10km/h""" + actual_speed = self.get_actual_speed() + + # 高速区:38-42km/h + if target_speed == 40: + if actual_speed > 42: + self.control.throttle = 0.0 + self.control.brake = 0.4 + elif actual_speed < 38: + self.control.throttle = 0.9 + self.control.brake = 0.0 + else: + self.control.throttle = 0.2 + self.control.brake = 0.0 + + # 中速区:23-27km/h + elif target_speed == 25: + if actual_speed > 27: + self.control.throttle = 0.0 + self.control.brake = 0.3 + elif actual_speed < 23: + self.control.throttle = 0.6 + self.control.brake = 0.0 + else: + self.control.throttle = 0.1 + self.control.brake = 0.0 + + # 低速区:9-11km/h(0.4油门确保速度达标) + elif target_speed == 10: + if actual_speed > 11: + self.control.throttle = 0.0 + self.control.brake = 0.2 + elif actual_speed < 9: + self.control.throttle = 0.4 # 加大油门确保到10km/h + self.control.brake = 0.0 + else: + self.control.throttle = 0.15 + self.control.brake = 0.0 + + self.vehicle.apply_control(self.control) + return actual_speed + + def receive_speed_command(self, command): + target_speed = command["speed_limit_kmh"] + actual_speed = self.precise_speed_control(target_speed) + print( + f"🚗 车载执行:目标{target_speed}km/h → 实际{actual_speed}km/h | 油门={round(self.control.throttle, 1)} 刹车={round(self.control.brake, 1)}") + +# ===================== 3. 近距离视角配置 ===================== +def set_near_observation_view(world, vehicle): + """设置车辆后方近距离视角(无绝对坐标)""" + spectator = world.get_spectator() + vehicle_transform = vehicle.get_transform() + forward_vector = vehicle_transform.rotation.get_forward_vector() + right_vector = vehicle_transform.rotation.get_right_vector() + view_location = vehicle_transform.location - forward_vector * 8 + right_vector * 2 + carla.Location(z=2) + view_rotation = carla.Rotation(pitch=-15, yaw=vehicle_transform.rotation.yaw, roll=0) + spectator.set_transform(carla.Transform(view_location, view_rotation)) + print("✅ 初始视角已设置:车辆后方近距离") + print("📌 视角操作:鼠标拖拽=旋转 | 滚轮=缩放 | WASD=移动") + +def get_valid_spawn_point(world): + """获取道路有效生成点(无绝对坐标)""" + spawn_points = world.get_map().get_spawn_points() + valid_spawn = spawn_points[10] if len(spawn_points) >= 10 else spawn_points[5] + print(f"✅ 车辆生成位置:(x={valid_spawn.location.x:.1f}, y={valid_spawn.location.y:.1f})") + return valid_spawn + +# ===================== 4. 主入口逻辑(唯一入口) ===================== +def main(): + # 1. 连接CARLA服务器(通用提示,无绝对路径) + try: + client = carla.Client('localhost', 2000) + client.set_timeout(20.0) + world = client.get_world() + print(f"\n✅ 连接CARLA成功!服务器版本:{client.get_server_version()}") + except Exception as e: + print(f"\n❌ CARLA服务器连接失败:{str(e)}") + print("📌 请先启动CARLA服务器(通用路径参考):") + print(" Windows: ./WindowsNoEditor/CarlaUE4.exe") + print(" Linux/Mac: ./CarlaUE4.sh") + sys.exit(1) + + # 2. 生成测试车辆(红色车身) + try: + bp_lib = world.get_blueprint_library() + vehicle_bp = bp_lib.filter('vehicle.tesla.model3')[0] + vehicle_bp.set_attribute('color', '255,0,0') + valid_spawn = get_valid_spawn_point(world) + vehicle = world.spawn_actor(vehicle_bp, valid_spawn) + print(f"✅ 车辆生成成功,ID:{vehicle.id}(红色车身)") + except Exception as e: + print(f"\n❌ 车辆生成失败:{str(e)}") + sys.exit(1) + + # 3. 初始化V2X组件+设置视角 + rsu = RoadSideUnit(world, vehicle) + vu = VehicleUnit(vehicle) + set_near_observation_view(world, vehicle) + + # 4. 启动三区均衡测试 + print("\n✅ 开始V2X三区均衡变速测试(30秒)...") + print("📌 高速/中速/低速区各停留10秒,低速精准到10km/h!") + start_time = time.time() + try: + while time.time() - start_time < 30: + speed_limit, zone_type = rsu.get_balance_speed_limit() + command = rsu.send_speed_command(vehicle.id, speed_limit, zone_type) + vu.receive_speed_command(command) + time.sleep(1) # 1秒高频更新,响应更快 + except KeyboardInterrupt: + print("\n⚠️ 用户手动中断测试") + finally: + # 安全停车并销毁车辆 + vehicle.apply_control(carla.VehicleControl(brake=1.0, throttle=0.0, steer=0.0)) + time.sleep(2) + vehicle.destroy() + print("\n✅ 测试结束,车辆已销毁") + +# 唯一入口(确保仅main.py作为脚本运行) +if __name__ == "__main__": + main() \ No newline at end of file