华为云用户手册

  • 执行顺序(Execution sequence) OSC2.0场景剧本StoryBoard通过执行顺序Execution Sequence和触发器Trigger来支持用户设计各种场景。StoryBoard中有parallel和serial两种执行指令,最外层执行指令之前需要加上do来使场景剧本生效。其中: parallel:同步执行下方代码块内的动作action。 serial:依次执行下方代码块内的动作act。 例如下方样例中,do parallel:下的assign_init_speed,assign_init_position和wait elapsed(10s) 是同步执行的。而serial:下的lead_vehicle.change_speed在Ego.activate_controller完成之后执行。 由于初始动作InitAction内的action同步执行,且InitAction与story之间不涉及顺序执行,建议场景最外层统一使用parallel。 样例 m_profile: dynamics_shape = linear do parallel: # InitAction Ego.assign_init_speed(15mps) Ego.assign_init_position(position: Ego_InitPosition) # Story serial: # act1 Ego.activate_controller(true, true) lead_vehicle.change_speed(target: 20mps, rate_profile: m_profile, rate_peak: 0.3mpss) serial: # act2 wait elapsed(10s) lead_vehicle.activate_controller(true, true)
  • 绘制对象 绘制多边形。 选择左侧工具栏多边形按钮,(快捷键4,非小键盘)绘制多边形。 图2 绘制多边形 选择标注。 标注列表页选择符合的标注。 图3 选择标注 绘制标注形状。 绘制标注形状有两种方法:点式绘制和交互式分割工具,用户可根据需要选择绘制方式 点式绘制形状:通过单击目标对象的边缘,点状连线,获得闭合的多边形,操作如下: 通过鼠标左键单击添加点标注图中对象,未闭合状态可通过“alt+Z”撤销上一步绘制的点,标注过程中可通过“alt+鼠标左键”拖动图片。按住键盘上空格键进行闭合,该对象标注完成。 项目类型为语义标注、道路特征提取、可行驶区域,这三类任务是空格键闭合且alt+鼠标左键拖动图片,其余任务使用左键拖动图片和闭合多边形。 交互式分割工具(仅在“语义标注”项目中使用):通过在标注对象及附近区域单击正点(目标对象区域的点)或负点(非目标对象区域的点), 自动得到较优的多边形。具体步骤如下: 单击快捷键“4,非小键盘”,进入多边形绘制状态。 单击快捷键“z”键进入目标对象的交互式标注模式, 页面右上角出现“交互式分割已开启”字样。 在前景区域,通过鼠标左键单击正点(目标对象区域的点),得到预测的多边形。 在背景区域,通过鼠标左键单击负点(非目标对象区域的点),修正多边形。在多边形区域未包含的前景区域左键单击正点,修正多边形。 重复单击正或负点,修正预测的多边形,直到多边形达到较好的效果。 一般情况下,单击3-5个点即可达到较好效果,如果超过10个点还未达到较好效果,则此对象的此次交互式标注基本无效,建议退出。 再次单击快捷键“z”键,可退出目标对象的交互式标注模式, 页面右上角“交互式分割已开启”字样消失。该对象标注完成。 切割线工具修改多边形。 单击左侧标注工具栏切割线(快捷键8,非小键盘),切割线空格键闭合,切割线绘制完成通过键盘上“m”键可完成切割。 切割线可用于切割多边形不贴合部分,切割线首尾两点与多边形需有交点。 其他常用标注工具。 绘制共边对象:通过键盘上“X”键实现两对象共边。 全局标注:选中一标注对象,单击左侧工具栏“全局标注物”按钮,或通过键盘快捷键“i”复制该对象到图层中,选中该对象可应用到本图或者下一张图中。该步骤可用于有相同对象的图片,或者有覆盖类型的标注中。 图4 全局标注 删除对象:选中一对象,通过键盘上“delete”键可在图中删除该对象。 撤回上一步:单击左侧工具栏“撤回”,或通过快捷键“shift+z”撤回上一步。 隐藏标注列表和预览图:单击左侧工具栏“隐藏标注列表”、“隐藏预览”,扩大标注区域。 调整透明度:单击左侧工具栏“调整透明度”,调整图片。 更改标注类别 多边形闭合后可在该对象上单击鼠标右键,更改该对象类别。 图5 更改标注类别 修改额外属性。 右键单击目标图形,如果目标含有额外属性,如果其默认属性错误,单击即可选择属性。 修改对象ID。 右键单击目标图形,可以在对象ID栏手动输入数值来修改ID。
  • 跟车起停(Stop and Go)检测 跟车起停检测的目的是判断主车跟随前车停车后能否在前车启动后重新启动。 当主车跟随前车制动停止后, 前车重新启动后, 主车重新启动的时间要合适, 该时间允许用户自定义, 本设计默认取3s。 当重新启动时间大于指定阈值时, 则跟车起停检测不通过。 该指标关联的内置可视化时间序列数据为:暂无。 该指标的异常时间点记录类型为:POINT_TYPE_REGION。 父主题: 内置评测指标说明
  • split 简述:地图场景为匝道分流。lead_vehicle和主车Ego在主道的同一车道上分别以35kph和Ego_InitSpeed_Ve0的初始速度一前一后行驶,Ego设定了目标在匝道上的目标点Target_position,仿真开始后激活Ego控制器(控制器会影响Ego去往Target_position的寻路算法,但目前仿真器B尚不支持寻路动作acquire_position)。控制器有时会根据lead_vehicle的位置更改主车Ego的速度。 使用xyz坐标创建终点时,由于匝道地图泛化会使终点偏移,建议在创建测评任务时为检测终点设置合适的半径,例如"到达半径5m"。 地图文件(odr) scenario Split: m_scene: scenery lane_width: length = [3m..4m] main_speed: speed = 120kph ramp_speed: speed = 60kph ramp_length: length = [300m..350m] road_aids_type: road_aids_type = "DType-2" split_1: split with: keep(it.lane_width == lane_width) keep(it.left_lane_num == 0) keep(it.right_lane_num == 3) keep(it.ramp_lane_num == 1) keep(it.main_speed == main_speed) keep(it.ramp_speed == ramp_speed) keep(it.radius_of_curvature == 200m) keep(it.ramp_length == ramp_length) keep(it.road_aids_type == road_aids_type) 场景文件(osc) import standard scenario Split: # map map: map map.set_map_file("./split.odr") # parameter Ego_InitSpeed_Ve0: speed = [90kph..110kph] Ego_InitPosition_LaneId: string = ['-1', '-2'] Ego_InitPosition_s: length = [0m..100m] Ego_Odr: odr_point = map.create_odr_point(road_id: '10', lane_id: Ego_InitPosition_LaneId, s: Ego_InitPosition_s, t: 0.0m) Ego_InitPosition: pose_3d with: keep(it.odr_point == Ego_Odr) m_InitDistance: length = [60m..100m] Target_xyz: xyz_point = map.create_xyz_point(x: 445m, y: -46.5m ,z: 0.0m) Target_position: pose_3d with: keep(it.xyz_point == Target_xyz) Duration: time = 100s # entity Ego: vehicle with: keep(it.name == "Saimo") keep(it.initial_bm == "默认驾驶员") lead_vehicle: vehicle with: keep(it.name == "Saimo") keep(it.initial_bm == "默认驾驶员") # storyboard do parallel(duration: Duration): # init Ego.assign_init_position(position: Ego_InitPosition) Ego.assign_init_speed(Ego_InitSpeed_Ve0) lead_vehicle.assign_init_position() with: lane(same_as: Ego) position(distance: m_InitDistance, ahead_of: Ego) lead_vehicle.assign_init_speed(35kph) Ego.activate_controller(true, true) Ego.acquire_position(target: Target_position) 父主题: 种子地图的逻辑场景样例(仿真器B)
  • 注册华为账号 并开通华为云 在使用华为云服务之前您需要申请华为云账号并进行实名认证。通过此账号,您可以使用所有华为云服务,并且只需为您所使用的服务付费。 如果您已有一个华为云账号,请跳到下一个任务。如果您还没有华为云账号,请参考以下步骤创建。 打开华为云官网,单击“注册”。 根据提示信息完成注册,详细操作请参见注册华为账号并开通华为云。 注册成功后,系统会自动跳转至您的个人信息界面。 参考实名认证完成个人或企业账号实名认证。 父主题: 准备工作
  • OCTOPUS格式文件基本要求(文本标注) 上传的OCTOPUS格式数据集需包含以下文件(以txt格式为例)。文本文件支持的格式包含:txt、yaml、xml、csv。 . ├─ 文件夹1 ├─ text1.txt #文本文件 ├─ text1.json #该文本文件的所有标注信息 ├─ 文件夹2 ├─ text2.txt #文本文件 ├─ text2.json #该文本文件的所有标注信息
  • 标注数据.json文件说明 数据集中必含“.json”文件,用于集合该文本文件的所有标注数据信息,包括该文本所在的项目id、数据包id、文本上所有标注信息等。上传数据集前请保证“.json”文件内容正确。“.json”文件编写的参考样例如下: { "frame_id": 1, #帧序号 "batch_task_id": 1368, #批次任务id "project_id": "ee263479089143cf9d8ca66a10ed3c3d", #资源域ID "label_mode": "manual", #标注类型:auto和manual两种 "status": "labeled", #标注任务状态:unlabeled、labeled、unconfirmed、confirmed、all五种 "sample_type": "TEXT", #样本类型:包含“IMAGE”,“POINT_CLOUD”,“AUDIO”,“TEXT” "des_order": "", #此份数据对应的原始数据包描述 "tag_names": [], #标签名称 "valid": true, #是否有效,包含“true”和“false”两种 "create_time": 1708657733087, #标注的创建时间 "difficult": false, #是否难例,包含“true”难例和“false”非难例 "label_counts": [ #各类标注物的个数统计 { "label_meta_id": 7900, #标注物使用的标签ID "label_num": 1, #标注物个数 "label_meta_name": "人物", #标注物名称 "label_meta_desc": "1233", #标注物描述 "label_meta_attr": "{\"男\":\"少年,青年\",\"女\":\"少年,青年\"}", #标注物额外属性 "label_meta_shape": "text", #标注物形状,包含“bndbox、line、circle、polygon、points、dashed、cube_3d、multiBox、polygon_3d_v2、audio、text” "label_meta_color": "#496832", #标注物颜色信息 "level": 0 }, { "label_meta_id": 7901, "label_num": 1, "label_meta_name": "水果", "label_meta_desc": "11", "label_meta_attr": "{\"颜色\":\红,黄\"}", "label_meta_shape": "text", "label_meta_color": "#391c1c", "level": 0 } ], "text_meta_info": { #文本信息 "id": "4951cbcb-57ea-4367-b0e2-56b77a18e9bd", "name": "0000.txt", #文本名称 "source": "https://octopus-raw-ee263479089143cf9d8ca66a10ed3c3d.obs.cn-north-5.myhuaweicloud.com/label-data/task-1368/data/txt/0000.txt" #音频源的obs路径url }, "label_task_id": 1691, #批次子任务ID "partitionId": 20240222, "label_update_time": 1708944569975, #标注最近更新时间 "prefix_folder": "txt", "image_id": "889b33fa-8c43-4760-a215-14d299af4291", "inspection": 0, "labels": [ { "label_meta_id": 7900, #标注物对应的标签ID "create_time": 0, "shape_type": "text", #标注物形状 "serial_number": 1, #该帧中标注物唯一自增id "label_object_id": -1, "attribute": "{\"人物\":\"男\"}", #标注物属性 "text": { #文本标注信息 "start_idx": 1, #标注起始偏移量 "end_idx": 3 #标注结束偏移量 }, "label_meta_name": "人物" #标注物名称 } ] }
  • 背景 Octopus内置一套评测算法,用于对自动驾驶系统的性能表现进行多维度评测。内置评测算法的评测结果按照eva.proto中的定义,序列化成pb文件保存起来。 Octopus仿真平台的前端通过解析评测pb对评测结果进行展示,目前控制台展示主要分为两大方面: 各个评测指标的通过/未通过/无效的结果展示。 仿真过程中关键数据的时间序列曲线图展示。 另外,对于用户自研的评测算法的评测结果,也可以按照eva.proto,序列化成pb文件保存起来,这样Octopus的仿真平台前端能够展示用户自研评测算法的评测结果。
  • eva.proto的关键字段解释 在利用Octopus仿真平台进行批量仿真时,每个场景都会有一个评测结果,单个场景的评测结果全部保存在如数据类图所示的Evaluation类中。 Evaluation类包含以下的7个字段。 表1 Evaluation类包含的字段 字段 说明 version 用于表示当前Octopus_eva.proto的版本。 score 用户保存批量仿真中单个场景下评测算法计算出的评测得分,Octopus的评分取值为[0, 100]。 avg_speed 单个场景下自动驾驶算法控制下主车的平均车速,单位m/s。 distance 单个场景下自动驾驶算法控制下主车的行驶里程,单位m。 vis 主车关键状态量的(如速度、加速度)的时间序列数据,用于前端进行可视化曲线展示。 metrics Octopus内置了一批大类评测指标,并且每个大类评测指标下会多个子类指标。 该字段用于保存每个大类和子类评测指标的通过/未通过/无效的结果状态。 其中无效状态表示该指标在特定场景下是没意义的,如在没有交通灯的场景下,主车在交通灯前的行为检测是没有意义的。 source 是一个Source枚举类型,表示该评测算法的结果来源类型。 source共有6种类型,具体参考source。 表2 source 字段 说明 SOURCE_UNSPECIFIED 表示评测算法类型未定义。 SOURCE_CUSTOMIZED_REALTIME 用户自定义实时评测算法结果。 SOURCE_CUSTOMIZED_OFFLINE 用户自定义延时评测算法结果。 SOURCE_DEFAULT_REALTIME 八爪鱼内置实时评测算法结果。 SOURCE_DEFAULT_OFFLINE 八爪鱼内置延时评测结果。 SOURCE_MERGED 融合后的评测结果。 Evaluation中两个比较关键且复杂的字段是vis和metrics,其中vis字段类型是Visualization,metrics字段的类型是repeated Metric。 Visualization和Metric的成员组成如上数据类图所示,各个关键成员的含义如下所示。 Visualization类型包含的各个字段及其含义如下所示。 表3 Visualization类型字段 字段 说明 sim_times 仿真过程的时间序列点,以仿真开始时刻(t0)为0点,相邻时刻的时间间隔为仿真器的周期,单位为秒(s)。 frame_nums 每个仿真时刻对应的数据帧数,表明这是第几帧的数据。 stats 统计类型的数据值,是指某数据在一段时间内统计值才有展示分析的意义,如加速度均方根值(arms),随着仿真时刻不断后移,需要不断计算初始时刻(t0)到当前仿真时刻(t)的arms值。 stats字段的类型是Statistic,Statistic类型的成员具体参考stats。 vector 向量类型的数据值,是指每个时刻都会有一个对应的数据值,如加速度、速度等物理量。 vector字段的类型是Vector,Vector类型的成员具体参考vector。 表4 stats 字段 说明 type 是一个Type的枚举类型,表示该数据是哪种Octopus内置的Statistic类型。 value 该数据在每个仿真时刻对应的数值。 display_name 存储用户自定义的Statistic类型名称,用户自定义的数据无需对type赋值。 source 表示该数据的评测结果来源类型。 importance 表示该数据是重要类型还是次要类型。 module 表示该数据是来源于哪个算法模块。 performance 表示该数据是表示的哪个类别的算法性能。 表5 vector 字段 说明 type 是一个Type的枚举类型,表示该数据是哪种Octopus内置的Vector类型。 value 该数据在每个仿真时刻对应的数值。 display_name 存储用户自定义的Vector类型名称,用户自定义的数据无需对type赋值。 source 表示该数据的评测结果来源类型。 importance 表示该数据是重要类型还是次要类型。 module 表示该数据是来源于哪个算法模块。 performance 表示该数据是表示的哪个类别的算法性能。 Metric类型包含的各个字段及其含义如下所示。 表6 Metric类型字段 字段 说明 type 是一个Enum类型,表示该数据是哪种Octopus内置的大类指标类型。 status 是一个Result的枚举类型,用于表示该大类指标的评测结果。 其中Result有三种类型,分别为: RESULT_UNSPECIFIED:该状态的结果表示评测指标是无效的,如对于红绿灯检测指标,如果仿真完成后评测函数发现场景中不存在红绿灯,则该项指标的评测是没有意义的,故评测结果展示为无效。 RESULT_PASSED: 该状态的结果表示评测结果为通过。 RESULT_FAILED:该状态的结果表示评测结果为未通过。 anomalies 用于保存每个大类指标下对应的子类指标发生异常的时间点,其数据类型为repeated Anomaly,其中Anomaly类型成员如下所示: status: 是一个Result类型,与上述大类指标的status的表示相同,该字段用于存储子类指标的三种不同状态结果。 subtype:是一个Subtype的枚举类型,表示该子类指标是哪种Octopus内置的子类指标类型。 其中,对于某些没有子类指标的大类指标来说,其subtype赋值为SUBTYPE_UNSPECIFIED。 point_type:是一个PointType的枚举类型,表示该子类指标发生特殊状态(一般是指发生异常)时的时刻点用哪种形式存储起来。 其中PointType共有5种类型,参考PointType。 Points:是repeated float类型,保存每个子类指标发生特殊状态的具体时间点的值。 Stats_indices:是repeated ui32类型,表示该子指标关联的统计类数值列表。 Vector_indices:是repeated ui32类型,表示该子指标关联的时间序列数值列表。 display_name 存储用户自定义的Anomaly类型名称,表示其自定义的子类指标,用户自定义的数据无需对sub_type赋值。 importance 表示该指标的重要程度。具体参考importance。 source 表示该数据的评测结果来源类型。 module 表示该数据是来源于哪个算法模块。具体参考module。 performance 表示该数据是表示的哪个类别的算法性能。具体参考performance。 表7 PointType 字段 说明 POINT_TYPE_UNSPECIFIED 未定义的类型,遵循proto定义格式,Octopus未使用该类型,用户可根据需要对该类型赋予特定含义。 POINT_TYPE_POINT 表示该子类指标的异常时间点是离散的时间点形式,在任何时刻都可能发生异常。 POINT_TYPE_REGION 表示该子类指标的异常时间点是区间形式,一旦在某个时刻开始发生异常,则在随后一段时间内都会处于异常状态。 POINT_TYPE_ALL 表示该类指标的异常时间点是布尔形式的,从仿真开始到当前时刻的状态要么是完全通过,要么全过程都是异常的,统计类型的指标需要以这种形式表示。 POINT_TYPE_NORMAL 该类型与其他类型相反,如果该类型的点存在,则表示对应的子类指标是通过的,Octopus用该类型保存主车到达终点的时间值。 表8 importance 字段 取值 说明 CATEGORY_UNSPECIFIED 0 未定义 CATEGORY_MAJOR 1 主要 CATEGORY_MINOR 2 次要 表9 module 字段 取值 说明 MODULE_UNSPECIFIED 0 未定义 MODULE_NAVIGATION 1 导航 MODULE_LOCATION 2 定位 MODULE_PERCEPTION 3 感知 MODULE_PREDICTION 4 预测 MODULE_DECISION 5 决策 MODULE_PLANNING 6 规划 MODULE_CONTROL 7 控制 MODULE_WHOLE 8 整车 表10 performance 字段 取值 说明 PERFORMANCE_UNSPECIFIED 0 未定义 PERFORMANCE_SAFETY 1 安全性 PERFORMANCE_REGULATION 2 合规性 PERFORMANCE_COMFORT 3 舒适性 PERFORMANCE_INTELLIGENCE 4 智能型
  • 创建脱敏作业 查看数据递送订单详情,选择待脱敏的数据包,单击创建脱敏作业。 图3 创建脱敏作业 完成算子基本配置。 图4 算子基本信息 处理算子:根据需要选择数据脱敏算子。 资源规格:选择合适的资源规格。 优先级:设定任务的优先级,数值取[-50,50]的整数,数字越大,优先级越高。 环境变量:配置算子的环境变量。允许添加的环境变量个数不超过10个。 Key:只能由英文、数字、和特殊符号(,-_)组成,且需要以字母开头 。长度不超过64个字符。 Value:只能由英文、数字和特殊符号(\/,.[]-_)组成 。长度不超过64个字符。 合规数据ID:展示选择数据包的ID。 单击“创建”,执行数据包脱敏任务。脱敏完成后,数据包状态变为脱敏完成。
  • 指示标志牌前行为(Mandatory Sign)检测 指示标志牌前行为检测的目的是判断主车在这些指示标志牌前的行为是否合理,本设计考虑的指示标志牌有: 左转指示牌 右转指示牌 直行指示牌 左转直行指示牌 右转直行指示牌 左转右转指示牌 靠左行驶指示牌 靠右行驶指示牌 当主车前端超过左转指示牌, 并且主车不存在左转行为, 则左转指示牌前行为检测不通过。 当主车前端超过右转指示牌, 并且主车不存在右转行为, 则右转指示牌前行为检测不通过。 当主车前端超过直行指示牌, 并且主车不存在直行行为, 则直行指示牌前行为检测不通过。 当主车前端超过左转直行指示牌, 并且主车不存在左转直行行为, 则左转直行指示牌前行为检测不通过。 当主车前端超过右转直行指示牌, 并且主车不存在右转直行行为, 则右转直行指示牌前行为检测不通过。 当主车前端超过左转右转指示牌, 并且主车不存在左转右转行为, 则左转右转指示牌前行为检测不通过。 该指标关联的内置可视化时间序列数据为:暂无。 该指标的异常时间点记录类型为:POINT_TYPE_REGION。 父主题: 内置评测指标说明
  • 评测任务相关操作 在“评测任务”列表,可对任务进行以下操作。 表3 评测任务相关操作 任务 操作步骤 查找任务 在搜索输入框中输入搜索条件,按回车键即可查询。 查看任务详情 单击任务名称,可在任务详情页查看该任务详情、参数信息、评测结果、任务日志和资源在占用情况。 任务详情:任务ID、名称、描述、状态、资源类型等信息。 任务视图:根据创建任务时选择不同的评测,显示不同的任务视图。 评测结果:单击任务视图,可显示相对应的评测任务结果,详情请参考评测结果。 任务日志:单击任务视图,可显示相对应的任务运行过程中生成的日志信息,详情请查看评测任务日志查看与下载。 资源占用情况:单击任务视图,可显示相对应任务占用的CPU、内存、GPU显存利用率、占用率百分比的折线图,详情请查看资源占用情况。 删除任务 单击操作栏的“删除”,删除单个任务。 勾选多个任务,单击列表上方的“删除”,可批量删除任务。 重建任务 单击操作栏内的“重建”,输入新任务名称(以“任务组名-自定义名称”的形式)和是否删除原任务选项,同时可重新选择需要修改的参数。 停止任务 单击操作栏的“停止”,停止评测任务。 继续任务 单击操作栏中的“继续”,继续执行任务。 对比任务 勾选2-4个任务(要求类别相同,且均为已完成状态),单击“对比”创建对比任务,具体步骤请参考评测对比。
  • 构建镜像 Dockerfile示例 FROM python:3.10 COPY mask.py /home/main/ WORKDIR /home/main/ RUN pip install rosbags requests numpy USER root 构建镜像 sudo docker build --no-cache -f Dockerfile -t rosbagmask:0.1 . 本地调试 准备一个待处理的rosbag包。 sudo docker run -v ${HOME}/data/test.bag:/home/main/test.bag --env input_file=/home/main/test.bag –env raw_dir=/home/main/raw_dir –env desensitized_dir=/home/main/desensitized_dir –env output_dir=/home/main/output_dir -it rosbagmask:0.1 /bin/sh -c "python mask.py"
  • 作业输入输出规范 用户完成自定义脱敏算子创建,运行作业容器时Octopus平台向其中注入以下环境变量: input_file:待脱敏的文件路径 raw_dir:抽取的image,gnss,lidar数据存放路径 desensitized_dir:脱敏后的image,gnss,lidar数据存放路径 output_dir:脱敏后的文件存放路径 用户根据需要可以自定义环境变量,以rosbag文件为例,可以定义如下环境变量: rosbag_version:robag版本 image_topics:图像数据topic列表 gnss_topic:gnss数据topic lidar_topics:lidar数据topic列表 用户作业容器需要将input_file中的image,gnss,lidar数据抽取到raw_dir,待系统内置算子脱敏完成,并将脱敏后的数据存放到desensitized_dir后,用户算子根据input_file和desensitized_dir中的脱敏数据生成新的数据文件存放到output_dir。 文件结构如下: -raw --image ---topic0 ----timestamp1.jpg ----timestamp2.jpg ---topic1 ----timestamp1.jpg --gnss ---gnss_topic.json --lidar ---pcd_topic0 ----timestamp0.pcd ----timestamp1.pcd --SUC CES S -desensitized --image ---topic0 ----timestamp1.jpg ----timestamp2.jpg ---topic1 ----timestamp1.jpg --gnss ---gnss_topic.json --lidar ---pcd_topic0 ----timestamp0.pcd ----timestamp1.pcd --SUCCESS -output --test.bag --SUCCESS 其中,“SUCCESS”文件为标识文件,标识所在阶段的任务结束。
  • 示例代码 下面是rosbag脱敏的算子示例: # mask.py import json import logging import multiprocessing as mp import os import shutil import time from pathlib import Path from typing import cast import av import numpy as np import open3d from rosbags.highlevel import AnyReader from rosbags.interfaces import ConnectionExtRosbag1, ConnectionExtRosbag2 from rosbags.rosbag1 import Writer as Writer1 from rosbags.rosbag2 import Writer as Writer2 from rosbags.serde import cdr_to_ros1, serialize_cdr from rosbags.typesys import get_types_from_msg, register_types from rosbags.typesys.types import builtin_interfaces__msg__Time as Time from rosbags.typesys.types import \ sensor_msgs__msg__CompressedImage as CompressedImage from rosbags.typesys.types import std_msgs__msg__Header as Header logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s', ) LOG = logging.getLogger(__file__) # Octopus数据服务拉起镜像时灌入的环境变量 # 获取环境变量 input_path = os.getenv('input_path', 'data/hangyan-move.bag.bak') raw_dir = os.getenv('raw_dir', 'empty_dir/raw') # 抽取的文件存放目录 desens_dir = os.getenv('desensitized_dir', 'empty_dir/desens') # 脱敏后的文件存放目录 output_dir = os.getenv('output_dir', 'empty_dir/output') lidar_process_num = os.getenv('lidar_process_num', 5) # lidar数据进程数 # 用户自定义环境变量 rosbag_version = os.getenv('rosbag_version', '1') # rosbag版本,取值为'1'或'2' image_topics = [ x.strip(' ') for x in os.getenv('image_topics', '/camera_encoded_1').split(',') ] # 图像数据的topic列表 gnss_topic = os.getenv('gnss_topic', '/inspvax') # gnss数据的topic,gnss数据只能有一个topic lidar_topics = [ x.strip(' ') for x in os.getenv('lidar_topic', '/pandar').split(',') ] # 点云数据的topic列表 # 注册自定义消息类型 Video_encoded_data_text = Path('msgs/Video_encoded_data.msg').read_text() NovatelMessageHeader_text = Path('msgs/NovatelMessageHeader.msg').read_text() NovatelExtendedSolutionStatus_text = Path( 'msgs/NovatelExtendedSolutionStatus.msg').read_text() NovatelReceiverStatus_text = Path('msgs/NovatelReceiverStatus.msg').read_text() Inspvax_text = Path('msgs/Inspvax.msg').read_text() add_types = {} add_types.update( get_types_from_msg( Video_encoded_data_text, 'kyber_msgs/msg/Video_encoded_data', )) add_types.update( get_types_from_msg( NovatelMessageHeader_text, 'novatel_gps_msgs/msg/NovatelMessageHeader', )) add_types.update( get_types_from_msg( NovatelExtendedSolutionStatus_text, 'novatel_gps_msgs/msg/NovatelExtendedSolutionStatus', )) add_types.update( get_types_from_msg( NovatelReceiverStatus_text, 'novatel_gps_msgs/msg/NovatelReceiverStatus', )) add_types.update( get_types_from_msg( Inspvax_text, 'novatel_gps_msgs/msg/Inspvax', )) register_types(add_types) # create gnss file gnss_file_path = Path(raw_dir, 'gnss') / f'{gnss_topic}.json'.strip('/') Path.mkdir(gnss_file_path.parent, parents=True, exist_ok=True) def extract_image(input_rosbag): '''从原始rosbag中抽取图像数据.''' LOG.info('Start extracting image.') codec_ctx = av.codec.Codec('hevc', 'r') h265_code = codec_ctx.create() with AnyReader([Path(input_rosbag)]) as reader: for connection, timestamp, data in reader.messages(): topic = connection.topic if topic in image_topics: deserialized_data = reader.deserialize(data, connection.msgtype) try: data = deserialized_data.raw_data packet = av.packet.Packet(data) out = h265_code.decode(packet) img = None for frame in out: if frame.format.name != 'rgb24': frame = frame.reformat(format='rgb24') img = frame.to_image() # 图像存放路径 file_name = f'{timestamp}.jpg' f_path = Path(raw_dir, 'image') / topic.strip('/') tmp_path = Path(raw_dir, 'tmp_image') / topic.strip('/') Path.mkdir(tmp_path, parents=True, exist_ok=True) tmp_file = tmp_path / file_name file = f_path / file_name # 当未建立目录时,先基于topic名称建立目录 Path.mkdir(file.parent, parents=True, exist_ok=True) img.save(tmp_file) os.chmod(tmp_file, 0o777) os.chmod(file.parent, 0o777) shutil.move(tmp_file, file) except Exception as e: LOG.info("%s frame can not trans to jpg, message: %s", timestamp, str(e)) LOG.info('Finish extracting image.') def extract_lidar(task_id, task_num, input_rosbag): '''从原始rosbag中抽取点云数据.''' LOG.info('Start extracting pcd.') with AnyReader([Path(input_rosbag)]) as reader: for i, (connection, timestamp, data) in enumerate(reader.messages()): if i % task_num != task_id: continue topic = connection.topic if topic in lidar_topics: deserialized_data = reader.deserialize(data, connection.msgtype) pcd = open3d.geometry.PointCloud() reshaped = deserialized_data.data.reshape( int(len(deserialized_data.data) / 3), 3) pcd.points = open3d.utility.Vector3dVector(reshaped) file_name = f'{timestamp}.pcd' f_path = Path(raw_dir, 'lidar') / topic.strip('/') tmp_path = Path(raw_dir, 'tmp_lidar') / topic.strip('/') Path.mkdir(tmp_path, parents=True, exist_ok=True) tmp_file = tmp_path / file_name file = f_path / file_name # 当未建立目录时,先基于topic名称建立目录 Path.mkdir(file.parent, parents=True, exist_ok=True) open3d.io.write_point_cloud(str(tmp_file), pcd) os.chmod(tmp_file, 0o777) os.chmod(file.parent, 0o777) shutil.move(tmp_file, file) LOG.info('Finish extracting pcd.') def extract_gnss(input_rosbag): '''从原始rosbag中抽取gnss数据.''' LOG.info('Start extracting rosbag.') gnss_file = open(gnss_file_path, 'w') gnss = dict() with AnyReader([Path(input_rosbag)]) as reader: for connection, timestamp, data in reader.messages(): topic = connection.topic if topic == gnss_topic: deserialized_data = reader.deserialize(data, connection.msgtype) # 这里以msgytpe为NavSatFix为例 latitude = deserialized_data.latitude longitude = deserialized_data.longitude altitude = deserialized_data.altitude gnss[timestamp] = { 'latitude': latitude, 'longitude': longitude, 'altitude': altitude } gnss_file.write(json.dumps(gnss)) gnss_file.close() LOG.info('Finish extracting gnss.') def _get_masked_image(topic, timestamp): '''从脱敏后的图像数据中获取目标图像数据.''' file = Path(desens_dir, 'image') / topic.strip('/') / f'{timestamp}.jpg' if file.is_file(): return np.fromfile(file, dtype='uint8') else: return None def _get_conn_map(rosbag_version: int, reader, writer): '''构建connection的索引.''' conn_map = {} if rosbag_version == '1': for conn in reader.connections: if conn.topic in image_topics: conn_map[conn.id] = writer.add_connection( '/image', CompressedImage.__msgtype__, ) else: ext = cast(ConnectionExtRosbag1, conn.ext) conn_map[conn.id] = writer.add_connection( conn.topic, conn.msgtype, conn.msgdef, conn.md5sum, ext.callerid, ext.latching, ) elif rosbag_version == '2': for conn in reader.connections: if conn.topic in image_topics: conn_map[conn.id] = writer.add_connection( '/image', CompressedImage.__msgtype__, ) else: ext = cast(ConnectionExtRosbag2, conn.ext) conn_map[conn.id] = writer.add_connection( conn.topic, conn.msgtype, ext.serialization_format, ext.offered_qos_profiles, ) return conn_map def _serialize_data(rosbag_version, data, msgtype): '''对数据进行序列化.''' if rosbag_version == '1': return cdr_to_ros1(serialize_cdr(data, msgtype), msgtype) elif rosbag_version == '2': return serialize_cdr(data, msgtype) def generate_rosbag(input_rosbag, output_rosbag): '''生成脱敏后rosbag.''' LOG.info('Start generating rosbag.') gnss_file = open( Path(desens_dir, 'gnss') / f'{gnss_topic}.json'.strip('/'), 'r') gnss_data = json.load(gnss_file) gnss_file.close() Writer = Writer1 if rosbag_version == '1' else Writer2 with AnyReader([Path(input_rosbag) ]) as reader, Writer(Path(output_rosbag)) as writer: conn_map = _get_conn_map(rosbag_version, reader, writer) for connection, timestamp, data in reader.messages(): topic = connection.topic # 当topic为图像数据的topic时,读取脱敏后图像数据 if topic in image_topics: masked_data = _get_masked_image(topic, timestamp) if masked_data is None: # 没有解析出图像文件时,不要该帧了 continue deserialized_data = CompressedImage( Header( stamp=Time( sec=int(timestamp // 10**9), nanosec=int(timestamp % 10**9), ), frame_id='0', ), format='jpg', data=masked_data, ) data = _serialize_data( rosbag_version, deserialized_data, CompressedImage.__msgtype__, ) # 当topic为gnss数据时,读取脱敏后gnss数据 elif topic == gnss_topic: deserialized_data = reader.deserialize(data, connection.msgtype) deserialized_data.latitude = gnss_data.get( str(timestamp)).get('latitude') deserialized_data.longitude = gnss_data.get( str(timestamp)).get('longitude') deserialized_data.altitude = gnss_data.get( str(timestamp)).get('altitude') data = _serialize_data( rosbag_version, deserialized_data, connection.msgtype, ) # 当topic为点云数据时,读取脱敏后点云数据 elif topic in lidar_topics: deserialized_data = reader.deserialize( data, connection.msgtype, ) file = Path( desens_dir, 'lidar', ) / topic.strip('/') / f'{timestamp}.pcd' point_cloud = open3d.io.read_point_cloud(str(file)) deserialized_data.data = np.asarray( point_cloud.points).flatten() writer.write(conn_map[connection.id], timestamp, data) # 生成_SUCCESS文件标识完成数据抽取 Path(output_dir, '_SUCCESS').touch() LOG.info('Finish generating rosbag.') if __name__ == "__main__": LOG.info('Start user operator.') process_image = mp.Process(target=extract_image, args=(input_path, )) pool_lidar = mp.Pool(processes=lidar_process_num) for i in range(lidar_process_num): pool_lidar.apply_async(extract_lidar, args=(i, lidar_process_num, input_path)) process_gnss = mp.Process(target=extract_gnss, args=(input_path, )) # 启动子进程 process_image.start() pool_lidar.close() process_gnss.start() process_image.join() pool_lidar.join() process_gnss.join() LOG.info('Child processes exit.') # 生成_SUCCESS文件标识完成数据抽取 Path(raw_dir, '_SUCCESS').touch() # 后面输出的rosbag文件与输入的rosbag文件保持同名 output_rosbag_file = Path(output_dir, Path(input_path).name) # 如果输出文件夹不存在,先创建文件夹 Path.mkdir(output_rosbag_file.parent, parents=True, exist_ok=True) # 检测到脱敏任务结束后,生成新的rosbag文件 while time.sleep(1) is None: if Path(desens_dir).joinpath('_SUCCESS').is_file(): generate_rosbag(Path(input_path), output_rosbag_file) break
  • 场景库相关操作 在“场景库”页签,可对场景库进行以下操作。 表1 场景库相关操作 任务 操作步骤 查看场景库信息 单击左侧场景库名称,查看右侧该场景库信息以及场景库包含场景信息。 场景库信息:场景库名称、创建人、仿真器、描述、关联仿真任务数和创建时间等信息。 场景列表:该场景库中包含的所有场景。场景的具体操作请参考场景管理。 修改场景库信息/场景库分类信息 单击场景库名称或场景库分类后的,修改场景库或场景库分类的信息。 删除场景库/场景库分类 单击场景库名称或场景库分类后的,删除指定场景库或场景库分类。 查询场景 根据“场景名称”或“创建人”,输入搜索条件,查询场景列表中的场景。
  • 任务配置相关操作 在“任务配置”列表,可对仿真任务配置进行以下操作。 表3 任务配置相关操作 任务 操作步骤 查看算法详情 单击该任务配置所使用的算法名称,即可查看算法详情。无算法接入时页面显示“--”,使用仿真器自带的驾驶员模型控制主车。 查看评测详情 单击该任务配置所使用的评测名称,即可查看评测详情。 查看任务配置详情 单击任务配置名称,可查看任务配置详情。 图6 任务配置详情 查询任务配置 可按照"任务配置ID"、"任务配置名称"、"算法名称"、"评测名称"、"任务配置描述"查询任务配置。 删除任务配置 单击操作栏“ 删除”,删除该任务配置。删除后不可恢复,请谨慎操作。 编辑任务配置 单击操作栏“编辑”,以修改任务配置名称和描述信息。
  • Octopus 目录 标注文件目录结构 +--- 1599625710056 | +--- 1599625710056.jpg | +--- 1599625710056.json +--- 1599625740054 | +--- 1599625740054.jpg | +--- 1599625740054.json 推理文件目录结构 +--- 1599625710056 | +--- 1599625710056.json +--- 1599625740054 | +--- 1599625740054.json 示例标注文件 2D目标追踪-Octopus标注.json { "frame_id": 0, "labels": [ { "label_meta_name": "Car", "label_object_id": 1, "bndbox": { "ymin": 503, "xmax": 980, "ymax": 524, "xmin": 956 } }, { "label_meta_name": "Car", "label_object_id": 2, "bndbox": { "ymin": 508, "xmax": 931, "ymax": 531, "xmin": 904 } } ] } 示例推理文件 2D目标追踪-Octopus推理.json { "frame_id": 0, "labels": [ { "label_meta_name": "Car", "label_object_id": 1, "score": 0.89, "bndbox": { "ymin": 500, "xmax": 970, "ymax": 520, "xmin": 950 } }, { "label_meta_name": "Car", "label_object_id": 2, "score": 0.82, "bndbox": { "ymin": 508, "xmax": 930, "ymax": 520, "xmin": 900 } } ] }
  • 修改标注框 修改矩形框。 左键单击矩形框的某条边拖动可修改这个边的位置,左键单击某个角点拖动可以修复角点位置。 左键选中某条边,或者某个角点,可以通过h(←)j(↓)k(→)u(↑)调整像素框1px。 图7 修改矩形框 修改目标类别。 右键单击目标图形,可进入选择类别的跳出框,即可修改类别。 图8 修改目标类别 修改额外属性。 右键单击目标图形,如果目标含有额外属性,如果其默认属性错误,单击即可选择属性。 图9 修改额外属性 修改对象ID。 右键单击目标图形,可以在对象ID栏手动输入数值来修改ID。 图10 修改对象ID
  • 绘制对象 绘制矩形框。 选择矩形图形工具(快捷键3,非小键盘)。 在标注列表中选择需要标注的类别(非必要,也可等标注完成后,右键修改类别)。 单击选择的第一个点,移动鼠标选择需要绘制的第二个,再次单击结束。 图2 选择绘制矩形框 绘制垂直线。 同选择矩形框工具方式与类别一致选择直线图形工具(快捷键2,非小键盘)。 长按键盘Shift,单击直线开始点,再单击直线结束点,可以绘制成一条垂直线。 同理操作可绘制水平线 。 图3 绘制垂直线 图4 绘制垂直线 绘制点。 同选择矩形框工具方式与类别一致选择点图形工具(快捷键1,非小键盘)。 左键单击即可绘制点图形 。 图5 绘制点 图6 绘制点
  • Octopus 目录 标注文件目录结构 +--- 1599625710056 | +--- 1599625710056.pcd | +--- 1599625710056.json +--- 1599625740054 | +--- 1599625740054.pcd | +--- 1599625740054.json 推理文件目录结构 +--- 1599625710056 | +--- 1599625710056.json +--- 1599625740054 | +--- 1599625740054.json 示例标注/推理文件 3D语义分割-Octopus.json { "labels": [ { "label_meta_id": 1, "polygon_3d_v2": { "ascii_char": "\"" }, "shape_type": "polygon_3d_v2", "serial_number": 0, "label_object_id": -1, "name": "car" }, { "label_meta_id": 19, "polygon_3d_v2": { "ascii_char": "4" }, "shape_type": "polygon_3d_v2", "serial_number": 0, "label_object_id": -1, "name": "traffic-sign" } ], "labels_ext": { "ascii_string": "000000000000000000000000000000000000000000000000000000000000000000444404444000111000000000000000000000000000000000000000000000000,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,," } }
  • 动作(lane_offset) 动作主体:车辆vehicle 结束时间:当动作主体actor到达目标偏移offset处时,动作结束。 是否支持modifier:否 参数:参数如下表,支持位置参数和关键字参数。参数target非必选项,不设置target时采用绝对偏移,设置target时采用相对偏移。 表7 lane_offset参数 Parameter Type Mandatory Description offset length yes Signed number in meters the vehicle should respect as an offset from the center of the current lane rate_peak speed yes Target value for the peak lateral velocity that must be achieved during the action dynamics_shape dynamics_shape yes Geometrical shape of the LaneOffsetAction's dynamics target entity no Reference entity offset值不能超出当前所在lane的宽度范围。 绝对偏移 m_shape: dynamics_shape = step Ego.lane_offset(0.8m, 0.5mps, m_shape) 相对偏移 m_shape: dynamics_shape = linear side_vehicle.lane_offset(offset:1.0m, rate_peak: 1.5mps, dynamics_shape:m_shape, target: Ego)
  • 动作(acquire_position) 动作主体:车辆vehicle或行人pedestrian。 结束时间:当动作主体actor获取目标位置position时,动作结束。 是否支持modifier:否 参数表: 参数如下表,pose_3d是point和orientation的组合结构, point可以使用xyz_point或odr_point或road_point中的任意一个,orientation非必选项。 表8 acquire_position参数 Parameter Type Mandatory Description target pose_3d yes target position acquire_position与acquire_position_init的使用方法相同,但由于不是初始动作,可以设置触发条件。 仿真器B尚未支持acquire_position动作。 代码样例见初始动作(acquire_position_init)。
  • 动作(activate_controller) 动作主体:车辆vehicle 结束时间:激活或停用控制器controller后,动作结束。 是否支持modifier:否 参数:参数如下表,支持位置参数和关键字参数。 表6 activate_controller参数 Parameter Type Mandatory Description lateral bool yes In lateral domain: Activate or deactivate controller defined (e.g. automated, autonomous) behavior longitudinal bool yes In longitudinal domain: Activate or deactivate autonomous behavior 代码样例: Ego.activate_controller(lateral:true, longitudinal:true)
  • 初始动作(assign_init_position) 动作主体:车辆vehicle或行人pedestrian。 结束时间:当动作主体actor到达指定的位置坐标时,动作结束。 是否支持modifier:是 参数:参数如下表 表2 assign_init_position参数 Parameter Type Mandatory Description position pose_3d no Desired position assigned by the user assign_init_position支持设置绝对位置和相对位置,设置相对位置时使用修饰器(position)和修饰器(lane)来给出相对值。 当初始位置需要车辆转换朝向时,通过设置pose_3d的orientation来设定朝向,以与所在车道朝向一致,例如车辆所在车道和road0呈90°夹角时,设置orientation的yaw为1.57rad,否则车辆启动后会有转向行为,影响场景的正常执行。 设置初始位置时所采用的地图元素必须是对应的地图中有的元素,比如设置绝对位置create_odr_point('0', '-4', 5.0m, 0.0m)时,地图上必须有id为'0'的road,该road上必须有lane_id为 '-4'的lane,该lane至少有5.0m以上的长度。如果设置的初始位置找不到地图中的对应元素,将泛化出无效的场景。 绝对位置 m_odr: odr_point = map.create_odr_point('0', '-4', 5.0m, 0.0m) m_orientation: orientation_3d with: keep(it.roll == 0.0rad) keep(it.pitch == 0.0rad) keep(it.yaw == 1.57rad) init_position: pose_3d with: keep(it.odr_point == m_odr) keep(it.orientation == m_orientation) Ego.assign_init_position(position: init_position) 相对位置 cut_in_vehicle.assign_init_position() with: lane(lane: raletive_lane_id, side_of: Ego, side: left) position(distance: 85.0m, behind: Ego)
  • 初始动作(acquire_position_init) 动作主体:车辆vehicle或行人pedestrian。 结束时间:当动作主体actor获取目标位置position时,动作结束。 是否支持modifier:否 参数表: 参数如下表,pose_3d是point和orientation的组合结构,point可以使用xyz_point或odr_point或road_point中的任意一个,orientation非必选项。 表3 acquire_position_init参数 Parameter Type Mandatory Description target pose_3d yes target position 目标位置必须在地图设定的道路上,且是可达的。 xyz_point,有方向要求 m_x: length = 0.0m m_xyz: xyz_point = map.create_xyz_point(x: m_x, y: 10.0m ,z: 0.0m) m_heading: angle = 1.57rad m_orientation: orientation_3d with: keep(it.roll == 0.0rad) keep(it.pitch == 0.0rad) keep(it.yaw == m_heading) m_position: pose_3d with: keep(it.xyz_point == m_xyz) keep(it.orientation == m_orientation) Ego.acquire_position_init(target: m_position) odr_point,无方向要求 m_odr: odr_point = map.create_odr_point(road_id: '0', lane_id: '-4', s: 5.0m, t: 0.0m) m_position: pose_3d with: keep(it.odr_point == m_odr) Ego.acquire_position_init(target: m_position) road_point,无方向要求 m_road: road_point = map.create_road_point(road_id: '0', s: 5.0m, t: 0.0m) m_position: pose_3d with: keep(it.road_point == m_road) Ego.acquire_position_init(target: m_position)
  • 动作(change_speed) 动作主体:车辆vehicle或行人pedestrian。 结束时间:当动作主体actor达到目标速度target ,动作结束。 是否支持modifier:否 参数:参数如下表,支持位置参数和关键字参数。 表4 change_speed参数 Parameter Type Mandatory Description reference entity no Default=it.actor. Reference to the entity that is used to determine the target speed. If this argument is omitted, the actor itself is used as reference target speed yes Target value for the speed at the end of the action rate_profile dynamics_shape yes Assign a shape for the change of the speed variable. This profile affects the acceleration during action execution rate_peak acceleration yes Target value for the peak acceleration that must be achieved during the action 目标速度不能超出所在道路的限速值。 当rate_profile为step时,瞬间达到目标速度,不会受到rate_peak值的影响。 样例 m_profile: dynamics_shape = sinusoidal Ego.change_speed(reference: lead_vehicle, target: -5.0mps, rate_profile: m_profile, rate_peak: 2mpss)
  • 动作(change_lane) 动作主体:车辆vehicle 结束时间:当动作主体actor位于目标车道lane中、目标偏移offset处时,动作结束。 是否支持modifier:否 参数:参数如下表,支持关键字参数。rate_peak和rate_profile是必选项,用于设置osc1中的dynamics、target和reference必须设置且只设置其中之一,前者用于指定绝对车道,后者用于指定相对车道。 表5 change_lane参数 Parameter Type Mandatory Description number_of_lanes uint no The target lane is "num_of_lanes" to the side of the reference entity. Use in conjunction with "side" side lane_change_side no Select on which side of the reference entity reference entity no Default=it.actor. Reference to the entity that is used to determine the target lane. If this argument is omitted, the actor itself is used as reference offset length no Default=0.0. Target offset from center of the target lane that the actor follows at the end of the action rate_profile dynamics_shape yes Assign a shape for the change of the lateral position variable (t-axis). This profile affects the lateral velocity during action execution rate_peak speed yes Target value for the peak lateral velocity that must be achieved during the action target lane_id(uint) no The actor starts and finishes the action in the target lane 目标lane必须在地图上。 中心线左侧的lane_id为正,如'1','2'。右侧的lane_id为负,如'-1','-3'。绝对值越大,距离中心线越远。 offset值不能超出当前所在lane的宽度范围。 使用相对位置时,参考对象reference必须是车辆。 rate_profile只能选择linear或step。 绝对车道1 my_lane: lane with: keep(it.lane_id == '1') m_profile: dynamics_shape = linear side_vehicle.change_lane(target: my_lane, rate_profile: m_profile, rate_peak: 0.3mps) 绝对车道2 my_lane: lane with: keep(it.lane_id == '-1') m_profile: dynamics_shape = linear side_vehicle.change_lane(target: my_lane, offset: -0.2m, rate_profile: m_profile, rate_peak: 0.4mps) 相对车道1 m_profile: dynamics_shape = step m_side: lane_change_side = left m_profile: dynamics_shape = step Ego.change_lane(number_of_lanes: 2, side: m_side, reference: side_vehicle, offset: 0.8m, rate_profile: m_profile, rate_peak: 0.3mps) 相对车道2 m_profile: dynamics_shape = step m_side: lane_change_side = same m_profile: dynamics_shape = step Ego.change_lane(number_of_lanes: 1, reference: side_vehicle, side:m_side, rate_profile: m_profile, rate_peak: 0.3mps)
  • 初始动作(assign_init_speed) 动作主体:车辆vehicle或行人pedestrian 。 结束时间:当动作主体actor达到指定的速度speed时,动作结束。 是否支持modifier:是 参数:参数如下表 表1 assign_init_speed参数 Parameter Type Mandatory Description target speed yes Desired (scalar) speed assigned by the user assign_init_speed支持设置绝对速度和相对速度,设置相对速度时使用修饰器(speed)来给出相对值。 设置初始速度时,初始速度不能超过该主体所在道路的限速。 如果所需场景起始速度为0,无需使用assign_init_speed动作。 绝对速度 init_speed: speed = 10.0mps Ego.assign_init_speed(init_speed) 相对速度 cut_in_vehicle.assign_init_speed() with: speed(speed: 5mps, faster_than: Ego)
  • 本地调试 运行如下命令(基于上述示例镜像): docker run -v ${HOME}/tmp/output:/tmp/output --env output_dir=/tmp/output --env tmp_dir=/tmp/workspace ros-hard-mining:0.1 /bin/sh -c “python3 /home/main/ros_hard_mining.py --tags tag1,tag2 --time_range 1673231275000,1673261275000 --sensors camera_encoded_1,pandar --number 10” 完成后在${HOME}/tmp/output目录查看运行结果文件:
共100000条