一、安装并编译 UE4
1 、 Carla 安装前的环境准备
(ubuntu20.04 ):
|---------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| python3.8版本及以上;pip3正常使用; 掉过头重新说明一下,由于官方carla0.9.16中的编译文件只有cp310、cp311、cp312(之前官方明确规定仅支持python3.7~3.9,此次carla也是最新版,可能有所改变),所以支持python3.10~3.12版本。本次选择python3.10.12 |
2 、 python 环境完成后,安装所需包
|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| SQL pip3 install --user pygame numpy pip install --user setuptools && pip3 install --user -Iv setuptools==47.3.1 && pip install --user distro && pip3 install --user distro && pip install --user wheel && pip3 install --user wheel auditwheel |
安装过程中如果遇到:
|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Plain Text ERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts. launchpadlib 1.10.13 requires testresources, which is not installed. |
这里说明我们要更新 numpy 版本,然后按照提示安装 launchpadlib 后再安装:
|-------------------------------------------------------------------|
| Plain Text pip3 install --upgrade numpy pip3 install launchpadlib |
这里由于我们是使用 python 语言进行开发,所以这里最重要的就是安装 python3 ,其他环境安装如下:
|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| SQL sudo apt-get update && sudo apt-get install wget software-properties-common && sudo add-apt-repository ppa:ubuntu-toolchain-r/test && wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key\|sudo apt-key add - && sudo apt-add-repository "deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-8 main" && sudo apt-get update |
3 、安装 Carla 和它的相关引擎
这里不同系统版本对应不同的安装指令【官网进行查看:How to build Carla on Ubuntu 】。这里使用的是 Ubuntu 20.04 版本,我们要保证Carla和它的引擎UnrealEngine用的是一个版本的Clang,命令如下:
|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| SQL sudo apt-add-repository "deb http://apt.llvm.org/focal/ llvm-toolchain-focal main" sudo apt-get install build-essential clang-10 lld-10 g++-7 cmake ninja-build libvulkan1 python python-dev python3-dev python3-pip libpng-dev libtiff5-dev libjpeg-dev tzdata sed curl unzip autoconf libtool rsync libxml2-dev git sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/lib/llvm-10/bin/clang++ 180 && sudo update-alternatives --install /usr/bin/clang clang /usr/lib/llvm-10/bin/clang 18 |
4 、 UE4 安装
|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 我们安装的是Carla0.9.16,从 Carla 0.9.12 版本开始,使用的是 Unreal Engine 4.26 的改进型分叉,此分叉包含 Carla 特有的补丁。 在安装 Carla 0.9.16 时,需要先安装 Unreal Engine 4.26,可以通过将 GitHub 账户与 Unreal Engine 账户连接后,从 GitHub 上克隆 Carla 指定的 UE4 分支进行安装 |
a 、注册并登录账户
terminal安装git,并进行登录:
|---------------------------------------------------------------|
| Plain Text # 可在https://github.com/官网提前注册 sudo apt install git |
登录Feed - Unreal Engine,可以直接使用Epic账号邮箱密码登录
b 、接下来要完成 Github 和 UnrealEngine 的关联
连接方法可以参考该链接www.unrealengine.com,或者可以根据下面的方法:
- 使用经过验证的Epic Games帐户登录www.unrealengine.com,单击右上角网站标题栏中的用户名,然后选择personal选项。
- 从菜单中选择连接的账户(APPS AND ACCOUNTS),单击Github图标下方的连接。
- 查看《虚幻引擎最终用户许可协议》并选中对应复选框接受该协议,然后单击关联您的账户按钮(如果已经接受了最新版本的《虚幻引擎最终用户许可协议》,则不会显示该提示)。
- 登录现有GitHub帐户。
- 单击授权按钮,之后你会收到Gibhub发的一封EpicTeamAdmin邀请您加入确认的邮件,单击join @EpicGames完成关联流程。
- 需要进入https://github.com/EpicGames- Connect to preview 点击Follow

|----------------------------------------|
| 确认好上述均完成后,尤其是github和Rpic账号关联,再进行下面的操作。 |
c 、 Github Repo Clone
【这步主要是将UnrealEngine4.26git clone到自己ubuntu的home目录下,大概要花费90G---100G左右空间。】
|--------------------------------------------------------------------------------------------------------------|
| Plain Text git clone --depth 1 -b carla https://github.com/CarlaUnreal/UnrealEngine.git ~/UnrealEngine_4.26 |
可能会遇到git连接问题:
|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Plain Text trunk@trunk:~$ git clone --depth 1 -b carla https://github.com/CarlaUnreal/UnrealEngine.git ~/UnrealEngine_4.26 正克隆到 '/home/trunk/UnrealEngine_4.26'... fatal: 无法访问 'https://github.com/CarlaUnreal/UnrealEngine.git/':Failed to connect to github.com port 443: 连接超时 |
|--------------------------------------------------------------------------------------------------|
| 解决方法: 1.在项目文件夹的命令行窗口执行下面代码,然后再git commit 或git clone 取消git本身的https代理,使用自己本机的代理,如果没有的话,其实默认还是用git的 |
|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Plain Text //取消http代理 git config --global --unset http.proxy //取消https代理 git config --global --unset https.proxy // 要是还不行,试试 git config --global http.sslVerify "false" |
克隆过程中需要github的username(登录的用户名,不是邮箱 )和password(GitHub 个人访问令牌( Personal Access Token ))
|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 如何获取个人访问令牌( PAT ): 1. 登录 GitHub → 点击头像 → 选择 Settings; 1. 左侧菜单拉到最下方,选择 Developer settings → Personal access tokens → Tokens (classic); 1. 点击 Generate new token → Generate new token (classic); 1. 填写 Note(如 "clone UE4"),勾选 repo 权限(必须勾选,否则无仓库访问权限),其他保持默认; 1. 点击 Generate token,生成后立即复制令牌(关闭页面后无法再查看)。 |
以下是正常的界面:

5 、编译 UE4
|--------------------------------------------------------------------------------------------------------------------------|
| Plain Text cd UnrealEngine_4.26/ ./Setup.sh && ./GenerateProjectFiles.sh && make # 编译的时间可能很长.......因为,UE4.26分支源码规模很大 |


6 、测试 UE4 环境
|-----------------------------------------------------------------------------------|
| Plain Text # 启动UE4 cd ~/UnrealEngine_4.26/Engine/Binaries/Linux && ./UE4Editor |


|---------------------------------------------------------------------------|
| 测试完成,需要把UnrealEngine的路径添加到~/.bashrc中; 末行添加"UE4_ROOT=~/UnrealEngine_4.26" |

二、安装 Carla0.9.16
找到相应的版本包:Release 0.9.16 · carla-simulator/carla(git下载有点慢)

下载完成后,解压(路径/home/trunk/carla_0.9.16/;其中carla目录需要自己提前创建)
进入carla_0.9.16/运行【./CarlaUE4.sh】,运行carla:

|-----------------------------------------------------------------|
| 目前成功安装,但运行结果不太满意:卡?硬件?着色器?------------------------显卡驱动未安装,调动显卡: |
|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Plain Text # 安装驱动 sudo add-apt-repository ppa:graphics-drivers/ppa sudo apt update sudo apt install nvidia-driver-535 nvidia-utils-535 # 重启 sudo reboot now # 查看显卡 nvidia-smi # 开始操作 cd ~/carla_0.9.16 ./CarlaUE4.sh -opengl -ResX=1280 -ResY=720 # 强制OpenGL+降低分辨率 # 完美运行! |

三、测试 Carla , Bug 解决中
|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 在路径~/carla_0.9.16/PythonAPI/examples 执行:pip3 install -r requirements.txt 安装依赖 遇到问题,无法执行python3的相关脚本,原因是查看PythonAPI/carla/dist,下面只有cp310、cp311和cp312的whl,没有python3,8所对应的cp38!!! 所以又从git上进行进行clone一个carla的文件夹【之前的包也是从git官网下的,很奇怪】 之前的操作是 "安装预编译包" (下载现成的编译好的文件,直接启动),而现在是 "源码编译"(从官方源码出发,根据电脑的 Python 版本、系统环境,重新生成适配的 Carla 程序和库)。 |
|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Plain Text # 克隆官方的源码 git clone -b 0.9.16 https://github.com/carla-simulator/carla.git cd carla # ./Update.sh 的作用:只下载地图、车辆模型等资产文件; # Util/Setup.sh 的作用:安装编译必需的系统依赖(编译器、开发库等) ./Update.sh ./Setup.sh【版本不同Setup.sh所在位置不同】 |

1 、直接安装 Python3.10 及其以上版本
|----------------------------------------------------------------------------------|
| 因为carla0.9.16里面的whl文件只有cp301~cp312。之前尝试强制使用3.8版本去运行,失败;直接保留carla,更改python版本去适配。 |

2 、安装好之后,回到 dist 目录下,进行编译

3 、启动并测试
|--------------------------------------------------------------------------------------------------------------------------------------------------------|
| Plain Text # 启动引擎并加载 Town04 高速地图(后台运行,不占用终端) ./CarlaUE4.sh -carla-map=Town04 & # 引擎必须启动,才能执行后续脚本和方针运行 # 执行脚本测试 python3.10 manual_control.py 测试成功! |

四、了解和学习命令
1 、了解文件和简单命令
|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Plain Text 执行manual_control.py(Carla****最基础的 "手动控制车辆" 示例 )。 键盘AWSD,分别控制左拐、前进加速、制动刹停、右拐;(S制动) 空格刹车; P是切换自动驾驶和人工; Z是左转向灯,X是右转向灯(二者任一单独按两次即使双闪); Q是切换前进/后退; C控制变换天气; |
a 、知悉脚本
- automatic_control.py:纯自动驾驶脚本;
- generate_traffic.py:批量生成自动驾驶的车辆和行人,自定义数量、车速、行为(如加塞、绕行),-n 车辆数、-p 行人数、--speed 最大车速;
- vehicle_gallery.py:列出 Carla 所有可用车型
- dynamic_weather.py:动态切换天气(晴、雨、雾、雪),还能调节时间(日出 / 日落)
- start_recording.py :记录仿真过程中的所有数据(车辆运动、传感器、交通灯、碰撞事件),保存为 .log 文件
- start_replaying.py:回放之前记录的日志文件,重现场景(支持快进、慢放、指定时间点开始)
- show_recorder_collisions.py:分析记录文件,显示所有碰撞事件(时间、碰撞的车辆 / 行人),用于事故分析
- no_rendering_mode.py:关闭图形渲染(只保留物理仿真),大幅提升帧率,适合批量采集数据、训练算法(无需可视化)
- synchronous_mode.py:同步模式(Python 脚本与 Carla 引擎帧率同步),避免数据丢失,适合高精度仿真
- tutorial.py:Carla Python API 入门教程,一步步教你创建车辆、添加传感器、控制运动,带详细注释。
- V2XDemo.py:车联网(V2X)演示,车辆之间、车辆与路侧设备通信,适合车路协同场景测试。
- 自定义脚本:完全自己写的,可以尝试一下··················
b 、地图选择
|-------------------------------------------------|
| Plain Text # 按"~"进入控制台,然后使用命令"Open Town04"切换地图 |

|-----------------------------------------------------------------------------------------------------------------------------------------|
| Plain Text # 目前只有Town01~05的五张基础地图,其余需要可以下载拓展地图(官网) # 下载官方拓展地图包,然后放到carla_0.9.16/Import/下,然后执行ImportAssets.sh脚本即可。 # 下面是Town06,模拟的高速道路。 |

2 、实现简单的交互场景
源代码:
|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Python import carla import random import time import subprocess import os # 核心配置 CARLA_PATH = "/home/trunk/carla_0.9.16" HOST = '127.0.0.1' PORT = 2000 MAP_NAME = "Town06" EGO_VEHICLE_COLOR = "255,0,0" # 自车红色 EGO_SPEED_KMH = 85 STATIC_CARS_NUM = 3 LEFT_CARS_NUM = 8 RIGHT_CARS_NUM = 8 MIDDLE_MOVING_CARS = 2 SIDE_CARS_SPEED_MIN = 75 SIDE_CARS_SPEED_MAX = 82 FIXED_VIEW_LOCATION = carla.Location(x=100, y=0, z=35) FIXED_VIEW_ROTATION = carla.Rotation(pitch=-70, yaw=0) def start_carla_server(): """检查并启动 Carla 服务器""" print("正在检查 Carla 服务器是否运行...") try: client = carla.Client(HOST, PORT) client.set_timeout(2.0) client.get_world() print("Carla 服务器已在运行。") return True except RuntimeError: print("未检测到 Carla 服务器,正在尝试启动...") carla_sh_path = os.path.join(CARLA_PATH, "CarlaUE4.sh") if not os.path.exists(carla_sh_path): print(f"错误:无法找到 Carla 启动脚本 {carla_sh_path}") return False subprocess.Popen([carla_sh_path, f"-carla-map={MAP_NAME}"], stdout=subprocess.PIPE, stderr=subprocess.PIPE) print("等待 Carla 服务器启动... (30-60 秒)") time.sleep(30) try: client = carla.Client(HOST, PORT) client.set_timeout(10.0) client.get_world() print("Carla 服务器启动成功!") return True except RuntimeError as e: print(f"错误:启动 Carla 服务器失败。{e}") return False def is_straight_waypoint(waypoint, distance=15.0): """判断路点是否为直线(适配 Carla 0.9.16)""" next_waypoints = waypoint.next(distance) if not next_waypoints: return False next_waypoint = next_waypoints[0] current_yaw = waypoint.transform.rotation.yaw next_yaw = next_waypoint.transform.rotation.yaw yaw_diff = abs(current_yaw - next_yaw) yaw_diff = min(yaw_diff, 360 - yaw_diff) return yaw_diff < 1.5 def get_three_consecutive_lanes(world): """筛选连续三条直线车道""" spawn_points = world.get_map().get_spawn_points() straight_spawns = [] for sp in spawn_points: waypoint = world.get_map().get_waypoint(sp.location) if waypoint.lane_type == carla.LaneType.Driving and is_straight_waypoint(waypoint): straight_spawns.append((sp, waypoint.lane_id)) lane_spawns = {} for sp, lane_id in straight_spawns: if lane_id not in lane_spawns: lane_spawns[lane_id] = [] lane_spawns[lane_id].append(sp) sorted_lane_ids = sorted(lane_spawns.keys()) total_lanes = len(sorted_lane_ids) if total_lanes < 3: raise Exception(f"当前地图仅找到 {total_lanes} 条直线车道,不足3条无法测试") best_consecutive = None max_spawns = 0 for i in range(total_lanes - 2): consecutive_ids = sorted_lane_ids[i:i+3] total_sp = sum(len(lane_spawns[lid]) for lid in consecutive_ids) if total_sp > max_spawns: max_spawns = total_sp best_consecutive = consecutive_ids left_lane_id = best_consecutive[0] middle_lane_id = best_consecutive[1] right_lane_id = best_consecutive[2] print(f"已筛选连续三条直线车道:左车道{left_lane_id} → 中间车道{middle_lane_id} → 右车道{right_lane_id}") return { "left": lane_spawns[left_lane_id], "middle": lane_spawns[middle_lane_id], "right": lane_spawns[right_lane_id] } def get_black_car_bp(world): """获取黑色小汽车蓝图(排除两轮车,确保有颜色属性)""" # 筛选:四轮汽车 + 排除两轮车 + 有颜色属性 valid_cars = [] for bp in world.get_blueprint_library().filter('vehicle.*'): # 排除两轮车 if any(keyword in bp.id for keyword in ['motorcycle', 'bike', 'bicycle', 'scooter']): continue # 确保有颜色属性 if bp.has_attribute('color'): valid_cars.append(bp) if not valid_cars: raise Exception("错误:未找到符合条件的小汽车(需支持颜色设置且非两轮车)") # 优先选紧凑型/小型车 compact_cars = [bp for bp in valid_cars if bp.id.startswith('vehicle.compact') or bp.id.startswith('vehicle.micro')] bp = random.choice(compact_cars) if compact_cars else random.choice(valid_cars) bp.set_attribute('color', '0,0,0') # 强制黑色 return bp def get_red_truck_bp(world): """获取红色带挂货车蓝图(确保有颜色属性)""" # 筛选:货车/挂车 + 有颜色属性 valid_trucks = [] for bp in world.get_blueprint_library().filter('vehicle.*'): # 匹配货车/挂车模型(包含truck、semi关键词) if 'truck' in bp.id or 'semi' in bp.id: if bp.has_attribute('color'): valid_trucks.append(bp) if not valid_trucks: raise Exception("错误:未找到符合条件的货车(需支持颜色设置)") # 优先选带挂的货车(semi类) semi_trucks = [bp for bp in valid_trucks if 'semi' in bp.id] bp = random.choice(semi_trucks) if semi_trucks else random.choice(valid_trucks) bp.set_attribute('color', EGO_VEHICLE_COLOR) # 强制红色 return bp def main(): if not start_carla_server(): return try: client = carla.Client(HOST, PORT) client.set_timeout(15.0) world = client.load_world(MAP_NAME) print(f"地图 {MAP_NAME} 加载成功") # 调整为正常天气 weather = carla.WeatherParameters( cloudiness=40.0, precipitation=0.0, sun_altitude_angle=45.0, fog_density=0.03 ) world.set_weather(weather) print("已设置为正常天气(柔和阴天)") tm = client.get_trafficmanager(8000) tm.set_global_distance_to_leading_vehicle(2.8) tm.set_hybrid_physics_mode(True) tm.set_hybrid_physics_radius(500.0) print("正在筛选连续三条直线车道...") lane_spawns = get_three_consecutive_lanes(world) for lane, spawns in lane_spawns.items(): print(f"{lane}车道可用生成点:{len(spawns)} 个") # 1. 中间车道:生成3辆静止车(黑色小汽车) print(f"\n生成中间车道静止车辆({STATIC_CARS_NUM} 辆,黑色小汽车)...") middle_spawns = lane_spawns["middle"] static_cars = [] for i in range(STATIC_CARS_NUM): base_spawn = middle_spawns[0] static_location = carla.Location( x=base_spawn.location.x + 90 + i*15, y=base_spawn.location.y, z=base_spawn.location.z ) static_transform = carla.Transform(static_location, base_spawn.rotation) bp = get_black_car_bp(world) try: car = world.spawn_actor(bp, static_transform) car.set_autopilot(False) static_cars.append(car) print(f"生成静止车 {i+1}: {bp.id}(位置:x={static_location.x:.1f})") except Exception as e: print(f"生成静止车 {i+1} 失败: {e}") # 2. 中间车道:生成自车(红色带挂货车)+ 2辆额外行驶车(黑色小汽车) print("\n生成中间车道车辆...") # 自车(红色带挂货车) base_spawn = middle_spawns[0] ego_spawn_location = carla.Location( x=base_spawn.location.x + 20, y=base_spawn.location.y, z=base_spawn.location.z ) ego_transform = carla.Transform(ego_spawn_location, base_spawn.rotation) ego_bp = get_red_truck_bp(world) ego_vehicle = world.spawn_actor(ego_bp, ego_transform) ego_vehicle.set_autopilot(True, tm.get_port()) ego_speed_factor = EGO_SPEED_KMH / 120.0 tm.vehicle_percentage_speed_difference(ego_vehicle, int((ego_speed_factor - 1.0) * 100)) print(f"生成自车: {ego_bp.id}(红色带挂货车,速度:{EGO_SPEED_KMH} km/h,位置:x={ego_spawn_location.x:.1f})") # 中间车道额外2辆行驶车(黑色小汽车) middle_moving_cars = [] for i in range(MIDDLE_MOVING_CARS): if i == 0: move_location = carla.Location( x=base_spawn.location.x + 50, y=base_spawn.location.y, z=base_spawn.location.z ) speed = random.randint(EGO_SPEED_KMH-5, EGO_SPEED_KMH) else: move_location = carla.Location( x=base_spawn.location.x - 20, y=base_spawn.location.y, z=base_spawn.location.z ) speed = random.randint(EGO_SPEED_KMH-8, EGO_SPEED_KMH-3) move_transform = carla.Transform(move_location, base_spawn.rotation) bp = get_black_car_bp(world) try: car = world.spawn_actor(bp, move_transform) car.set_autopilot(True, tm.get_port()) speed_factor = speed / 120.0 tm.vehicle_percentage_speed_difference(car, int((speed_factor - 1.0) * 100)) middle_moving_cars.append(car) print(f"生成中间车道行驶车 {i+1}: {bp.id}(黑色小汽车,速度:{speed} km/h,位置:x={move_location.x:.1f})") except Exception as e: print(f"生成中间车道行驶车 {i+1} 失败: {e}") # 3. 左侧车道:生成8辆车辆(黑色小汽车) print(f"\n生成左侧车道车辆({LEFT_CARS_NUM} 辆,黑色小汽车)...") left_spawns = lane_spawns["left"] left_cars = [] for i in range(LEFT_CARS_NUM): spawn_point = left_spawns[i % len(left_spawns)] spawn_location = carla.Location( x=spawn_point.location.x + random.randint(-80, 80), y=spawn_point.location.y, z=spawn_point.location.z ) spawn_transform = carla.Transform(spawn_location, spawn_point.rotation) bp = get_black_car_bp(world) try: car = world.spawn_actor(bp, spawn_transform) car.set_autopilot(True, tm.get_port()) random_speed = random.randint(SIDE_CARS_SPEED_MIN, SIDE_CARS_SPEED_MAX) speed_factor = random_speed / 120.0 tm.vehicle_percentage_speed_difference(car, int((speed_factor - 1.0) * 100)) left_cars.append(car) if (i+1) % 4 == 0: print(f"生成左侧车 {i+1}: {bp.id}(速度:{random_speed} km/h,位置:x={spawn_location.x:.1f})") except Exception as e: print(f"生成左侧车 {i+1} 失败: {e}") # 4. 右侧车道:生成8辆车辆(黑色小汽车) print(f"\n生成右侧车道车辆({RIGHT_CARS_NUM} 辆,黑色小汽车)...") right_spawns = lane_spawns["right"] right_cars = [] for i in range(RIGHT_CARS_NUM): spawn_point = right_spawns[i % len(right_spawns)] spawn_location = carla.Location( x=spawn_point.location.x + random.randint(-80, 80), y=spawn_point.location.y, z=spawn_point.location.z ) spawn_transform = carla.Transform(spawn_location, spawn_point.rotation) bp = get_black_car_bp(world) try: car = world.spawn_actor(bp, spawn_transform) car.set_autopilot(True, tm.get_port()) random_speed = random.randint(SIDE_CARS_SPEED_MIN, SIDE_CARS_SPEED_MAX) speed_factor = random_speed / 120.0 tm.vehicle_percentage_speed_difference(car, int((speed_factor - 1.0) * 100)) right_cars.append(car) if (i+1) % 4 == 0: print(f"生成右侧车 {i+1}: {bp.id}(速度:{random_speed} km/h,位置:x={spawn_location.x:.1f})") except Exception as e: print(f"生成右侧车 {i+1} 失败: {e}") # 5. 固定高空俯览视角 print("\n设置固定视角...") spectator = world.get_spectator() spectator.set_transform(carla.Transform(FIXED_VIEW_LOCATION, FIXED_VIEW_ROTATION)) print("视角已固定(高空俯览,覆盖三条测试车道)") # 场景就绪提示 total_cars = 1 + STATIC_CARS_NUM + MIDDLE_MOVING_CARS + LEFT_CARS_NUM + RIGHT_CARS_NUM print("\n" + "-"*50) print("变道测试场景已就绪(Carla 0.9.16)") print(f"总车辆数:{total_cars} 辆") print(f"自车:红色带挂货车({ego_bp.id},中间车道,{EGO_SPEED_KMH} km/h)") print("其他车辆:全部为黑色小汽车(无两轮车)") print("天气:正常柔和阴天") print("观察重点:红色货车接近静止车时是否主动变道避让") print("-"*50) print("按 Ctrl+C 终止脚本并清理车辆") while True: time.sleep(1) except KeyboardInterrupt: print("\n正在清理所有车辆...") actors = world.get_actors() vehicles = actors.filter('vehicle.*') vehicle_count = len(vehicles) for v in vehicles: v.destroy() print(f"已销毁所有 {vehicle_count} 辆车辆") except Exception as e: print(f"\n场景运行出错: {e}") actors = world.get_actors() vehicles = actors.filter('vehicle.*') for v in vehicles: v.destroy() print("已自动清理所有车辆") if name == 'main': main() |
图示:

3 、设置模拟目标点场景搭建
|-----------------------------------------------------------------------|
| 这里采用: 对每个车辆(包括自车)设置初始和目标位置(包含多个目标点),设置初始和目标点的速度大小。 (后续在此脚本上进行更改和变化即可) |

|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Python import carla import time import math # --- 配置参数 --- HOST = '127.0.0.1' PORT = 2000 # --- 核心配置 --- # 每辆车都包含:初始位置、初始速度、以及一系列目标点(位置+速度) VEHICLE_CONFIGS = { 'ego': { # 自车 (消防车车型) 'model': 'vehicle.carlamotors.firetruck', 'initial_transform': carla.Transform( carla.Location(x=22, y=143, z=0.300000), carla.Rotation(pitch=0, yaw=0, roll=0) ), 'initial_speed': 0.0, # 初始速度为0 'target_points': [ {'location': carla.Location(x=222, y=143, z=0.3), 'speed': 80.0}, {'location': carla.Location(x=322, y=143, z=0.3), 'speed': 60.0}, {'location': carla.Location(x=400, y=146.5, z=0.3), 'speed': 60.0}, {'location': carla.Location(x=622, y=143, z=0.3), 'speed': 0.0} ] }, # 右侧车辆 'r_0': { # 黑色小汽车 'model': 'vehicle.tesla.model3', 'initial_transform': carla.Transform( carla.Location(x=41, y=146.5, z=0.300000), carla.Rotation(pitch=0, yaw=0, roll=0) ), 'initial_speed': 0.0, 'target_points': [ {'location': carla.Location(x=241, y=146.5, z=0.3), 'speed': 60.0}, {'location': carla.Location(x=441, y=146.5, z=0.3), 'speed': 0.0}, ] }, 'r_1': { # 黑色小汽车 'model': 'vehicle.tesla.model3', 'initial_transform': carla.Transform( carla.Location(x=34, y=146.5, z=0.300000), carla.Rotation(pitch=0, yaw=0, roll=0) ), 'initial_speed': 0.0, 'target_points': [ {'location': carla.Location(x=234, y=146.5, z=0.3), 'speed': 60.0}, {'location': carla.Location(x=434, y=146.5, z=0.3), 'speed': 0.0}, ] }, 'r_2': { # 黑色小汽车 'model': 'vehicle.tesla.model3', 'initial_transform': carla.Transform( carla.Location(x=27, y=146.5, z=0.300000), carla.Rotation(pitch=0, yaw=0, roll=0) ), 'initial_speed': 0.0, 'target_points': [ {'location': carla.Location(x=227, y=142.587830, z=0.3), 'speed': 0.0}, {'location': carla.Location(x=327, y=142.587830, z=0.3), 'speed': 00.0}, ] }, 'r_3': { # 黑色小汽车 'model': 'vehicle.tesla.model3', 'initial_transform': carla.Transform( carla.Location(x=20, y=146.5, z=0.300000), carla.Rotation(pitch=0, yaw=0, roll=0) ), 'initial_speed': 0.0, 'target_points': [ {'location': carla.Location(x=220, y=142.587830, z=0.3), 'speed': 0.0}, {'location': carla.Location(x=320, y=142.587830, z=0.3), 'speed': 00.0}, ] }, # 左侧车辆 'l_0': { # 黑色小汽车 'model': 'vehicle.tesla.model3', 'initial_transform': carla.Transform( carla.Location(x=41, y=139.5, z=0.300000), carla.Rotation(pitch=0, yaw=0, roll=0) ), 'initial_speed': 0.0, 'target_points': [ {'location': carla.Location(x=241, y=139.5, z=0.3), 'speed': 60.0}, {'location': carla.Location(x=441, y=139.5, z=0.3), 'speed': 0.0}, ] }, 'l_1': { # 黑色小汽车 'model': 'vehicle.tesla.model3', 'initial_transform': carla.Transform( carla.Location(x=34, y=139.5, z=0.300000), carla.Rotation(pitch=0, yaw=0, roll=0) ), 'initial_speed': 0.0, 'target_points': [ {'location': carla.Location(x=234, y=139.5, z=0.3), 'speed': 60.0}, {'location': carla.Location(x=434, y=139.5, z=0.3), 'speed': 00.0}, ] }, 'l_2': { # 黑色小汽车 'model': 'vehicle.tesla.model3', 'initial_transform': carla.Transform( carla.Location(x=27, y=139.5, z=0.300000), carla.Rotation(pitch=0, yaw=0, roll=0) ), 'initial_speed': 0.0, 'target_points': [ {'location': carla.Location(x=227, y=142.587830, z=0.3), 'speed': 0.0}, {'location': carla.Location(x=327, y=142.587830, z=0.3), 'speed': 00.0}, ] }, 'l_3': { # 黑色小汽车 'model': 'vehicle.tesla.model3', 'initial_transform': carla.Transform( carla.Location(x=20, y=139.5, z=0.300000), carla.Rotation(pitch=0, yaw=0, roll=0) ), 'initial_speed': 0.0, 'target_points': [ {'location': carla.Location(x=220, y=142.587830, z=0.3), 'speed': 0.0}, {'location': carla.Location(x=320, y=142.587830, z=0.3), 'speed': 00.0}, ] } # 可以继续添加更多车辆... } # --- 辅助函数 --- def clear_existing_actors(world): """清除世界中所有现有车辆""" print("正在清除现有车辆...") for actor in world.get_actors().filter('vehicle.*'): actor.destroy() print("现有车辆已清除。") def generate_path(world, start_location, end_location, resolution=2.0): """生成从起点到终点的路径点列表""" path = [] start_waypoint = world.get_map().get_waypoint(start_location) end_waypoint = world.get_map().get_waypoint(end_location) # 如果起点和终点在同一条车道上,直接生成直线路径 if start_waypoint.lane_id == end_waypoint.lane_id: current_waypoint = start_waypoint while current_waypoint.transform.location.distance(end_location) > resolution: path.append(current_waypoint.transform.location) next_waypoints = current_waypoint.next(resolution) if not next_waypoints: break current_waypoint = next_waypoints[0] path.append(end_location) else: # 这里简化处理,实际复杂场景可能需要更高级的路径规划 path.append(start_location) path.append(end_location) return path def control_vehicle(vehicle, target_location, target_speed): """ 控制车辆朝向目标位置行驶,并尝试达到目标速度 返回: 车辆是否已到达目标位置 """ vehicle_location = vehicle.get_transform().location distance = vehicle_location.distance(target_location) # 如果距离目标点很近,认为已经到达 if distance < 3.0: return True # 计算朝向目标点所需的转向角 vehicle_rotation = vehicle.get_transform().rotation forward_vector = carla.Vector3D( math.cos(math.radians(vehicle_rotation.yaw)), math.sin(math.radians(vehicle_rotation.yaw)), 0 ) target_vector = carla.Vector3D( target_location.x - vehicle_location.x, target_location.y - vehicle_location.y, 0 ) target_vector = target_vector.make_unit_vector() # 计算两个向量的夹角 dot_product = forward_vector.x * target_vector.x + forward_vector.y * target_vector.y cross_product = forward_vector.x * target_vector.y - forward_vector.y * target_vector.x angle = math.degrees(math.atan2(cross_product, dot_product)) # 速度控制 current_speed = vehicle.get_velocity().length() speed_error = (target_speed / 3.6) - current_speed throttle = 0.0 brake = 0.0 steer = angle / 45.0 # 将角度归一化到[-1, 1] if speed_error > 0: throttle = min(1.0, speed_error / 5.0) else: brake = min(1.0, -speed_error / 2.0) # 应用控制 vehicle.apply_control(carla.VehicleControl(throttle=throttle, steer=steer, brake=brake)) return False # --- 主控制循环 --- def main(): try: client = carla.Client(HOST, PORT) client.set_timeout(10.0) world = client.get_world() world.set_weather(carla.WeatherParameters.ClearNoon) clear_existing_actors(world) # 生成车辆并存储其状态 vehicles = {} blueprint_library = world.get_blueprint_library() for vehicle_id, config in VEHICLE_CONFIGS.items(): blueprint = blueprint_library.find(config['model']) if not blueprint: print(f"警告: 未找到车型 {config['model']},跳过。") continue if config['model'] != 'vehicle.carlamotors.firetruck': blueprint.set_attribute('color', '0,0,0') vehicle = world.spawn_actor(blueprint, config['initial_transform']) if not vehicle: print(f"警告: 生成车辆 {vehicle_id} 失败。") continue vehicle.set_simulate_physics(True) # 初始速度为0 vehicle.apply_control(carla.VehicleControl(throttle=0.0, brake=1.0)) time.sleep(0.1) vehicle.apply_control(carla.VehicleControl(throttle=0.0, brake=0.0)) vehicles[vehicle_id] = { 'actor': vehicle, 'target_points': config['target_points'], 'current_target_index': 0, 'current_path': [] } print(f"成功生成车辆 ID: {vehicle_id}") print("\n开始车辆控制...") while True: for vehicle_id, state in vehicles.items(): vehicle = state['actor'] target_points = state['target_points'] current_index = state['current_target_index'] if current_index >= len(target_points): continue # 所有目标点都已完成 current_target = target_points[current_index] # 如果当前没有路径,生成一条 if not state['current_path']: print(f"车辆 {vehicle_id}:生成到目标点 {current_index} 的路径...") state['current_path'] = generate_path( world, vehicle.get_transform().location, current_target['location'] ) if not state['current_path']: print(f"警告: 车辆 {vehicle_id} 无法生成到目标点 {current_index} 的路径。") state['current_target_index'] += 1 continue # 获取下一个路径点 next_waypoint_location = state['current_path'][0] # 控制车辆向路径点移动 reached_waypoint = control_vehicle( vehicle, next_waypoint_location, current_target['speed'] ) # 如果到达了路径点,将其从列表中移除 if reached_waypoint: state['current_path'].pop(0) # 如果路径为空,说明到达了目标点 if not state['current_path']: print(f"车辆 {vehicle_id}:已到达目标点 {current_index}") state['current_target_index'] += 1 if state['current_target_index'] >= len(target_points): print(f"车辆 {vehicle_id}:所有目标点已完成!") time.sleep(0.05) except KeyboardInterrupt: print("\n程序被手动停止。") finally: print("\n正在清理资源...") for vehicle_id, state in vehicles.items(): try: state['actor'].destroy() print(f"已销毁车辆 ID: {vehicle_id}") except Exception as e: print(f"销毁车辆 ID: {vehicle_id} 时出错: {e}") print("所有资源已清理。") if name == 'main': main() |
五、(预先拓展)结合 ROS 环境,桥接
1. 安装 ROS Noetic (已经存在,验证)

2. 配置 CARLA-ROS 桥接
2.1 创建并进入 Catkin 工作空间
|---------------------------------------------------------------------|
| Plain Text # 创建工作空间目录 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src |
2.2 下载兼容 CARLA 0.9.16 的 ROS 桥接包
|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Plain Text # 进入 catkin_ws/src 目录 cd ~/catkin_ws/src # 删除之前的无效目录和压缩包 rm -rf carla_ros_bridge carla_ros_bridge.zip # 下载 CARLA 官方 ros-bridge 的 master 分支 wget https://github.com/carla-simulator/ros-bridge/archive/refs/heads/master.zip -O carla_ros_bridge.zip #解压压缩包 unzip carla_ros_bridge.zip # 重命名为 carla_ros_bridge(ROS 功能包名规范) mv ros-bridge-master carla_ros_bridge # 进入解压后的 carla_ros_bridge 根目录 cd ~/catkin_ws/src/carla_ros_bridge # 查找所有子文件夹中的 CMakeLists.txt(会显示具体路径) find . -name "CMakeLists.txt" |
2.3 安装桥接包依赖
|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Plain Text # 回到工作空间根目录 cd ~/catkin_ws # 自动安装所有缺失的依赖 rosdep install --from-paths src --ignore-src -r -y # 有报错,按照报错信息进行执行 ERROR: your rosdep installation has not been initialized yet. Please run: sudo rosdep init rosdep update |
2.4 编译工作空间
|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Plain Text # 设置 CARLA 路径(防止环境变量失效) export CARLA_ROOT=/home/trunk/carla_0.9.16 ls CARLA_ROOT/PythonAPI/carla/dist # python3.10版本 export PYTHONPATH=PYTHONPATH:CARLA_ROOT/PythonAPI/carla/dist/carla-0.9.16-cp310-cp310-manylinux_2_31_x86_64.whl:CARLA_ROOT/PythonAPI/carla # 编译源码(耐心等待,约 5-10 分钟,无红报错即可) catkin_make # 若编译时提示 "缺少 xxx 包",执行 sudo apt install ros-noetic-xxx(替换 xxx 为缺失包名),再重新编译。 |
2.5 同时添加 CARLA 环境变量(避免每次编译 / 运行脚本都要手动设置):
|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Markdown # 把 CARLA 路径和 PYTHONPATH 也写入 .bashrc(替换为你的 Python 版本,如 cp311) echo 'export CARLA_ROOT=/home/trunk/carla_0.9.16' >> ~/.bashrc echo 'export PYTHONPATH=PYTHONPATH:CARLA_ROOT/PythonAPI/carla/dist/carla-0.9.16-cp310-cp310-manylinux_2_31_x86_64.whl:$CARLA_ROOT/PythonAPI' >> ~/.bashrc # 再次生效 source ~/.bashrc |
3. 开始连接并进行测试(有问题: ros Noetic 是依赖 python3.8 ,在原 Ubuntu 系统中已经存在)
4. 创建 Python3.10 的虚拟环境
|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Markdown # 1. 创建虚拟环境(名字叫 carla-ros-venv,存放在用户目录下) python3.10 -m venv ~/carla-ros-venv # 2. 激活虚拟环境(每次用之前都要执行这行) source ~/carla-ros-venv/bin/activate # 3. 安装所有必需依赖(一次性装完,后续不用再补) pip install --upgrade pip pip install rospkg catkin_pkg PyYAML empy lark-parser pygame # 4. 加载 ROS 和工作空间环境(激活虚拟环境后执行) source /opt/ros/noetic/setup.bash source ~/catkin_ws/devel/setup.bash # 5. 验证(都输出成功即可) python3 -c "import carla; print('CARLA 导入成功')" python3 -c "import rospy; print('ROS 导入成功')" |
5. 桥接步骤 (有些修改放在****步骤 7**)**
|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Python # 1**:启动** CARLA 服务器(新终端 1 ,无需激活虚拟环境) cd /home/trunk/carla_0.9.16 ./CarlaUE4.sh 【可以切换地体------ Town06" 接近高速用图"】 # 2 :编译并 source 工作空间: source ~/carla_ros_venv-py310/bin/activate 【确保在虚拟环境中进行编译】 cd ~/catkin_ws catkin_make source devel/setup.bash # 3 :启动: roscore source ~/carla_ros_venv-py310/bin/activate source /opt/ros/noetic/setup.bash roscore # 4:激活环境并启动桥接 source ~/carla_ros_venv-py310/bin/activate source /opt/ros/noetic/setup.bash source ~/catkin_ws/devel/setup.bash roslaunch carla_ros_bridge carla_ros_bridge.launch host:=localhost port:=2000 roslaunch carla_offline_adapter offline_simulation.launch【启动launch文件】 |
6. ROS****和 Carla 桥接成功!!!!!!!!

7. 备注信息(消除版本影响和取消地图选择【即默认地图选择】、修复关闭 bug )


|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Python **#**在" ~/catkin_ws/src/carla_ros_bridge/carla_ros_bridge/src/carla_ros_bridge/bridge.py" 找到" def destroy(self):" # self.shutdown.set() # 注释掉或删除这行 self.shutdown_event.set() |

8 、重新安装 carla_ws 工作环境(即桥接环境)
|------------------------------------------------------------------------------------------------------------------------------------------------|
| catkin_make 和 catkin build 是两种不同的 ROS 编译工具,设计理念和规则差异很大 ------ 之前用 catkin_make 不行,换 catkin build 就成了,本质是工具的 "规则适配性" 问题。 |
|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| JavaScript mkdir -p ~/carla_ws/src cd ~/carla_ws/src #解压官方桥接包(替换为你的压缩包路径,确保是官方完整包) unzip ~/下载/ros-bridge-master.zip #重命名为 carla_ros_bridge mv ros-bridge-master carla_ros_bridge #验证子包完整(必须有这些目录) ls carla_ros_bridge | grep -E "carla_ackermann_msgs|carla_ros_bridge|carla_msgs" #预期输出:carla_ackermann_msgs carla_ros_bridge carla_msgs(证明包完整) pip3 install numpy==1.26.4 pip3 install opencv-python==4.8.0.76 cd ~/carla_ws #激活 Python3.10 虚拟环境 source ~/carla_ros_venv-py310/bin/activate #编译(自动扫描 src/carla_ros_bridge 下所有子包,指定 Python3.10 和 Carla 路径) catkin build \-DPYTHON_EXECUTABLE=/home/trunk/carla_ros_venv-py310/bin/python3 \-DCARLA_INCLUDE_DIR=/home/trunk/carla_0.9.16/PythonAPI/carla/include \-DCARLA_LIBRARY_DIR=/home/trunk/carla_0.9.16/PythonAPI/carla \ --cmake-args -DCMAKE_BUILD_TYPE=Release source devel/setup.bash roslaunch carla_ros_bridge carla_ros_bridge_with_example_ego_vehicle.launch town:="Town06" 再次修改步骤七中的信息,因为要消除强制版本对应等限制! |
Carla 0.9.16 + ROS Noetic + Python3.10 + 0.9.13****桥接包 =====>>> 成功链接
六、桥接测试,利用 ROS 生态和 Carla 闭环联动
1. 利用 ros 查看和播放 bag 包
|----------------------------------------|
| Python # bag包使用的是"ID25059" rosbag info |

2. ros_bridge 和 carla 链接操作步骤
|--------------------------------------------------------------------------------------------------------|
| 流程: 启动 Carla → 手动生成 Ego 车 → 启动 ROS Bridge 和转换节点 → 回放 bag 包 |

|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Python # 窗口化启动carla ./CarlaUE4.sh -windowed -ResX=1280 -ResY=720 【这里是直接采用官网的 0.9.13zip 压缩包解压使用的,采用的编译有不同】 # 运行ros_carla_bridge文件(launch) cd ~/ros-bridge-master # 清空旧编译缓存 catkin clean -y # 重新编译 carla_ros_bridge 包 catkin build carla_ros_bridge --cmake-args -DPYTHON_EXECUTABLE=$(which python3) # 强制加载编译后的环境 source devel/setup.bash --extend # 验证 ROS 能否找到该包 rospack find carla_ros_bridge # 启动 launch 文件 roslaunch carla_ros_bridge carla_ros_bridge.launch carla_version:=0.9.16 |
|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Python # 正常启动ros-carla连接 # 先启动carla(窗口化) ./CarlaUE4.sh -windowed -ResX=1280 -ResY=720 # 再启动roslaunch文件(记得使用python虚拟环境) source devel/setup.sh roslaunch carla_ros_bridge carla_ros_bridge.launch |
3 、创建 pncc_msgs 包,驱动 ego 车辆
|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| # 目录层次 ros-bridge-master/ ├── src/ │ ├── carla_ros_bridge/ │ └── pncc_msgs/ # 新增自定义包 │ ├── CMakeLists.txt │ ├── package.xml │ └── msg/ │ ├── DecisionCmd.msg │ ├── PlanningCmd.msg │ ├── TnpInfo.msg │ ├── VehicleCmd.msg │ └── VehicleInfo2.msg ├── build/ ├── devel/ └── ... |
3.1 创建自定义消息包
|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Python # 进入 ros-bridge-master/src 目录 cd ~/ros-bridge-master/src # 创建 pncc_msgs 包(依赖 std_msgs、geometry_msgs 即可,无需依赖 carla_ros_bridge) catkin_create_pkg pncc_msgs std_msgs geometry_msgs # 创建 msg 目录(存放自定义消息) mkdir -p pncc_msgs/msg |
3.2 测试 pncc_msgs 和 ros 正常对接
|------------------------------------------------------------------------------------------|
| 单纯的 rostopic pub/echo 测试确实是基础验证步骤,它的核心价值是【排除 pncc_msgs 本身的问题】,为后续【bag 转译 + Carla 车辆复现】铺路 |