HIL-Sim台架CHS使用手册

本文档主要介绍HIL-Sim台架CHS(Caronsim HIL-Sim)的使用方法和SDK二次开发,carla源码仓库:https://gitcode.com/caronsim/carla,SDK源码仓库:https://gitcode.com/caronsim/hil_sim_sdk

SDK开发环境只需要一台普通ubuntu22.04(配nvidia显卡)即可,生产环境台架硬件配置见:https://caronsim.com/hil_sim

我们提供了编译打包好的carla二进制网盘下载,你也可以自行编译。对于carla的编译使用方法请参考官方文档

CH2板卡

caronsim_hil_2_0_0

CH2板卡基础用法配置如下:

  1. SW9拨码配置为0/1/0/1的sd卡启动模式(注意拨码数字"1234"一侧为0,而"ON KE"一侧为1)
  2. SW10拨码配置为0/1/0/1,配置MAX9295加串器的IIC默认地址为80,以及GMSL2为6Gbs模式
  3. sd卡用读卡器在PC上格式化为fat32,然后在根目录下放入BOOT.BIN(固件镜像),最后把sd卡插入CH2板卡的sd卡插槽
  4. 注意风扇正确插入FAN插槽,RST开关拨ON(即靠近FAN插槽一侧)。在服务器关机状态下,把CH2板卡插到PCIe的x16插槽,此时板卡完全由PCIe插槽供电不需要外接电源
  5. 上图中有三组12路视频编号,这里推荐用“罗森版HFM四腔母头转XX”系列的mini-fakra线材来连接CH2板卡和你的域控,比较常见的情况如下:

1 2 3 4 5

CH2板卡进阶使用方法:

SW9全部为ON/ON/ON/ON状态为JTAG模式,OFF/ON/OFF/ON为sd卡启动模式,原理图如下: image-IpEI.png

SW10为OFF/ON/OFF/ON状态为I2C地址80+6Gbs模式,OFF/ON/ON/OFF状态为I2C地址80+3Gbs模式,其他模式配置见如下原理图: image-PuXt.png

两个12pin的简牛口引出了GMSL2加串器的frame-sync/frame-trigger接口以及IIC接口,方便获取对应信号,如下图: image-DmWl.png

刷写固件:把BOOT.BIN放到hil_sim_sdk/tools目录下,运行./flash.sh BOOT.BIN可以刷写CH2板卡固件,刷写完后CH2板卡会自行断电下线(你会听到咔的一声),然后你需要reboot重启服务器。

安装依赖

在ubuntu22.04系统中下载SDK后unzip hil_sim_sdk-vx.y.z.zip解压,目录结构如下:

.
├── api 此sdk二次开发api
│   ├── build.sh 演示api用法,编译ue4_mock二进制
│   ├── hil_api.h 开放的api的头文件
│   ├── hil_api.py 开放的api的python接口
│   ├── hil_utils.h
│   ├── libhil_api.so
│   ├── lsgpu
│   ├── ue4_mock
│   ├── ue4_mock.cpp
│   └── ue4_mock.sh
├── cache
├── can 此目录为can服务相关
│   ├── can_client.py
│   ├── can_server.py
│   ├── demo_0.dbc
│   ├── demo_1.dbc
├── common.sh
├── config.sh 本sdk配置文件
├── data 驱动文件
│   ├── CH341SER_LINUX.ZIP
│   ├── dma_ip_drivers-master.zip
│   ├── f81601a_driver.zip
│   ├── imx728_3840x2161.pad.raw
│   ├── isx031_1920x1537.raw
│   ├── ovx3c_1920x1282.pad.raw
│   └── peak-linux-driver-9.0.tar.gz
├── dut_deploy 本sdk自带timesync.service的时钟同步服务
│   ├── deploy.sh
│   ├── dut_chrony.conf
│   ├── dut_chronyd
│   ├── dut_phc2sys
│   ├── dut_ptp4l
│   ├── dut.service
│   └── dut.sh
├── dut_deploy.sh
├── host_deploy.sh 把sdk部署到台架服务器
├── host_install.sh 安装sdk运行所需依赖
├── LinuxNoEditor 编译打包好的carla二进制
├── logs
├── lscpu.txt cpu核心绑定配置文件
├── lsgpu.txt gpu详细信息
├── monitor.log
├── monitor.py
├── monitor.sh 查看video.service/can.service/timesync.service状态
├── restart_services.sh
├── results
├── service
│   ├── can.service
│   ├── can_service.sh
│   ├── hdmi.service
│   ├── hdmi_service_app
│   ├── hdmi_service.sh
│   ├── phc2sys
│   ├── ptp4l
│   ├── ptp4l.cfg
│   ├── ptp4l.cfg.template
│   ├── timesync.service
│   ├── timesync_service.sh
│   ├── video.service
│   ├── video_service_app
│   └── video_service.sh
├── sim 本sdk的python客户端核心代码
│   ├── camera_sensors.py
│   ├── client.py
│   ├── collision_sensor.py
│   ├── drive_control.py 
│   ├── ego_car.py
│   ├── fake_dut_drive.py
│   ├── gnss_sensor.py
│   ├── hud.py
│   ├── imu_sensor.py
│   ├── keyboard_parser.py
│   ├── lane_invasion_sensor.py
│   ├── lidar_sensors.py
│   ├── schedule_callback.py
│   ├── screen_sensor.py
│   └── sim_utils.py
├── sim.sh
├── test_case 本sdk的测试框架和测试用例demo
│   ├── cncap
│   ├── collision_checker.py
│   ├── crosslane_checker.py
│   ├── demo
│   ├── egocar_controller.py
│   ├── metric_collector.py
│   ├── test_case.py
│   ├── test_case_utils.py
│   ├── timeout_checker.py
│   └── yield_callback.py
└── tools 刷写CH2板卡固件工具
    ├── BOOT.BIN
    ├── flash.py
    ├── flash.sh
    └── show_nv12.py

cd进入hil_sim_sdk目录,用root运行host_install.sh脚本。host_install.sh脚本做了三件事:

  1. 更换lowlatency的ubuntu内核,并且优化系统性能
  2. 安装必要的系统依赖和pip依赖
  3. 安装Nvidia显卡驱动和CH2板卡驱动
  4. CAN卡驱动(PEAK的pcan驱动和FINTEK的f81601a驱动),如果你没有用这两种CAN卡可直接忽略

安装过程中请按照脚本提示对系统进行重启,最终输出"host_install ok!"代表脚本运行成功。

如果服务器插了CH2板卡,如果ls /dev/xdma*可以看到相关设备则代表CH2板卡驱动安装成功。

如果服务器插了Nvidia显卡,运行nvtop可以看到GPU信息代表显卡驱动安装成功。

如果服务器插了PEAK或者FINTEK的CAN卡,运行ip link show可以看到can0/can1/can2/can3这样的socketcan设备,则代表can卡驱动安装成功。

部署SDK

在config.sh中可以对SDK参数进行配置,每次修改完config.sh之后,必须运行一次./host_deploy.sh重启服务。

可以看到SDK包含了video.service、hdmi.service、can.service和timesync.service这4个服务:

  • video.service:常驻后台服务,video.service通过共享内存接受来自ue4中渲染好的图像,然后再走PCIe传到CH2板卡中
  • can.service:常驻后台服务,负责管理socketcan接口
  • can.service:常驻后台服务,负责管理socketcan接口
  • timesync.service:常驻后台服务,负责管理域控和服务器的时间同步,自带基于clockdiff和ptp两种时间同步方法

在config.sh中,配置core核心参数部分:

  • HOST_USER:操作系统非root普通用户名
  • ENABLE_SERVICES:这里必选video或hdmi,can和timesync服务可以不选
  • HIL_TS_SRC:回灌数据的时候可能需要给注入udp数据(比如lidar点云)打上时间戳,这就需要把域控制器和HIL-Sim台架服务器时间进行同步,然后通过hil_api.h的hil_ts_get()接口获取当前HIL_TS_SRC指定的同步时间源
    • CLOCK_REALTIME:HIL_TS_SRC就是当前系统时间,即运行date命令输出的这个时间
    • clockdiff:需要在config.sh中的timesync.service服务中配置DUT_HOST_SYNC=clockdiff,通过chronyd测量HOST服务器和DUT(DeviceUnderTest)域控的系统时间差clockdiff,来间接获取DUT的系统时间
    • /dev/ptp0:HOST网卡时间,也就是运行sudo phc_ctl /dev/ptp0 get输出的这个时间。一般用法是基于ptp协议把DUT域控时间同步到HOST网卡上,在config.sh的timesync.serivce中配置DUT_HOST_SYNC=ptp可以自动把域控时间同步到HOST的LAN口网卡上
  • REPLAY_OR_SIM: 这里Sim模式为1
  • BIND_CPU: 在大负载的情况下,用lscpu.txt配置文件对关键进程绑定到固定CPU核心上,优化性能
  • VIDEO_PERIOD:camera每帧时间周期,单位us

在config.sh中,配置carla参数部分:

  • MASTER_TICK_US:配置carla的master节点仿真步长,根据经验5ms(200Hz)已经可以满足车辆动力学需求了,更小的值对服务器配置要求更高
  • NODE_SLAVES:以json字符串方式配置carla的slave节点,NODE_NAME为slave节点名,SLAVE_TICK_US为slave节点仿真步长(FSYNC代表仿真步长和fsync-trigger步长一致)。GPU_BUS_ID: lsgpu.txt中有每块显卡的BUS_ID,每个carla的slave节点都必须绑定一张显卡,这是必选参数。HDMI_MODE_ID:这个参数指定slave节点渲染后的图像是否往某个显示器模式输出,lsgpu.txt中列出了每块显卡最多4个显示器的所有可用模式,这是可选参数。

在config.sh中,配置video.service参数部分:

  • VIDEO_MISS_1000:为了让渲染每帧图像delay更短,渲染每帧的时间通常小于33.333ms(这里假设为20ms左右),那么我们可以把渲染开始时机延迟10ms,这样相当于总渲染时间为30ms左右依然在规定时间内完成,但是也更容易超时。这里我们设置每1000帧允许几帧超时(取值范围[1, 100]),这个值越大,渲染实时性越强。
  • VIDEO_FSYNC_USE:VIDEO_FSYNC_USE=0的时候,不使用域控DUT的fsync-trigger信号,而是每隔VIDEO_PERIOD时间构造一次假的fsync-trigger信号;VIDEO_FSYNC_USE=1的时候,图像会等待域控的frame-sync/frame-trigger信号到达后才注入
  • VIDEO_FSYNC_IDX:从域控的哪一路camera获取frame-sync/frame-trigger信号
  • 12路视频每两路一组总共分成六组:0到1为一组、2到3为一组、4到5为一组、6到7为一组、8到9为一组、10到11为一组,每组的分辨率和图像格式必须相同
  • VIDEO_*_SIZE_H:头嵌入行数+图像本体行数+尾嵌入行数
  • VIDEO_*_SIZE_W:图像宽度
  • VIDEO_*_NAME:相机名字,方便在decode_video_app针对不同的相机进行不同处理
  • VIDEO_*_PATH:回放视频h264/h265文件

在config.sh中,hdmi.service参数部分配置UE4实例渲染好的图像往显卡HDMI口显示器输出,如果渲染图像分辨率和显示器分辨率不匹配,那么图像会被缩放适应显示器分辨率。

  • HDMI_A="02:0_11" :这里的格式为(一般每张显卡最多可以插4个显示器):GPU_BUS_ID:HDMI_MODE_ID,HDMI_MODE_ID,HDMI_MODE_ID,HDMI_MODE_ID

hdmi.service刚启动成功绑定显示器之后(此时UE4实例还没渲染图像输出),默认会显示白色屏幕且在中央输出GPU_BUS_ID:HDMI_MODE_ID,如下图: img_v3_0215j_3f509b82-541b-4022-aef2-fd608e4b445g.jpg

在config.sh中,can.service参数部分配置CHR台架自带的CAN卡(你可以在ENABLE_SERVICES环境变量中删除这个服务):

  • CAN_DRIVER:PEAK对应pcan,FINTEK对应f81601a
  • CAN_*:配置socketcan名称和是否为canfd

在config.sh中,timesync.service参数部分配置CHR台架自带的clockdiff和ptp的两种同步机制(你可以在ENABLE_SERVICES环境变量中删除这个服务):

  • HOST_*:这部分配置是为了让DUT域控能通过HOST的WAN口上外网
  • DUT_HOST_SYNC:选择clockdiff会在DUT域控的dut.service服务中启动chronyd服务器端,timesync.service会运行chronyd客户端去测量和DUT域控系统时间的差clockdiff,然后保存到/dev/shm/HOST_clockdiff_DUT共享内存中,从而间接获取DUT系统时间;选择ptp会在DUT域控的dut.service运行ptp4l服务端,HOST主机通过ptp4l把时间到本地网卡HOST_LAN中
  • timesync这个服务假设DUT域控是aarch64的linux操作系统,所以不支持QNX系统。修改完config.sh中timesync相关参数后,需要运行./dut_deploy.sh,该脚本会把dut_deploy目录下的dut.service服务部署的DUT域控中,域控开机自启动服务运行dut.sh

运行测试

在命令行输入c回车快捷进入hil_sim_sdk目录,然后运行./sim.sh开始一次默认参数的测试。sim.sh支持以下参数:

  1. CASE:运行测试用例名,默认CPLA这个测试用例,对应test_case/cncap/CPLA.json中定义的4个子testcase,也可以这样CASE=CPLA.50kmh ./sim.sh来只运行某个子testcase,或者CASE=MAP0_CASE1,MAP0_CASE2 ./sim.sh这样运行多个地图相同的testcase
  2. RECORD:默认通过ffmpeg录制屏幕方便事后查看,默认使能
  3. CAR:指定车辆模型名称,你需要针对你的实车创建自己的车辆模型
  4. EDITOR:是否启动UE4的EDITOR(Spectator)调试界面,在EDITOR=1模式下只会启动一个运行在同步模式下的carla的UE4节点。当EDITOR=2的时候,调试界面会额外画出debug用的信息(比如传感器外参、地图坐标)

sim.sh会先把carla的master和所有slave节点都拉起来,slaves节点在config.sh中的NODE_SLAVES变量处定义,每个UE4节点都会消耗内存/CPU/显卡,所以配置较低的开发环境不要定义太多slaves节点。每个slave节点必须定义NODE_NAME用于区分该节点,SLAVE_TICK_US代表该节点每多少us渲染一帧(如果值是FSYNC则以fsync-trigger为准)。生产环境务必把BIND_CPU=1,然后在lscpu.txt和lsgpu.txt中把每个节点都进行绑定。

carla节点都拉起来后,才会把GUI(client.py)拉起来,GUI可以显示自车状态和传感器信息如下图。 image-nHyJ.png

GUI可以通过键盘进行控制,方法如下:

    W/S          : throttle/brake (keep)
    Up/Down      : throttle/brake
    A/D          : steer left/right (keep)
    Left/Right   : steer left/right
    0-9          : user defined callbacks
    R            : reverse drive toggle
    H            : hand brake toggle
    C            : camera show next (Shift+C reverse)
    L            : lidar show next (Shift+L reverse)
    TAB          : change screen
    E            : exit CASE_DRIVE
    T            : toggle DUT_DRIVE button(teleport specator in editor mode)
    P            : pause case
    N            : next case
    ESC          : quit

在GUI的左边状态栏有一个Driver字段,代表当前自车是MAN_DRIVE、CASE_DRIVE还是DUT_DRIVE。MAN_DRIVE代表我们用键盘控车,适合模拟手动开车调试的情况。CASE_DRIVE代表测试用例中通过carla的api或traffic manager来控车,一般用域控制器激活自动驾驶前的过渡阶段。DUT_DRIVE代表当前自车是由DUT(DeviceUnderTest)域控制器控制,默认通过T按键激活一个SDK自带的只会往前开的fake-DUT模式,用户需要自行适配为激活真实的DUT域控制器。在CPLA这个测试用例中,首先在车前方生成了一个行走的NPC行人,然后自车先进行CASE_DRIVE状态(由carla的traffic manager控制往前开)。然后自动按下键盘T按键往fake-DUT发送激活智驾can消息toggle_DUT_DRIVE,然后检查fake-DUT发送来的控制can消息is_DUT_DRIVE,确定进入DUT_DRIVE的智驾模式。由于fake-DUT只会往前开在撞到行人之后,CollisionChecker检测到碰撞后判断测试失败退出。

在camera_sensors.py中可以对camera模型和内外参进行配置,其它lidar/gnss/imu/collision传感器的配置不再赘述。

can.service服务(can_server.py)常驻后台负责收发can信号,client.py中实例化can客户端(can_client.py)和can_server.py基于共享内存通信。在fake_dut_drive.py中有通过can客户端向fake-DUT域控发送激活智驾can消息toggle_DUT_DRIVE,以及接收fake-DUT域控发出的控车can消息DUT_DRIVE。

在闭环HIL-Sim中,仿真延迟尤其是camera链路的延迟对于仿真测试的准确性至关重要。卡朗仿真科技针对camera链路延迟做了大量的研究和优化,果断采用PCIe摒弃HDMI板卡方案,原因见:HIL视频注入走PCIe还是HDMI。通过命令行运行./monitor可以查看当前视频链路延迟情况,可以看到下图中我们渲染的针孔模型和fisheye模型的camera注入链路只比实车慢10到30ms左右,正是因为我们软硬件一体化方案才能优化出业界领先的camera延迟。如果您希望camera链路延时更低且能容忍更多帧超时(没赶上fsync-trigger的超时情况,我们会默认发送渲染的上一帧图像),把VIDEO_MISS_1000这个参数调高即可。

image-SBgm.png

testcase开发

test_case子目录下的框架是非常轻量级的python测试框架,可以直接访问carla原生api和GUI主线程(client.py)变量。testcase中不使用任何阻塞函数,而是定义run_callback回调函数或者run_yield生成器回调,GUI主线程会定期调用之。

这里以CPLA这个cncap标准中的基础测试为例,在test_case/cncap/CPLA.json中定义了如下参数:

  1. _map:定义这个testcase对应地图,这里对应Town01_Opt这个地图
  2. _class:定义了testcase对应的python文件,这里对应CPLA.py
  3. _case:定义每个子case
  4. 其他不带下划线的参数由用户自行定义使用

现在来看test_case/cncap/CPLA.py这个文件:

#!/usr/bin/env python3.8
from test_case_utils import *

class EgoController(EgocarController):
    def __init__(self, base_case):
        super().__init__(base_case)
        
    def run_yield(self):
        self.test_case.case_drive_acquire()
        ego_car = self.test_case.client._EGO_CAR_ACTOR
        speed = self.test_case.get_config('speed')
        self.test_case._TM.set_desired_speed(ego_car, speed)

        yield from self._yield_sleep(5)
        yield from self.yield_toggle_dut_drive()
        while True:
            self.check_reach(target_loc=self.test_case.reach_loc)
            yield

class PedController(YieldCallback):
    def __init__(self, base_case):
        super().__init__(base_case)

    def run_yield(self):
        direction = carla.Vector3D(1, 0, 0)
        direction_unit = direction.make_unit_vector()
        
        go_straight = carla.WalkerControl(direction=direction_unit, speed=5/3.6) # 5km/h
        self.test_case.ped.apply_control(go_straight)
        yield

class CPLA(TestCase):

    def case_start(self):

        player_spawn_point = self.client._SPAWN_POINTS[46]
        self.client._EGO_CAR_ACTOR.set_transform(player_spawn_point)
        self.reach_loc = self.client._SPAWN_POINTS[46].location + carla.Location(x=210, y=0, z=0)

        pedestrian = self.get_config('pedestrian')
        blueprint = self.client._CARLA_WORLD.get_blueprint_library().find(pedestrian)
        blueprint.set_attribute('is_invincible', 'false')
        sp91 = self.client._SPAWN_POINTS[91]
        ped_spawn_point = carla.Transform(sp91.location, sp91.rotation)
        ped_spawn_point.location.y +=0.5 # 1/4 car width
        self.ped = self.client._CARLA_WORLD.spawn_actor(blueprint, ped_spawn_point)

        self._YIELD_CALLBACKS['ego'] = EgoController(self)
        self._YIELD_CALLBACKS['ped'] = PedController(self)

入口CPLA类必须继承TestCase基类,GUI主线程(client.py)加载TestCase的时候,会以下面的顺序来运行:

self._before_case_start()
self.case_start()
self._after_case_start()
self._case_run()
self._case_destroy()

用户需要覆盖case_start类方法,在这里完成自车和NPC初始化。所有需要定期调用的逻辑都需要直接或间接继承YieldCallback基类,如果需要普通回调则定义run_callback类方法,如果需要yield回调则定义run_yield类方法。YieldCallback基类的_PERIOD_MS可以定义回调周期(最小10ms),_ENABLED可禁用此回调,_RESULT_INFO可用于保存信息。这里为了控制自车和行人定义了EgoController(EgocarController)和PedController(YieldCallback),对应实例需要放在self._YIELD_CALLBACKS字典中。

在run_yield函数中,用户需要牢记在任何循环中必须yield返回,否则会陷入死循环卡死逻辑。在run_callback/run_yield逻辑中,用户可以控制自车、控制行人、收集参数以及判断测试用例是否需要退出。调用case_exit(self, exit_code, exit_msg, exit_delay=10)类方法可退出测试用例,exit_code值定义如下:

ExitCodeMAP = {
        0: "PASS",
        1: "FAIL",
        2: "WARN",
        3: "SIM_ERROR",
        4: "SIM_DEBUG",
    }

在EgocarController(YieldCallback)中有一些控制自车的常用辅助函数,TestCase自带了4个默认YieldCallback:

self._YIELD_CALLBACKS['timeout'] = TimeoutChecker(self)
self._YIELD_CALLBACKS['collision'] = CollisionChecker(self)
self._YIELD_CALLBACKS['crosslane'] = CrosslaneChecker(self)
self._YIELD_CALLBACKS['metric'] = MetricCollector(self)

如果不想使用,可以像self._YIELD_CALLBACKS['timeout']._ENABLED = False这样禁用掉。

车辆动力学

本SDK提供一种基于查找表的车辆动力学方法,实现输入车速v和加速度a,输出刹车brake或者油门throttle大小。这里用到了carla的AdditionalMaps,先去这里下载额外地图:https://github.com/carla-simulator/carla/releases/tag/0.9.16 ,然后参考官方文档导入额外地图:https://carla.readthedocs.io/en/0.9.16/core_map/#additional-maps

车辆3D模型

需要实车的长、宽、轴距、轮距、车轮半径这几个信息,基于carla模板生成一个简单虚拟车辆3D模型,这里暂定模型名字为my_car。具体见官方文档:https://carla.readthedocs.io/en/0.9.16/tuto_content_authoring_vehicles/

您也可以直接基于AI来修改Carla中现有的车辆模型,这样更加简单快捷,参考文档:https://caronsim.com/archives/yong-aizai-carlazhong-sheng-cheng-che-liang-3dmo-xing

方向盘标定

需要实车方向盘转角到车轮标定数据,车轮大小和前轮最大转角,并且在EgoCar._modify_physx中更新my_car这个车辆模型的wheel_radius和wheel_max_degree。 运行CAR=my_car CASE=calib.steer EDITOR=1 ./sim.sh这个测试用例,用例会自动在虚拟场景中获取方向盘转角和右前车轮转角的对应关系,如下图:

image-LKle.png

这样DUT域控制器发出dut_steer方向盘转角信号,首先转换为FRWheel右前轮转角,然后用EgoCar.FRWheel_to_steer方法就能转换为carla中my_car车辆模型的steer方向盘转角了。

刹车油门标定

运行CAR=my_car CASE=calib.throttle_brake_forward,calib.throttle_brake_reverse EDITOR=1 ./sim.sh这个两个测试用例,用例会遍历自车往前开或往后开的任意速度v的时候,要得到加速度a,需要给的刹车brake或油门throttle的值。运行完毕之后,可以看到往前开和往后开的两张非常漂亮的查找表。默认跑一次需要半天时间,你可以把calib.py中的SAMPLE_STEP从0.01改到0.05来加速,只是得到的查找表精度低一些。遍历结果保存在test_case/demo/calib目录下,支持中途打断后继续遍历运行。

image-cqgc.png image-GtuP.png

对于DUT域控制器发出加速度a请求,只需要根据当前自车车速v,去EgoCar.v_a_to_throttle_brake就能根据查找表获取刹车brake或油门throttle的值。

由于这个查找表是在平地上测得的,对于坡道上自车存在往下坡方向重力分力的情况,sdk默认会给自车施加一个上坡的反作用力进行抵消,这样受力分析就和平地上一样了。具体见DriveControl.compensate_slope,你还可以运行:EDITOR=2 ./sim.sh来查看坡道情况下的受力补偿。

源码编译

hil_api二次开发

hil_api头文件路径:hil_sim_sdk/api/hil_api.h,主要用来对camera图像注入格式调整,使用的时候继承HIL_SIM_APP类,覆盖nv12_convert类方法,这里自行修改图像嵌入行信息和图像格式转换。

carla源码编译

请首先按照carla官方文档在ubuntu22.04上编译打包carla0.9.16版本:https://carla.readthedocs.io/en/0.9.16/build_linux/ 然后通过git remote add caronsim https://gitcode.com/caronsim/carla添加caronsim的仓库,然后git fetch caronsim && git checkout caronsim就是我们的开发分支,您可以在此基础上做lidar/radar/gnss/imu等传感器的二次开发,或者新建您自己的地图或3D素材。在carla源码的carla_ue4_dev/caronsim目录下是一些方便编译打包的脚本,在env.sh这里更新环境变量,make_package.sh脚本可以从源码编译打包二进制,make_binary.sh脚本只编译二进制速度更快。

地图开发

在比较简单的场景中,我们可以直接复用carla中自带的地图,这里以Town06_Opt这个地图举例。Town06_Opt是一个直道很长的简单地图,我们在现实真实地图中找一个道路为东西南北走向的地方,然后把此地的GPS坐标点写到Content/Carla/Maps/OpenDrive/Town06_Opt.xodr文件中,如下图:

test.jpg

这样自车的GNSS传感器坐标就成了现实中的坐标点了,由于各家用的地图供应商不一样,需要自行处理地图加偏问题。

各主机厂可能还有内部HDMAP地图(比如NDS格式),我们可以把HDMAP转换为carla地图来得到一张和现实道路完全符合的仿真地图。卡朗仿真科技已经打通了先基于HDMAP的SDK转换为roadrunner的rrhd地图格式,然后在roadrunner中打开对地图进行细节修改,最后基于carla官方文档的办法导入carla。

把HDMAP地图转换为rrhd地图格式可以利用roadrunner的官方SDK,见:rrhd.pdf

转换后的rrhd地图是非常粗糙的,地图可能有断裂、穿模、人行道缺失等情况,需要在roadrunner中做修复。此外,matlab官方也有一些roadrunner地图相关skill可以辅助AI自动化,见:https://github.com/matlab/matlab-agentic-toolkit/blob/main/skills-catalog/README.md#automotive-automotive