首页/文章/ 详情

Carla传感器模型深度解析——鱼眼相机篇

8月前浏览940

 
 
作者|峻川  
编辑|峻川  
出品|车路漫漫  

写在前面

本文的鱼眼相机代码源自github上Carla仓库的Fisheye sensor #3755(https://github.com/carla-simulator/carla/pull/3755),正文中作为示例的是本文作者基于此改编的适配最新版Carla"Unreal Engine 5.5 version of CARLA"的Fisheye sensor代码。文末会附上改编后的代码。

鱼眼相机效果

鱼眼相机模型代码解析

在Carla的文档中,有如何建立新传感器模型的教程:how-to-add-a-new-sensor,建议首先阅读链接中的文档以熟悉这一过程。

和文档中一样,我们首先从新建立的Sensor Actor开始。AFisheyeSensor::GetSensorDefinition()AFisheyeSensor::GetImageWidth()AFisheyeSensor::GetImageHeight()AFisheyeSensor::GetFOV()获取一些如图像分辨率、相机内参等参数,AFisheyeSensor::Set(const FActorDescription &Description)会将这些参数赋值给类内部的成员。

在构造函数中,定义了一个Fisheye对象:

Fisheye = CreateDefaultSubobject<USceneCaptureComponentCube>(
      FName(*FString::Printf(TEXT("SceneCaptureComponentCube_%d"), SCENE_CAPTURE_COUNTER_CUBE)));

1. USceneCaptureComponentCube 的作用

  • 动态捕获立方体贴图
    USceneCaptureComponentCube 是用于从场景的某个位置捕获 立方体贴图(Cubemap) 的组件。它会实时渲染场景的六个面(前、后、左、右、上、下),生成一个立方体贴图。这种贴图常用于动态环境反射(如金属、水面)、天空盒效果,或需要全方向视角的场景捕捉(如VR,和本文所述的鱼眼相机)。

  • 应用场景
    例如,在角色周围动态生成环境反射时,可以将 USceneCaptureComponentCube 附加到角色身上,实时捕捉周围环境,并将结果传递给材质系统,实现动态反射效果。

2. SCENE_CAPTURE_COUNTER_CUBE 的作用

  • 唯一命名标识
    SCENE_CAPTURE_COUNTER_CUBE 是一个无符号整型计数器(0u 表示初始值为0),用于为每个 USceneCaptureComponentCube 实例生成唯一名称。通过 FString::Printf 将其嵌入名称字符串(如 "SceneCaptureComponentCube_0"),避免多个组件因同名导致冲突。

  • 计数器的递增
    通常,在每次创建组件后,计数器会递增(例如 SCENE_CAPTURE_COUNTER_CUBE++),确保后续实例的名称后缀依次为 _1_2 等。这是Unreal中管理动态生成组件命名的常见做法。


在Unreal Engine中,**USceneCaptureComponentCube::CaptureScene()** 是一个关键方法,用于 手动触发 立方体贴图(Cubemap)的场景捕获操作。以下是关于该方法的详细说明:

  • 立即捕获场景
    CaptureScene() 会立即从 USceneCaptureComponentCube 的当前位置和方向,渲染场景的六个面(前、后、左、右、上、下),生成一个完整的立方体贴图,并将结果写入关联的渲染目标(TextureRenderTargetCube)。

下面进入FisheyeSensor在仿真开始时会运行的方法:BeginPlay()

void AFisheyeSensor::BeginPlay()
{
  // 省略
}

这是FisheyeSensor中的第一个重要方法。以下是逐行解释:

1. 初始化渲染目标

CaptureRenderTarget->Init(GetImageWidth(), PF_B8G8R8A8);
  • 作用:初始化一个渲染目标(UTextureRenderTarget2D),设置其宽度为GetImageWidth()返回的值,像素格式为PF_B8G8R8A8(32位BGRA格式,适合存储颜色数据)。
  • 细节:渲染目标用于将场景内容捕捉到纹理,后续可通过此纹理获取图像数据。

2. 配置鱼眼场景捕捉组件

Fisheye->Deactivate();
Fisheye->TextureTarget = CaptureRenderTarget;
Fisheye->CaptureScene();
  • 作用:停用鱼眼场景捕捉组件(如USceneCaptureComponent2D),避免未配置时自动渲染。然后将渲染目标绑定到组件,并立即触发一次场景捕捉。
  • 注意CaptureScene()可能在组件未激活时仍可手动调用,确保首次捕捉完成。

3. 设置捕捉数据源

Fisheye->CaptureSource = ESceneCaptureSource::SCS_FinalColorLDR; 
  • 作用:指定捕捉的数据源为“最终颜色(低动态范围,LDR)”,即经过后期处理(如色调映射)后的画面,适合显示或存储为标准格式图像。

4. 更新并激活组件

Fisheye->UpdateContent();
Fisheye->Activate();
  • 作用UpdateContent()确保参数更改生效,Activate()启用组件,使其后续可以自动更新(如每帧捕捉)。

5. 调整渲染超时设置

UKis metSystemLibrary::ExecuteConsoleCommand(
    GetWorld(),
    FString("g.TimeoutForBlockOnRenderFence 300000"));
  • 作用:通过控制台命令将渲染围栏阻塞超时设置为300秒(300000毫秒),防止高负载渲染任务(如高分辨率捕捉)因超时失败。
  • 注意:此设置全局生效,需谨慎使用,避免影响其他场景。

6. 通知天气更新

Weather->NotifyWeather(this);
  • 作用:触发天气系统更新,确保场景中的天气效果(如雨、雾)被应用到当前捕捉的画面中。
  • 细节GetEpisode()可能指向当前游戏情景,与项目逻辑相关。

7. 调用父类逻辑

Super::BeginPlay();
  • 作用:执行父类(如AActor)的BeginPlay(),完成继承链的初始化。

那么,在上面的代码中,我们为什么让Fisheye先调用了Deactivate()停用,再调用CaptureScene(),再调用Activate()呢?其行为目的如下:

1. 核心问题:为什么停用后还能捕捉到场景?

即使调用了Deactivate()手动调用CaptureScene()仍然有效
Deactivate()的作用是 关闭组件的自动更新逻辑(如Tick或依赖引擎自动触发的渲染),但不会阻止显式调用CaptureScene()这种主动请求的捕获操作。
关键区别

  • 自动行为(如bCaptureEveryFrame=true):依赖组件的激活状态(IsActive()),停用后自动捕获停止。
  • 手动行为(如CaptureScene()):直接执行,与激活状态无关。

因此,代码中Deactivate()的目的是 避免自动更新干扰,而非禁用所有功能。

2. 代码流程的详细解释

Fisheye->Deactivate();                 // 步骤1:停用自动逻辑
Fisheye->TextureTarget = CaptureRenderTarget; // 步骤2:绑定渲染目标
Fisheye->CaptureScene();               // 步骤3:手动触发捕获
Fisheye->CaptureSource = ESceneCaptureSource::SCS_FinalColorLDR; // 步骤4:设置捕获源
Fisheye->UpdateContent();              // 步骤5:强制更新配置
Fisheye->Activate();                   // 步骤6:重新激活组件

步骤1:Deactivate()的作用

  • 关闭自动更新:防止组件因bCaptureEveryFrame=true或其他引擎机制自动触发捕获。
  • 避免中间状态干扰:确保在配置参数(如TextureTargetCaptureSource)的过程中,组件不会意外执行未完全初始化的捕获操作。

步骤3:CaptureScene()的调用

  • 立即执行捕获:无论组件是否激活,手动调用会直接渲染场景到TextureTarget
  • 确保参数已设置:在调用前已绑定TextureTarget,因此捕获结果会正确写入目标资源。

步骤5:UpdateContent()的必要性

  • 同步配置到GPU:某些属性(如CaptureSource)的修改可能需要通过UpdateContent()强制更新渲染代理(Proxy),确保后续操作使用最新参数。
  • 避免延迟生效:Unreal的渲染线程可能异步处理参数更新,此方法确保立即生效。

步骤6:Activate()的恢复

  • 重启自动逻辑:如果后续需要组件自动更新(如恢复bCaptureEveryFrame=true),需重新激活。
  • 组件状态管理:保持组件在完成手动操作后处于一致的激活状态。

3. 这样做的目的

(1) 确保手动捕获的稳定性

  • 防止自动捕获干扰:若组件原本是激活状态且bCaptureEveryFrame=true,直接修改参数可能导致捕获过程中途被自动更新打断,产生不完整或冲突的结果。
  • 原子化操作:通过Deactivate()冻结组件的自动行为,确保参数修改(TextureTargetCaptureSource)和手动捕获(CaptureScene())是一个完整且不可中断的流程。

(2) 避免资源竞争

  • 渲染目标安全绑定:在停用状态下绑定TextureTarget,可避免渲染线程正在使用该资源时发生冲突(如前一帧未完成的捕获仍在写入纹理)。

(3) 兼容后续自动更新

  • 恢复初始状态:操作完成后重新Activate(),确保组件后续可以正常参与引擎的更新循环(如需要持续自动捕获)。

4. 典型应用场景

动态切换渲染目标

  • 需要临时更换TextureTarget并立即捕获一次,但不希望自动更新持续写入新目标。
  • 示例:根据玩家位置切换不同环境贴图的捕获目标。

编辑器工具链

  • 在非游戏运行时(如编辑器脚本中),通过手动控制捕获流程生成静态环境贴图,避免自动更新浪费性能。

复杂参数配置

  • 需按顺序设置多个属性(如CaptureSource、后期处理参数),并要求这些参数在捕获时完全生效。

AFisheyeSensor中,每一步鱼眼图像渲染的执行是在AFisheyeSensor::PrePhysTick()方法中实现的,其中最核心的方法就是以下函数:

template <typename TSensor>
void AFisheyeSensor::SendPixelsInRenderThread(TSensor &Sensor, float MaxAngle, float SizeX, float SizeY, float Fx, float Fy, float Cx, float Cy, float D1, float D2, float D3, float D4)
{
  // 省略
}

以下是代码的详细分步解释:

1. 函数功能概述

其核心功能是:
在渲染线程中将立方体贴图(Cubemap)转换为鱼眼图像,并通过Carla传感器数据流发送出去

2. 关键代码解析

步骤1:参数检查与初始化

check(Sensor.CaptureRenderTarget != nullptr);
UTextureRenderTargetCube *RenderTarget = Sensor.CaptureRenderTarget;
  • 目的:确保渲染目标有效,避免空指针崩溃。
  • **UTextureRenderTargetCube**:Unreal中存储立方体贴图的资源,通常由USceneCaptureComponentCube捕获生成。

步骤2:准备数据容器

TArray64<uint8> RawData;        // 存储鱼眼图像原始像素数据
FIntPoint Size;                 // 图像尺寸(输出参数)
EPixelFormat Format;            // 像素格式(输出参数)
  • **TArray64<uint8>**:支持大尺寸(64位)的字节数组,用于容纳高分辨率图像数据。

步骤3:配置鱼眼参数

CubemapHelpersFisheye::FFisheyeParams FisheyeParams;
FisheyeParams.ImageSize = FIntPoint(SizeX, SizeY);              // 鱼眼图像分辨率
FisheyeParams.CameraMatrix = FVector4(Fx, Fy, Cx, Cy);          // 相机内参矩阵
FisheyeParams.DistortionCoeffs = FVector4(D1, D2, D3, D4);      // 畸变系数(k1, k2, k3, k4)
FisheyeParams.MaxAngle = MaxAngle;                              // 鱼眼最大视场角(FOV)
  • 参数作用
    • 内参矩阵:将3D点投影到2D图像平面(fx/fy为焦距,cx/cy为主点坐标)。
    • 畸变系数:模拟镜头畸变效果。
    • MaxAngle:控制鱼眼图像的视野范围(例如180度全景)。

步骤4:立方体贴图展开为鱼眼图像

bool bUnwrapSuccess = CubemapHelpersFisheye::GenerateLongLatUnwrapFisheye(
  RenderTarget, RawData, FisheyeParams, Size, Format
);
  • 功能
    将立方体贴图的六个面展开为 等距柱状投影(Equirectangular Projection),再通过鱼眼模型转换为 鱼眼图像
  • 关键操作
    1. 立方体贴图 → 等距柱状投影:生成360°全景图。
    2. 等距柱状投影 → 鱼眼投影:根据内参和畸变系数裁剪并变形为鱼眼图像。
  • 输出
    • RawData:存储鱼眼图像的像素数据(RGB或灰度)。
    • Size:图像实际尺寸(可能与输入SizeX/Y不同,取决于算法)。
    • Format:像素格式(如PF_R8G8B8A8)。

步骤5:获取Carla传感器数据流

auto Stream = Sensor.GetDataStream(Sensor);
  • **GetDataStream**:Carla框架中获取传感器数据流的方法,用于将数据发送到客户端或日志系统。

步骤6:数据封装与发送

auto Buffer = Stream.PopBufferFromPool(); // 从缓冲池获取内存块
// 将鱼眼数据拷贝到缓冲区
Buffer.copy_from(carla::sensor::SensorRegistry::get<TSensor *>::type::header_offset, RawData.GetData(), RawData.Num());
// 序列化数据
carla::Buffer BufferReady(std::move(carla::sensor::SensorRegistry::Serialize(Sensor, std::move(Buffer))));
carla::SharedBufferView BufView = carla::BufferView::CreateFrom(std::move(BufferReady));

SCOPE_CYCLE_COUNTER(STAT_CarlaSensorStreamSend);
TRACE_CPUPROFILER_EVENT_SCOPE_STR("Stream Send");
// 发送数据
Stream.Send(Sensor, BufView);
  • 关键过程
    1. 缓冲池复用PopBufferFromPool 避免频繁内存分配,提升性能。
    2. 数据拷贝:将RawData写入缓冲区,跳过可能的头部预留空间(header_offset)。
    3. 序列化:将数据按Carla协议打包(可能包含时间戳、传感器ID等元数据)。
    4. 网络发送:通过Stream.Send将数据发送到Carla客户端或日志。

3. 代码设计要点

线程安全性

  • 渲染线程执行
    函数名 SendPixelsInRenderThread 指示其在渲染线程调用,确保对渲染资源(如UTextureRenderTargetCube)的安全访问。

性能优化

  • 缓冲池机制PopBufferFromPool 减少内存分配开销。
  • 数据零拷贝RawData.GetData() 直接访问内存,避免额外复 制。
  • 异步发送Stream.Send 可能非阻塞,避免阻塞渲染线程。

扩展性

  • 模板化设计template <typename TSensor> 支持多种传感器类型复用相同逻辑。
  • 参数化配置:相机参数(内参、畸变)通过函数参数传入,适配不同镜头模型。

AFisheyeSensor::SendPixelsInRenderThread()这个函数中,最关键的是对于CubemapHelpersFisheye::GenerateLongLatUnwrapFisheye方法的调用。CubemapHelpersFisheye::GenerateLongLatUnwrapFisheye来自UnrealEngine5_carla的Engine\Source\Runtime\Engine\Private\CubemapUnwrapUtils.cpp,是根据原有的CubemapHelpers编写的针对鱼眼相机仿真的新方法。

我们首先来看核心函数GenerateLongLatUnwrapFisheye的解析:

1. 函数功能概述

GenerateLongLatUnwrapFisheye 是Unreal引擎中用于将 立方体贴图(Cubemap)转换为鱼眼图像 的核心函数。其通过 GPU渲染管线 实现以下功能:

  1. 立方体贴图展开:将立方体贴图的六个面展开为 等距柱状投影(Equirectangular Projection)
  2. 鱼眼畸变模拟:根据相机参数(内参、畸变系数、最大视场角)对展开的全景图进行变形,生成鱼眼图像。
  3. 像素数据提取:将最终图像数据从GPU读取到CPU内存,供后续处理或传输。

2. 关键代码解析

1. 参数初始化与渲染配置

// 创建自定义的渲染参数(鱼眼变形逻辑)
TRefCountPtr<FBatchedElementParameters> BatchedElementParameters;
BatchedElementParameters = new FMipLevelBatchedElementParametersFisheye(
            (float)0,
            FisheyeParams.DistortionCoeffs,
            FisheyeParams.CameraMatrix,
            FisheyeParams.ImageSize,
            FisheyeParams.MaxAngle,
            true);

// 选择目标像素格式(LDR或HDR)
const EPixelFormat TargetPixelFormat = CalculateImageBytes(110, SourcePixelFormat) <= 4 ? PF_B8G8R8A8 : PF_FloatRGBA;
  • **FMipLevelBatchedElementParametersFisheye**:
    自定义的渲染参数类,负责在渲染时注入 鱼眼变形着色器逻辑,将等距柱状投影转换为鱼眼图像。其参数包括:
    • DistortionCoeffs:镜头畸变系数(k1, k2, k3, k4)。
    • CameraMatrix:相机内参(fx, fy, cx, cy)。
    • MaxAngle:最大视场角(控制鱼眼范围)。
  • 像素格式选择
    根据输入纹理的位宽选择目标格式(LDR用PF_B8G8R8A8,HDR用PF_FloatRGBA)。

2. 渲染目标创建与初始化

// 创建2D渲染目标(用于存储鱼眼图像)
UTextureRenderTarget2D* RenderTargetLongLat = NewObject<UTextureRenderTarget2D>();
RenderTargetLongLat->AddToRoot(); // 防止被GC回收
RenderTargetLongLat->ClearColor = FLinearColor(0.0f0.0f0.0f0.0f);
RenderTargetLongLat->InitCustomFormat(FisheyeParams.ImageSize.X, FisheyeParams.ImageSize.Y, TargetPixelFormat, false);
RenderTargetLongLat->TargetGamma = 0;
FRenderTarget* RenderTarget = RenderTargetLongLat->GameThread_GetRenderTargetResource();

// 创建画布并绑定渲染目标
FCanvas* Canvas = new FCanvas(RenderTarget, NULL, FGameTime(), GMaxRHIFeatureLevel);
Canvas->SetRenderTarget_GameThread(RenderTarget);
Canvas->Clear(FLinearColor(0000)); // 清空为透明
  • **UTextureRenderTarget2D**:2D渲染目标,用于存储中间渲染结果。
  • **AddToRoot**:防止Unreal垃圾回收器(GC)误删资源。
  • **FCanvas**:Unreal的2D画布工具,允许在游戏线程操作GPU渲染。

3. 绘制立方体贴图并应用鱼眼变形

// 将立方体贴图绘制到渲染目标,并应用鱼眼参数
FCanvasTileItem TileItem(FVector2D(0.0f0.0f), TextureResource, FVector2D(FisheyeParams.ImageSize.X, FisheyeParams.ImageSize.Y), FLinearColor::White);
TileItem.BatchedElementParameters = BatchedElementParameters; // 注入鱼眼逻辑
TileItem.BlendMode = SE_BLEND_Opaque;
Canvas->DrawItem(TileItem);

// 提交渲染命令并等待完成
Canvas->Flush_GameThread();
FlushRenderingCommands();
  • **FCanvasTileItem**:将立方体贴图作为纹理平铺到整个渲染目标。
  • **BatchedElementParameters**:关键参数,绑定自定义的鱼眼变形逻辑(通过Unreal的FBatchedElementParameters机制注入到着色器)。
  • **FlushRenderingCommands**:强制同步渲染线程,确保所有GPU操作完成。

4. 读取像素数据到内存

// 分配内存并读取渲染结果
BitsOUT.AddUninitialized(ImageBytes);
bool bReadSuccess = false;
switch (TargetPixelFormat)
{
    case PF_B8G8R8A8: // LDR格式
        bReadSuccess = RenderTarget->ReadPixelsPtr((FColor*)BitsOUT.GetData());
    break;
    case PF_FloatRGBA: // HDR格式
        {
            TArray<FFloat16Color> FloatColors;
            bReadSuccess = RenderTarget->ReadFloat16Pixels(FloatColors);
            FMemory::Memcpy(BitsOUT.GetData(), FloatColors.GetData(), ImageBytes);
        }
    break;
}
  • **ReadPixelsPtr / ReadFloat16Pixels**:从GPU读取像素数据到CPU内存。
  • 内存拷贝:HDR格式需要将FFloat16Color数组转换为字节流。

5. 资源清理与输出

// 释放资源
RenderTargetLongLat->ReleaseResource();
RenderTargetLongLat->RemoveFromRoot();
RenderTargetLongLat = NULL;
delete Canvas;

// 设置输出参数
if (!bReadSuccess) BitsOUT.Empty(); 
return bReadSuccess;
SizeOUT = FisheyeParams.ImageSize;
FormatOUT = TargetPixelFormat;
if (bReadSuccess == false)
{
    // 失败时清空数据
    BitsOUT.Empty();
}
return bReadSuccess;
  • 资源管理:显式释放渲染目标和画布,避免内存泄漏。
  • 错误处理:若读取失败,清空输出缓冲区。

3. 关键技术与设计分析

1. 鱼眼变形实现原理

  • 自定义着色器注入
    通过FMipLevelBatchedElementParametersFisheye向Unreal的渲染管线注入自定义的顶点/像素着色器逻辑。

2. 线程与资源安全

  • 游戏线程操作
    所有FCanvasUTextureRenderTarget2D操作均在游戏线程执行,通过FlushRenderingCommands同步渲染线程,确保GPU操作完成。
  • 资源生命周期
    AddToRoot/RemoveFromRoot显式控制渲染目标的GC生命周期,防止异步渲染过程中资源被释放。

3. 性能优化

  • 格式自适应:根据输入纹理位宽选择LDR/HDR格式,平衡精度与内存。
  • GPU加速:变形计算完全在GPU执行,避免CPU计算瓶颈。
  • 内存池复用:外部调用方可能通过TArray64<uint8>& BitsOUT复用内存,减少分配开销。

下面我们来看FMipLevelBatchedElementParametersFisheye绑定着色器shader的方法:

template<typename TPixelShader>
void FMipLevelBatchedElementParametersFisheye::BindShaders(FRHICommandList& RHICmdList, FGraphicsPipelineStateInitializer& GraphicsPSOInit, ERHIFeatureLevel::Type InFeatureLevel, const FMatrix& InTransform, const float InGamma, const FMatrix& ColorWeights, const FTexture* Texture)
{
    // 省略
}

1. 功能概述

此函数是 具体执行着色器绑定和参数传递 的核心实现,负责将 顶点着色器(VS)和像素着色器(PS) 绑定到图形管线,并传递渲染所需的参数(如畸变系数、相机矩阵等)。它是在代码中前文出现的BindShaders函数的具体实现模板。

2. 关键代码逐行分析

template<typename TPixelShader>
void FMipLevelBatchedElementParametersFisheye::BindShaders(...)
{
    // 1. 设置混合状态(不混合,直接覆盖)
    GraphicsPSOInit.BlendState = TStaticBlendState<>::GetRHI();

    // 2. 获取着色器实例
    TShaderMapRef<FCubemapTexturePropertiesVSFisheye> VertexShader(...)// 顶点着色器
    TShaderMapRef<TPixelShader> PixelShader(...);                        // 模板化的像素着色器

    // 3. 配置管线状态
    GraphicsPSOInit.BoundShaderState.VertexDeclarationRHI = GSimpleElementVertexDeclaration.VertexDeclarationRHI; // 顶点声明
    GraphicsPSOInit.BoundShaderState.VertexShaderRHI = VertexShader.GetVertexShader();  // 绑定VS
    GraphicsPSOInit.BoundShaderState.PixelShaderRHI = PixelShader.GetPixelShader();     // 绑定PS
    GraphicsPSOInit.PrimitiveType = PT_TriangleList;                                   // 图元类型为三角形列表

    // 4. 提交管线状态到GPU
    RHICmdList.ApplyCachedRenderTargets(GraphicsPSOInit);
   SetGraphicsPipelineState(RHICmdList, GraphicsPSOInit, 0);

    // 5. 传递参数到着色器
    SetShaderParametersLegacyVS(RHICmdList, VertexShader, InTransform); // VS参数(变换矩阵)
    SetShaderParametersLegacyPS(RHICmdList, PixelShader, Texture,
        ColorWeights,
        MipLevel,
        InGamma,
        DistortionCoeffs,
        CameraMatrix,
        ImageSize,
        MaxAngle
    ); // PS参数(包含鱼眼关键参数)
}

3. 核心设计解析

(1)模板化像素着色器

  • **TPixelShader**:
    允许传入不同的像素着色器类(如FCubemapTexturePropertiesPSFisheye<true><false>),在 编译时生成多份代码,避免运行时分支判断。
  • 变体控制
    通过模板参数传递HLSL宏定义(如HDR_OUTPUT),实现 同一份HLSL代码的不同编译版本

(2)固定顶点着色器

  • **FCubemapTexturePropertiesVSFisheye**:
    所有鱼眼变体共享相同的顶点处理逻辑(如坐标变换),无需模板化,减少冗余代码。

(3)参数传递架构

参数类型      
传递方式      
对应HLSL变量      
InTransform
顶点着色器SetParameters      
变换矩阵(FMatrix)      
DistortionCoeffs
像素着色器SetParameters      
DistortionCoeffs      
 (float4)      
CameraMatrix
像素着色器SetParameters      
CameraMatrix      
 (float4)      
MaxAngle
像素着色器SetParameters      
MaxAngle      
 (float)      

4. 渲染管线配置细节

(1)混合状态设置

GraphicsPSOInit.BlendState = TStaticBlendState<>::GetRHI();
  • **TStaticBlendState<>**:
    表示无混合操作(BlendOp=AddSrcBlend=OneDestBlend=Zero),直接覆盖目标颜色,适合不透明渲染。

(2)图元类型

GraphicsPSOInit.PrimitiveType = PT_TriangleList;
  • 三角形列表:将顶点数据解释为独立三角形,用于渲染全屏四边形或简单几何体。

(3)顶点声明

GSimpleElementVertexDeclaration.VertexDeclarationRHI
  • 简单顶点格式:通常包含位置(POSITION)和纹理坐标(TEXCOORD0),匹配全屏四边形的输入结构。

5. 与HLSL代码的交互

顶点着色器参数传递

VertexShader->SetParameters(RHICmdList, InTransform);
  • 对应HLSL中的顶点变换矩阵:

    float4x4 TransformMatrix;

像素着色器参数传递

PixelShader->SetParameters(RHICmdList, DistortionCoeffs, ...);
  • 对应鱼眼着色器参数:

    float4 DistortionCoeffs;
    float4 CameraMatrix;
    float MaxAngle;

在代码中,我们使用的顶点着色器是UE在SimpleElementVertexShader.usf中原有的顶点着色器:

IMPLEMENT_SHADER_TYPE(,FCubemapTexturePropertiesVSFisheye,TEXT("/Engine/Private/SimpleElementVertexShader.usf"),TEXT("Main"),SF_Vertex);

而鱼眼图像的像素转换过程则依靠在UE的SimpleElementPixelShader.usf中新添加的像素着色器。首先解释下什么是前面提到的HLSL,这是在usf文件中使用的编程语言:

HLSL 详解

HLSL(High-Level Shader Language,高级着色器语言)是微软为 DirectX 图形API设计的一种编程语言,主要用于编写在GPU上运行的 着色器程序(Shader)。它是实现复杂图形效果的核心工具,广泛应用于游戏开发、影视渲染和实时图形处理。

1. HLSL 的核心作用

(1)定义图形渲染流程

通过编写不同类型的着色器,控制GPU如何处理几何体、光照、纹理和像素:

  • 顶点着色器(Vertex Shader):处理3D模型的顶点位置、法线、UV坐标等。
  • 像素着色器(Pixel Shader / Fragment Shader):计算每个像素的最终颜色。
  • 几何着色器(Geometry Shader):动态生成或修改几何图元(如细分曲面)。
  • 计算着色器(Compute Shader):执行通用计算任务(如物理模拟、图像处理)。

(2)实现高级图形效果

  • 光照与阴影:如动态全局光照(GI)、软阴影、环境光遮蔽(SSAO)。
  • 材质与纹理:如PBR材质(金属/粗糙度)、法线贴图、视差映射。
  • 后处理效果:如景深、运动模糊、HDR色调映射。
  • 特殊投影:如我们本文讨论的鱼眼镜头畸变模拟。

2. HLSL 的语法特点

(1)类C语法结构

与C语言类似,支持函数、条件语句、循环等,但包含图形专用类型和语义:

// 示例:简单的像素着色器
float4 MainPS(float2 UV : TEXCOORD0) : SV_Target
{
    float4 Color = Texture2D.Sample(TextureSampler, UV);
    return Color * LightIntensity;
}

(2)图形专用数据类型

类型      
描述      
示例      
float      
half      
单精度/半精度浮点数      
float3 position;
int      
uint      
整数类型      
uint vertexID;
float2      
float3x3      
向量与矩阵      
float4 color = {1,0,0,1};
Texture2D
2D纹理      
Texture2D DiffuseMap;
SamplerState
纹理采样器(过滤/寻址模式)      
SamplerState LinearWrap;

(3)语义绑定(Semantics)

通过语义标签将变量与渲染管线数据关联:

// 顶点着色器输入
struct VSInput
{
    float3 Position : POSITION;    // 顶点位置
    float2 UV       : TEXCOORD0;   // 纹理坐标
};

// 像素着色器输出
float4 MainPS() : SV_Target        // 输出到渲染目标
{
    return float4(1,0,0,1);
}

3. HLSL 在 Unreal 引擎中的应用

(1)材质系统

Unreal的 材质编辑器 底层通过HLSL代码生成最终的着色器。用户可以通过节点图可视化编程,或直接编写 Custom Node 注入HLSL代码。

(2)自定义着色器

开发者可以直接编写.usf(Unreal Shader File)文件,实现复杂效果(如我们分析的鱼眼投影函数):

// 示例:鱼眼畸变计算
void CubemapTexturePropertiesFisheye(float2 UV)
{
    float2 NormCoord = (UV - CameraMatrix.zw) / CameraMatrix.xy;
    // 迭代求解畸变模型...
}

(3)渲染管线扩展

通过修改引擎的 Shader 代码,可以自定义延迟渲染、光线追踪等高级管线。


最后我们终于来到了本文最核心的部分:shader文件SimpleElementPixelShader.usf,该Shader文件是Unreal简单元素渲染系统的核心组件,通过高度优化的HLSL代码实现了从基础纹理混合到复杂鱼眼投影的多功能渲染。其中的鱼眼投影函数CubemapTexturePropertiesFisheye是本文讨论的重点:

1. 参数定义与物理意义

参数名      
类型      
物理意义      
对应现实世界中的标定参数      
DistortionCoeffsfloat4
鱼眼镜头畸变系数(k₁, k₂, k₃, k₄),用于描述径向畸变的非线性多项式模型。      
相机标定中的畸变参数(OpenCV/Kalibr格式)      
CameraMatrixfloat4
相机内参矩阵,存储焦距和主点坐标(f_x, f_y, c_x, c_y)。      
内参矩阵:[f_x, 0, c_x; 0, f_y, c_y; 0, 0, 1]      
MaxAnglefloat
鱼眼镜头最大视场角(单位:度),控制有效成像区域的角度范围。      
例如:180°、220°      

2. 计算流程与参数映射

以下是函数内部关键计算步骤与参数的对应关系:

步骤1:像素坐标归一化与去主点偏移
TextureCoordinate.x = (TextureCoordinate.x - c_x) / f_x;
TextureCoordinate.y = (TextureCoordinate.y - c_y) / f_y;
  • 参数作用
    • c_xc_y(来自CameraMatrix):将像素坐标从图像坐标系(以左上角为原点)转换到以光心为中心的归一化坐标系。
    • f_xf_y(来自CameraMatrix):将像素坐标缩放为无单位的归一化坐标(类似于OpenCV的“理想像素”坐标系)。
  • 数学对应
步骤2:畸变模型迭代计算
float r = sqrt(x*x + y*y);
float theta = r;
for (int j = 0; j < 10; j++) {
    float th2 = theta * theta;
    float th4 = th2 * th2;
    float th6 = th4 * th2;
    float th8 = th6 * th2;
    theta = r / (1.0 + d1*th2 + d2*th4 + d3*th6 + d4*th8);
}
  • 参数作用
    • d1d2d3d4(来自DistortionCoeffs):定义畸变多项式权重,通过牛顿迭代法反向求解无畸变半径。
  • 数学模型

通过10次迭代反向求解:


步骤3:球面坐标与方向向量映射
float lambda = atan2(y, x);
float phi = PI/2 - theta;
float3 Direction = float3(cos(phi)*cos(lambda), -cos(phi)*sin(lambda), sin(phi));
  • 参数作用
    • theta(来自迭代结果):无畸变归一化半径,转换为极角(Polar Angle)。
  • 几何映射
    • lambda:方位角(Azimuth Angle),从x轴逆时针旋转。
    • phi:天顶角(Zenith Angle),从z轴向下倾斜。
    • 方向向量:将极坐标转换为3D单位向量,用于立方体贴图采样。
步骤4:最大视场角限制与边缘柔化
float theta_f = MaxAngle * PI / 360.0f; // 转换为半角弧度
BaseColor *= (1 - s moothstep(theta_f - 0.2, theta_f, theta));
  • 参数作用
    • MaxAngle:定义有效成像的最大半角(例如180°对应theta_f = PI/2)。
  • 技术实现
    • 使用s moothstep[theta_f-0.2, theta_f]范围内创建渐变透明度,避免硬截断导致的锯齿。

3. 参数对最终图像的影响

参数调整      
图像变化效果      
应用场景示例      
增大MaxAngle
扩大鱼眼图像的视野范围,捕捉更广的环境,边缘拉伸更明显。      
超广角监控摄像头模拟      
增加d1(k₁)
增强桶形畸变(中心膨胀,边缘压缩),图像中心区域放大。      
低质量鱼眼镜头模拟      
调整f_xf_y
改变焦距:f_x减小 → 水平视场角增大;f_x增大 → 水平视场角减小。      
不同焦距镜头的标定参数测试      
偏移c_xc_y
图像中心点偏移,模拟光轴与图像传感器中心不对齐的镜头。      
非对称安装的镜头校正      

4. 完整数据流与参数传递

flowchart TD
    C++[C++侧参数设置] --> |DistortionCoeffs| HLSL(d1, d2, d3, d4)
    C++ --> |CameraMatrix| HLSL(f_x, f_y, c_x, c_y)
    C++ --> |MaxAngle| HLSL(theta_f)
    HLSL --> 像素坐标校正["归一化坐标 (x, y)"]
    像素坐标校正 --> 畸变迭代["迭代求解 theta"]
    畸变迭代 --> 球面映射["方向向量 Direction"]
    球面映射 --> 立方体采样["采样 Cubemap"]
    立方体采样 --> 边缘柔化["应用 MaxAngle 渐变"]
    边缘柔化 --> 输出颜色["OutColor"]

通过以上这种CubemapTexture展开做鱼眼相机投影的方法产生鱼眼相机图像,仍然没有解决的问题是,六面体Cubemap展开时,面与面的接缝有时会出现在图像中,如下图所示:

根据文档how-to-add-a-new-sensor,接下来是编制Sensor data serializer,Sensor data object,在SensorRegistry.h中注册你的新传感器等环节,本文提供的代码在这些部分中基本都是参照Carla原有传感器的代码进行编写的,读者可自行对照文末提供的代码进行分析。

在CarlaUE5\PythonAPI\examples提供的示例py文件cam_test_0313.py中,有调用这种Fisheye Sensor的例子。

代码验证

本文适配的CarlaUE5和UnrealEngine5_carla的确切版本是:

CarlaUE5:
commit 0bfb05bfdde8435bfecfccdef8a0e05041b22aef (origin/ue5-dev, origin/HEAD)
Author: MarcelPiNacy-CVC <169088301+MarcelPiNacy-CVC@users.noreply.github.com>
Date:   Mon Mar 10 14:24:37 2025 +0100
    Remove MakeFile. (#8739)

UnrealEngine5_carla:
commit eea6a8e677e3509a3e56122d69e3d380bb624bbf (HEAD -> ue5-dev-carla, origin/ue5-dev-carla, origin/HEAD)
Author: Marcel Pi <169088301+MarcelPiNacy-CVC@users.noreply.github.com>
Date:   Fri Feb 28 12:53:51 2025 +0100
    Add missing chrono include.

编译CarlaUE5和UnrealEngine5_carla的方法在官方文档中很清晰了。在CarlaUE的编译脚本中,会下载Unreal\CarlaUnreal\Content目录下的大文件(约70G),见文末百度云链接。

读者在编译前可提前下载,并放置在对应位置。

首次编译成功,可以运行Carla后,如果对UE和Carla的代码进行了修改,需要对UnrealEngine5_carla和CarlaUE5分别再次进行编译:

# UE5:
./Setup.sh
./GenerateProjectFiles.sh
make

# CarlaUE5:
./CarlaSetup.sh --interactive --python-root=/home/vipuser/.conda/envs/carla/bin

最新版本的CarlaUE5可以通过--python-root参数指定需要的python虚拟环境。CarlaSetup.sh中的参数launch修改为1可以在运行脚本后打开UE窗口。

点击UE窗口中的Run后,运行PythonAPI\examples\cam_test_0313.py,会将Fisheye生成的鱼眼图像保存在py脚本中写出的保存路径(请先按需修改)。

来源:车路漫漫
ACTSystemMarc非线性通用ADSpython游戏控制渲染曲面
著作权归作者所有,欢迎分享,未经许可,不得转载
首次发布时间:2025-12-10
最近编辑:8月前
李慢慢
硕士 自动驾驶仿真工程师一枚
获赞 14粉丝 93文章 320课程 0
点赞
收藏
作者推荐

盘点-自动驾驶仿真领域常见的开源工具

大家好,我是李慢慢。从事自动驾驶仿真好些年了,期间有接触到or听闻过很多开源的仿真工具,这里把他们整理了一下,分享给大家。内容有点多,建议先收藏。目录如下: 以下,正文。1、仿真软件1.1、CARLACARLA 是一个开源的自动驾驶研究模拟器。它基于 Unreal Engine 运行模拟,采用 OpenDRIVE 标准定义道路和城市环境。其具有可扩展的服务器 - 多客户端架构,支持同一或不同节点的多个客户端控制不同参与者。通过灵活的 API,用户能控制交通生成、行人行为、天气、传感器等模拟相关的所有方面。用户还可配置包含激光雷达、摄像头、深度传感器和 GPS 等多样化的自动驾驶传感器套件。此外,CARLA 支持地图生成、交通场景模拟,能与 ROS 集成,并提供自动驾驶基准,为自动驾驶系统的开发、训练和验证提供了丰富的功能和工具。 仓库地址:https://github.com/carla-simulator/carla车路漫漫历史相关文章:介绍一款开源的自动驾驶仿真模拟器-Carla1.2、LGSVLLGSVL Simulator 是 LG 电子美国研发中心开发的基于 Unity 游戏引擎的开源自动驾驶仿真系统。它提供端到端的仿真,通过自定义通信 Bridge 与多种自动驾驶算法引擎接口进行消息传递,支持 ROS、ROS2 和 Cyber RT 消息,能与 Autoware、百度 Apollo 等开源自动驾驶引擎便捷集成。用户可利用核心仿真引擎轻松定制传感器、创建新型可控对象等,还可通过地图工具导入导出多种格式的高精地图。其能模拟逼真的 3D 环境、动态交通场景和各类传感器,可用于自动驾驶系统的软件在环和硬件在环测试,助力开发者降低测试成本,加速自动驾驶技术的研发与验证。 仓库地址:https://github.com/lgsvl/simulator 截图:LGSVL已经于2022年停止更新维护1.3、AirsimAirSim 是微软开源的跨平台仿真平台,基于虚幻引擎构建,也支持 Unity 引擎。旨在为无人机、自动驾驶汽车等自主系统提供逼真的视觉和物理仿真环境。它具有高度逼真的渲染效果和精确的物理模拟,能模拟多种传感器,支持软件在环和硬件在环仿真。提供丰富的 API 接口,支持多种编程语言,方便开发者控制车辆、获取数据和修改环境参数。此外,AirSim 还具有跨平台兼容性、灵活性和可扩展性等特点,为人工智能、计算机视觉和强化学习算法的研究与开发提供了理想的测试环境,降低了实际硬件测试的成本和风险。 仓库地址:https://github.com/microsoft/AirSim备注:AirSim本来是为了无人机设计的仿真软件,但是也可以用于自动驾驶汽车甚至于飞行汽车。1.4、TADSimTAD Sim 是腾讯发布的开源自动驾驶仿真测试平台。它是为智能驾驶系统研发和验证量身定做的跨平台分布式仿真系统,基于腾讯专业的游戏引擎、厘米级数字孪生三维重建技术等,集成工业级车辆动力学模型、物理级传感器仿真和数据驱动的 AI 交通流模型。其具备高保真场景还原、高精度车辆动力学模型等特点,可完成实车上全部模块的闭环仿真验证,支持模型在环、软件在环等车辆验证 V 字全流程,能与自动驾驶云工具链全流程打通。此外,平台采用模块化、标准化、合规化设计,支持 OpenX 国际标准格式,方便扩展和第三方对接。 开源仓库地址:https://github.com/Tencent/TAD_Sim单机版 (标准版) 用户手册:http://www.agfutrue.com:8082/tadsim-html/index.html TADsim软件架构图1.5、self driving car simulatorUdacity self - driving car simulator 是基于 Unity 游戏引擎的开源自动驾驶汽车模拟器。它主要用于 Udacity 的无人驾驶工程师纳米学位课程,帮助学生学习如何使用深度学习训练无人驾驶汽车。该模拟器能构建高度真实的 3D 世界,包括复杂路况、天气条件和多样的交通参与者。通过其简洁的 API,开发者可发送控制指令并接收车辆状态等数据。同时,它还能方便地整合机器学习框架,用于训练和验证自动驾驶算法,可载入内置场景或创建虚拟测试路线,为学生和研究人员提供了一个安全、低成本的实践平台,有助于推动自动驾驶技术的发展。 仓库地址:https://github.com/udacity/self-driving-car-sim1.6、GazeboGazebo 是一款功能强大的开源机器人仿真软件。它能为机器人提供逼真的物理模拟环境,精确模拟机器人在现实世界中的运动、受力等情况。Gazebo 拥有丰富的模型库,包含各种机器人模型以及室内外场景模型,用户可方便地进行组合和定制。同时,它支持多种传感器模拟,如摄像头、激光雷达等,可帮助开发者测试机器人的感知系统。此外,Gazebo 还具有良好的开源生态,与 ROS 等机器人开发框架集成紧密,便于开发者进行机器人算法的开发、调试和验证,广泛应用于机器人研究、教学以及工业开发等领域。仓库地址:https://github.com/gazebosim/备注:Gazebo可以用于自动驾驶车辆仿真测试。它能提供逼真的物理模拟环境,精确模拟车辆的动力学特性和运动状态,包括车辆在不同路况、天气条件下的行驶情况。1.7、marsOPEN - AIR - SUN/mars 是用于自动驾驶仿真测试的开源工具。它聚焦于复杂场景的模拟,可构建出接近真实的交通环境,涵盖不同的道路类型、多样的天气状况以及复杂的交通流。其优势在于高保真度的传感器仿真,能精准模拟激光雷达、摄像头等设备的工作,为自动驾驶算法提供高质量的测试数据。并且,它具备灵活的场景编辑功能,开发者可以根据需求定制特定场景,实现对自动驾驶系统在极端或特殊情况下的性能测试。此外,该软件开源的特性,方便全球开发者共同参与优化和改进,促进自动驾驶技术的快速发展。 仓库地址:https://github.com/OPEN-AIR-SUN/mars1.8、渲染引擎1.8.1、UnrealUnreal 是一款强大的开源游戏开发引擎。它以高端的图形渲染能力著称,能够创建出极其逼真的游戏画面和沉浸式的虚拟环境。提供了丰富的工具和资源,涵盖建模、动画、特效等多个方面,方便开发者进行各种类型游戏的开发。其蓝图可视化脚本系统,让非专业编程人员也能轻松实现复杂的游戏逻辑。Unreal 还支持跨平台开发,可发布到 PC、主机、移动等多种平台。同时,它在影视制作、建筑设计、教育培训等领域也有广泛应用,凭借其出色的功能和性能,成为全球众多开发者和工作室青睐的开源软件。前文提到的自动驾驶仿真软件CARLA / TADSim就是基于Unreal开发的哦。1.8.2、UnityUnity 是一款广泛使用的跨平台开源游戏开发软件。它提供了丰富的工具和资源,让开发者能轻松创建 2D、3D 游戏及其他互动内容。其可视化的开发界面便于操作,即使是初学者也能快速上手。Unity 拥有大量的插件和 Asset Store 资源,可帮助开发者节省开发时间和成本。同时,它支持多种平台发布,包括 PC、移动设备、主机等,能满足不同用户的需求。此外,Unity 还有活跃的社区,开发者可以在社区中交流经验、分享代码,获取技术支持,这使得 Unity 成为游戏开发领域中非常受欢迎的开源软件之一。前文提到的自动驾驶仿真软件LGSVL / self driving car simulator 就是基于Unity开发的哦。2、地图&amp;场景2.1、场景播放器-Es miniEs mini 是一款由瑞典国家道路与交通研究所(VTI)开发的开源交通场景模拟器。它支持 OpenSCENARIO 标准,能依据该标准的场景描述文件精准创建各种复杂交通场景,为自动驾驶算法的开发与测试提供便利。通过 Es mini,用户可灵活定义交通参与者的行为、路线等元素,模拟逼真的交通环境。其基于 OpenSCENARIO 的特性,使得它能与其他遵循该标准的软件工具良好集成,方便研究人员和开发者在统一的场景描述规范下进行协同工作,推动自动驾驶技术的研究与发展,在自动驾驶领域有着广泛的应用和重要的地位。 仓库地址:https://github.com/es mini/es mini/releases车路漫漫历史相关文章:介绍一款开源的自动驾驶仿真场景播放器:es mini2.2、地图制作软件-TrueVision 仓库地址:https://github.com/truevisionai/designer车路漫漫历史相关文章:介绍一款开源的OpenDrive地图制作软件2.3、OpenDrive查看器-网页版https://odrviewer.io/网页版的OpenDRIVE文件查看器,不用注册,打开即用。 仓库地址:https://github.com/pageldev/libOpenDRIVE2.4、场景泛化-Python库:scenariogenerationscenariogeneration是一个用于生成汽车驾驶场景描述的 Python 库。它基于 OpenSCENARIO 标准,提供了丰富的接口和工具,能以编程方式创建复杂的驾驶场景。通过该库,用户可轻松定义道路、交通参与者、环境条件等场景元素,还能设置车辆的行为模式、交通规则等。其优势在于可实现场景生成的自动化,方便研究人员和开发人员为自动驾驶汽车的仿真测试创建各种不同的场景,有助于评估自动驾驶系统在多样化场景下的性能和安全性,在自动驾驶技术的研发和测试领域有着重要的应用。 车路漫漫历史相关文章:如何用python库scenariogeneration来创建静态地图+动态场景进行自动驾驶仿真2.5、交通场景制作器-RoadMateRoadMate 是由动森数字科技(重庆)有限公司研发的交通场景编辑器。它是国产首款实现设计和仿真一体化的软件,基于三维引擎技术,支持工程级别交通三维场景一键还原及正向设计,同时可进行实时交通模拟分析。其具有二三维一体化设计模式、实时渲染更新、交通流量实时仿真等功能,能让用户在 2D 平面视图与 3D 立体视图间无缝切换,即时查看高保真效果,模拟车辆轨迹与流量。此外,RoadMate 还可实现 VR 漫游,让用户以模拟驾驶体验来感受工程场景,优化设计方案,并且支持将设计场景导出为 OpenDRIVE 格式,广泛适用于公路与市政建设、驾驶仿真测试与规划、交通管理等领域。 备注:RoadMate部分功能需要付费,但对于想要简单画画道路的朋友来说免费功能也是足够了。 备注:RoadMate不是开源的,但部分功能可以免费 使用,所以也放到这里给大家参考。车路漫漫历史相关文章:介绍一款国产交通场景编辑器-Roadmate2.6、交通流仿真软件-SUMOSUMO 是一款开源的微观交通流仿真软件。它能对城市交通系统进行详细建模与仿真,包括车辆、行人、自行车等交通参与者以及道路网络、交通信号灯等基础设施。其具有高度的灵活性和可扩展性,用户可通过配置文件自定义各种交通场景和参数。SUMO 提供了丰富的接口,支持与其他软件如交通规划工具、自动驾驶算法等进行集成。它还能生成多种可视化结果和统计数据,帮助研究人员和交通规划者分析交通流量、评估交通方案,进而优化交通系统设计与管理,在智能交通系统研究、城市交通规划等领域应用广泛。 仓库地址:https://github.com/eclipse-sumo/sumo车路漫漫历史相关文章:SUMO:一个开源的交通流仿真平台3、中间件&amp;可视化3.1、ROS / ROS2ROS(机器人操作系统)是一个用于机器人开发的开源框架,提供了丰富的工具、库和约定,使开发者能更轻松地创建机器人应用程序。它采用分布式架构,通过话题、服务等机制实现节点间的通信,支持多种编程语言。ROS 2 是 ROS 的升级版,针对实时性、安全性等方面进行了改进,采用了更现代化的通信机制 DDS,提高了系统的可靠性和性能。ROS 2 还增强了对不同操作系统和硬件平台的支持,能更好地适应机器人领域不断发展的需求,无论是开发工业机器人还是科研用机器人,ROS/ROS 2 都是广泛使用的重要工具。官网地址:https://www.ros.org/车路漫漫历史相关文章:终于有人把ROS(机器人操作系统)讲明白了3.2、Riviz / riviz2RViz 和 RViz2 都是用于可视化机器人操作系统(ROS)的工具。RViz 是 ROS 最初推出的可视化工具,基于 Qt 和 OpenGL 库开发,能显示点云、激光扫描等多种数据,支持模块化插件。RViz2 是 RViz 的新版本,随 ROS 2 发布。它采用现代化的 Qt Quick 界面和新的图形渲染库,性能更好、渲染速度更快。RViz2 与 ROS 2 紧密集成,提供更多功能和改进,如对 2D 和 3D 导航的支持等。两者都有用户友好的界面,可同步显示机器人的传感器数据、模型等信息,帮助用户直观了解机器人运行状态,用户可根据需求和 ROS 版本选择使用。 3.3、FoxgloveFoxglove 是一款开源的数据可视化和分析工具,主要用于机器人、自动驾驶汽车等领域。它支持 ROS、ROS 2 等多种数据格式和协议,能实时显示机器人的运动、位置和状态,也可加载回放记录数据。通过直观的界面,用户可选择图表、3D 视图等多种方式展示数据,并利用时间轴工具、数据过滤等功能进行深入分析。此外,它还提供脚本编辑器、插件机制等高级特性,支持团队协作,方便成员共享数据和分析结果,有助于提高开发效率,优化机器人系统和自动驾驶技术。 官网:https://foxglove.dev/ 备注:2024 年 3 月,Foxglove 发布 2.0 版本,将原来的开源项目 Foxglove Studio 和 Foxglove 数据平台整合为一个产品,以统一机器人的可观测性。为了专注于开发这个集成平台,Foxglove 决定停止 Foxglove Studio 开源版本的开发。此前,Foxglove Studio 遵循开放核心许可模式,大多数功能开源,官方二进制发行版包含一些闭源功能。但自 2.0 版本发布后,1.x 版本的开源代码虽仍在线,但不再更新维护。4、被测对象-智驾软件被测对象,是相对于仿真测试来说的,其实指的就是智驾软件。以下分享两类智驾软件。一类是基于规则的自动驾驶,一类是基于端到端的自动驾驶。4.1、AutowareAutoware 是基于 ROS 构建的领先开源自动驾驶软件。它集成车辆定位、物体识别、路径规划和控制等关键功能,提供全栈式自动驾驶解决方案。分为 Autoware.Core 和 Autoware.Universe 两大分支,前者基于ROS开发,注重稳定版本开发;后者基于ROS2开发,专注实验性、前瞻性探索。其优势众多,包括模块化架构便于定制扩展、可扩展性强能满足多种应用、持续进化提升性能、应用场景广泛。它支持多种传感器,拥有活跃的社区和详细的官方文档,为全球开发者提供共享协作平台,降低自动驾驶技术研发门槛,推动该领域技术发展。 仓库地址:https://github.com/autowarefoundation/autoware车路漫漫历史相关文章:一站式搞定Autoware的下载、安装和试运行4.2、openpilotOpenpilot 是由 the comma.ai 团队发起的开源自动驾驶软件。它基于 Python 和 C++ 编写,利用深度学习和计算机视觉算法实时理解驾驶环境并决策。通过集成摄像头、雷达等传感器数据,实现自适应巡航控制、自动车道居中、前向碰撞警告等功能。其具有开源免费、高度可定制、模块化设计等特点,拥有活跃的社区和详细的官方文档,为自动驾驶领域的研究者、开发者以及爱好者提供了良好的平台,可用于日常驾驶、研发测试和教育学习等场合。 仓库地址:https://github.com/commaai/openpilot车路漫漫历史相关文章:开源自动驾驶系统openpilot的下载及使用4.3、ApolloApollo 是百度开源的自动驾驶平台,于 2017 年推出,目标是为开发者提供开放、完整且安全的解决方案,加速自动驾驶技术的发展。它提供了一套完整的工具链和参考代码,涵盖感知、规划、决策、控制等自动驾驶核心模块,支持多种传感器和硬件平台。同时,Apollo 具备强大的仿真能力,可模拟复杂场景进行算法测试和验证。此外,它拥有丰富的文档和社区资源,方便开发者学习和交流。许多企业和科研机构基于 Apollo 开展自动驾驶研发,促进了技术的快速迭代和落地应用,推动了整个自动驾驶行业的发展。 仓库地址:https://gitee.com/ApolloAuto/apolloApollo 自动驾驶开放平台:https://apollo.baidu.com/docs/apollo/10.x/index.html4.4、端到端模型-VADVAD (Vectorized Autonomous Driving)是由华中科技大学和地平线机器人公司的研究者共同开发的端到端自动驾驶开源软件(一段式)。它将驾驶场景建模为完全向量化的表示,摒弃了计算密集的栅格表示和手工设计的后处理步骤,有效提升了规划安全性和运行速度。其输入为多帧、多视角图像,输出是自车未来规划轨迹,框架分为图像特征提取、向量化场景学习、规划推理与训练等阶段。在 nuScenes 数据集和 CARLA 模拟环境中,VAD 都展现出了卓越的性能,实现了当前最优的端到端规划性能,为自动驾驶技术的研究和发展提供了有价值的参考。 仓库地址:https://github.com/hustvl/VAD4.5、端到端模型-UniADUniAD 是 OpenDriveLab 开发的基于端到端自动驾驶的开源软件。它旨在构建一个统一架构来处理自动驾驶中的感知、预测、规划等多个任务。其原理是通过多模态数据融合,利用深度学习网络将摄像头、激光雷达等传感器数据输入,经神经网络处理后直接输出驾驶决策,减少了传统方法中各模块间的复杂交互。在使用效果上,它能适应复杂的交通场景,展现出较好的泛化能力,可在不同的环境中做出合理决策。该模型为自动驾驶研究提供了新的思路和方案,其开源特性也方便全球开发者进行研究、改进,推动端到端自动驾驶技术不断进步。 仓库地址:https://github.com/opendrivelab/uniad4.6、端到端模型-ThinkTwiceThinkTwice 是由 OpenDriveLab 开发、基于 PyTorch 实现的端到端自动驾驶开源模型,在 CVPR 2023 上发布。它采用鸟瞰图(BEV)视角,通过多传感器融合获取 BEV 特征。其创新的解码器包含 Look、Prediction 和 Refinement 模块,能利用时空先验知识和密集监督,以粗到细的方式预测车辆动作和轨迹。该模型在 Carla 模拟器上进行闭环评估,展现出先进的性能,为自动驾驶车辆在复杂场景中提供精确的路径规划和决策支持。其代码结构清晰,文档和示例详细,方便研究者和开发者使用,推动了端到端自动驾驶技术的发展。 仓库地址:https://github.com/OpenDriveLab/ThinkTwice4.7、端到端模型-TCPOpenDriveLab/TCP 是一个端到端的自动驾驶开源模型。它是结合轨迹规划和控制预测的统一框架,通过研究两种输出形式的特点并将其整合,加入交互,根据先验方案灵活结合两分支输出来获得最佳最终控制信号。该模型仅使用单一单目相机作为输入,就在 CARLA 自动驾驶排行榜上取得了第一名的成绩,在不同测试环境和场景下,能出色应对各类挑战性驾驶场景。其代码遵循 Apache 2.0 许可协议,可在 GitHub 上获取,包含了模型训练、数据生成、评估等相关代码和教程。 仓库地址:https://github.com/OpenDriveLab/TCP5、评价方法5.1、LeaderboardCARLA Leaderboard 是基于 CARLA 仿真环境的扩展,用于评估自动驾驶算法的表现。它是一个开放平台,能对自动驾驶智能体在现实交通场景中的驾驶能力进行公平、可重复的评估。用户可通过配置文件定制评估流程,包括设定 CARLA 服务器地址和端口、测试路线、自动驾驶系统算法或模型、特殊场景、天气条件及日志记录等。自动驾驶智能体需按照预设路线行驶,路线涵盖高速公路、城区、乡村等场景及不同天气条件。用户可通过 sensor track 和 map track 两种方式参与评估,前者提供传感器模拟数据信息,后者在此基础上还提供高精地图信息。 仓库地址:https://github.com/carla-simulator/leaderboard官网:https://leaderboard.carla.org/5.2、Bench2DriveBench2Drive 是首个以闭环方式评估端到端自动驾驶(E2E - AD)系统多种能力的基准测试平台。其官方训练数据由 200 万帧完全标注的图像组成,涵盖 44 个交互场景、23 种天气条件和 12 个城镇。评估协议要求 E2E - AD 模型通过不同地点和天气下的 44 个交互场景,共 220 条路线,以此全面评估其驾驶能力。Bench2Drive 采用成功率和驾驶分数等指标,还具备多样化大规模官方训练数据、细致的技能评估等特点,为研究人员提供了在现实、全面和公平的环境中优化和评估端到端自动驾驶系统的关键工具,推动自动驾驶领域的发展。 仓库地址:https://github.com/Thinklab-SJTU/Bench2Drive车路漫漫历史相关文章:介绍一个端到端自动驾驶的闭环评价方案6、结语这么多开源工具,组合起来使用,其实已经可以干很多事了。有实力的小伙伴甚至还可以魔改魔改几个软件,可玩性很强的。小伙伴们如果还知道一些别的开源工具,可以在文末留言指出哈,非常感谢。以上,本文完。来源:车路漫漫

未登录
还没有评论
课程
培训
服务
行家
VIP会员 学习计划 福利任务
下载APP
联系我们
帮助与反馈