- 科研
- 自动驾驶
- 物理引擎
【免费下载链接】webots
Webots Robot Simulator
导读
本文围绕 Webots 开源机器人仿真器中的 SickLdMrs PROTO 展开,全面讲解如何用 Webots 内置的 Lidar 节点 建模 SICK LD-MRS 多线激光雷达:包括 PROTO 的全部字段含义与取值、主 Lidar 与长距离 Lidar 的双传感器架构、朝向与坐标系约定,以及与真实设备的仿真差异。文中还结合仓库自带的sick_point_cloud示例世界与控制器,演示如何在 C 和 Python 中通过点云 API 读取该雷达数据并完成目标计数,读完后你将能独立在 Webots 世界中部署并编程使用这一工业级 3D 激光雷达模型。
SickLdMrs PROTO 概述
SICK LD-MRS 是 SICK 公司专为恶劣室外环境设计的多层(multi-layer)激光雷达。在 Webots 中,它由projects/devices/sick/protos/SickLdMrs.proto定义:PROTO 内部包含一个 Lidar 节点,覆盖了绝大多数常规使用场景。该传感器在 Webots API 中的引用名称(reference name)直接对应SickLdMrs.name字段,因此你可以通过wb_robot_get_device("自定义name")(C)或getDevice("自定义name")(Python)直接获取设备句柄。
仿真模型的主要特性如下:
- 层数:默认 4 层;当
type为800001S01时为 8 层; - 水平扫描范围:85°,并相对设备正前方水平偏移 7.5°;
- 最大量程:300 米;
- 垂直层间距:相邻两层之间垂直间隔 0.8°。
这些数值在 SickLdMrs.proto 的主 Lidar 节点中被直接体现:fieldOfView为 85° 对应的弧度值,verticalFieldOfView为0.8 * (measurementLayers + 1)度,maxRange为 300,minRange为 0.5 米。
PROTO 基本用法与字段速览
在 Webots 世界中通过 EXTERNPROTO 引用该模型即可使用,例如仓库自带的示例世界 sick_point_cloud.wbt 中的声明:
EXTERNPROTO "webots://projects/devices/sick/protos/SickLdMrs.proto"随后在Robot节点下实例化:
SickLdMrs { translation 0.25 0 1.2 name "sick" type "800001S01" }SickLdMrs 完整的字段定义(来自 SickLdMrs.proto 及配套文档 sickldmrs.md):
| 字段 | 类型 | 默认值 | 取值范围/说明 |
|---|---|---|---|
translation | SFVec3f | 0 0 0 | 传感器在父节点坐标系中的位置 |
rotation | SFRotation | 0 0 1 0 | 传感器姿态(绕 z 轴旋转,默认无旋转) |
name | SFString | "Sick LD-MRS" | Webots API 中的设备引用名 |
type | SFString | "400001" | 设备型号,见下表 |
angularResolution | SFString | "0.5 [deg]" | 垂直角分辨率,三档可选 |
noise | SFFloat | 0.001 | 高斯噪声标准差(单位:米) |
enablePhysics | SFBool | TRUE | 是否启用物理属性(质量 1 kg) |
完整实例化示例:
SickLdMrs { translation 0 0 0 rotation 0 0 1 0 name "Sick LD-MRS" type "400001" angularResolution "0.5 [deg]" noise 0.001 enablePhysics TRUE }核心字段详解
type:设备型号
type字段对应 SICK LD-MRS 的不同硬件型号,SickLdMrs.proto 通过枚举约束了合法取值,只能是以下五者之一:
400001400102400001S01400102S01800001S01
其中400102与400102S01属于 HD(高分辨率)型号,800001S01属于 8 层型号。从源码看(SickLdMrs.proto):
const isHD = type === '400102' || type === '400102S01'; const is8L = type === '800001S01'; let measurementLayers = is8L ? 8 : 4;即默认(含 HD 型号)均为 4 层,仅800001S01为 8 层。型号同时影响外观纹理的选用:HD 型号使用textures/sick_ld_mrs_hd.png,8 层型号使用textures/sick_ld_mrs_8l.png,其余型号使用textures/sick_ld_mrs.png(SickLdMrs.proto)。
angularResolution:垂直角分辨率
angularResolution字段指定两次测量之间的垂直角度间隔。根据 SICK LD-MRS 规格,取值只能是0.5 [deg]、0.25 [deg]或0.125 [deg]三档。在 PROTO 模板脚本中,它被换算为弧度后直接驱动主 Lidar 的horizontalResolution(SickLdMrs.proto):
let angularResolution = wbutility.degreesToRadians(0.5); if (fields.angularResolution.value === '0.25 [deg]') angularResolution = angularResolution * 0.5; else if (fields.angularResolution.value === '0.125 [deg]') angularResolution = angularResolution * 0.25;随后主 Lidar 的水平分辨率计算为(SickLdMrs.proto):
horizontalResolution = round(horizontalFieldOfView / angularResolution)以默认值0.5 [deg]为例,主 Lidar 的水平分辨率为round(85° / 0.5°) = 170个点/层;若选用0.25 [deg]则为 340 点,0.125 [deg]则为 680 点。分辨率越高,单帧计算量越大,需要结合仿真实时性权衡。
noise:高斯噪声
noise字段指定叠加到每次测距深度值上的高斯噪声标准差,单位是米。PROTO 默认值为0.001(即 1 毫米)。按照 Lidar 参考文档 的约定,noise大于 0 时每个深度值都会叠加高斯噪声,值为 1.0 时对应标准差为maxRange(此处即 300 米)的高斯噪声。仿真中若不需要模拟测量噪声,可将其设为 0 以节省计算开销。
enablePhysics:物理属性
enablePhysics字段决定传感器是否受物理引擎影响。启用时,PROTO 会附加一个包围盒(boundingObject)与 Physics 节点,质量为 1 kg(SickLdMrs.proto):包围盒为尺寸0.1365 × 0.088 × 0.094米的长方体,并带有 -2.0944 弧度的旋转与 -0.047 米的平移以贴合设备外形。在需要将雷达安装在移动机器人上并参与碰撞/惯性计算的场景中,保持TRUE即可。
双 Lidar 架构:主传感器与长距离重叠层
SICK LD-MRS 的物理特性之一是:除了常规的多层扫描,它还包含用于重叠远距离测量的长距离层(long-range layers)。为了还原这一特性,SickLdMrs PROTO 在主 Lidar 节点之外,还创建了第二个Lidar 节点专门建模这部分重叠的长距离层(SickLdMrs.proto)。
该长距离 Lidar 的引用名称是SickLdMrs.name字段拼接上字符串" (long range)",即若name为"Sick LD-MRS",则第二个设备名为"Sick LD-MRS (long range)",编程时需要分别获取两个设备句柄。它的特性为:
- 水平扫描范围:110°,相对正前方水平偏移 5°(主 Lidar 为 85° / 7.5°);
- 层数:等于
SickLdMrs.measurementLayers的一半(即默认 4 层型号 → 2 层,8 层型号 → 4 层); - 其余特性(最大量程 300 m、最小量程 0.5 m、噪声)与主 Lidar 一致。
主、辅两个 Lidar 的朝向在 PROTO 模板中通过组合旋转实现(SickLdMrs.proto):
internalRotation = combine({x:0, y:0, z:1, a: -7.5°}, {x:1, y:0, z:0, a: π})其中第一个分量是水平偏移(主 Lidar -7.5°、长距离 Lidar -5°),第二个分量{1,0,0,π}是绕 x 轴翻转 180°,用于把 Lidar 的默认扫描方向调整到设备正前方。
传感器朝向约定
无论是主 Lidar 还是长距离 Lidar,其内部朝向遵循统一的约定(见 sickldmrs.md):
- Layer 0 对应最底层:
numberOfLayers编号自下而上,最底层为 0,最顶层为numberOfLayers - 1; - 第一个响应值对应设备右侧:每层扫描数据中索引 0 的点对应雷达右侧方向,数据沿扫描方向依次排列。
这一点在编程读取数据时非常关键——例如示例控制器读取"中间层"时使用layers / 2作为层索引(见下节),正是基于层编号自下而上的约定。
与真实设备的仿真差异
相对真实硬件,该仿真模型存在两点明确限制(文档原文,sickldmrs.md):
- 扫描范围分辨率恒定:整个扫描扇区内角度分辨率保持一致,而真实设备在不同角度区间可能存在分辨率差异;
- 垂直方位角恒定:每个测量点的垂直方位角在整个扫描过程中保持不变,真实设备在长距离层等场景中会有方位角变化。
在需要精确还原传感器物理细节的应用(如传感器标定算法验证)中,这两点差异需要额外考量;对于大多数机器人感知与避障仿真,该模型已足够真实。
实战:sick_point_cloud 示例世界与点云计数
仓库在 projects/samples/devices/worlds/sick_point_cloud.wbt 提供了一个完整示例:一个静态机器人搭载 SickLdMrs(型号800001S01,8 层),面前是一条传送带,罐装饮料(Can)沿传送带排列。控制器使用 Lidar 的点云 API 统计传感器前方障碍物的数量,并在 Webots 控制台输出 "I see N cans"。
该世界文件中雷达的关键配置(sick_point_cloud.wbt):
Robot { children [ SickLdMrs { translation 0.25 0 1.2 name "sick" type "800001S01" } ... ] controller "sick_point_cloud" }配套控制器提供 C 与 Python 两个版本,路径分别为 sick_point_cloud.c 与 sick_point_cloud.py。
C 版本核心流程(sick_point_cloud.c):
WbDeviceTag sick = wb_robot_get_device("sick"); wb_lidar_enable(sick, time_step); wb_lidar_enable_point_cloud(sick); const int resolution = wb_lidar_get_horizontal_resolution(sick); const int layers = wb_lidar_get_number_of_layers(sick); ... // 读取中间层的全部点 const WbLidarPoint *layer = wb_lidar_get_layer_point_cloud(sick, layers / 2); for (p = 0; p < resolution; ++p) { const bool obstacle = layer[p].x < THRESHOLD; // THRESHOLD = 3.0 米 if (obstacle && !previous_obstacle) object_counter++; previous_obstacle = obstacle; }Python 版本逻辑完全对应(sick_point_cloud.py):
self.sick = self.getDevice('sick') self.sick.enable(self.timeStep) self.sick.enablePointCloud() ... layer = self.sick.getLayerPointCloud(int(layers / 2)) for p in range(resolution): point = layer[p] obstacle = point.x < 3.0 if obstacle and not previous_obstacle: object_counter += 1 previous_obstacle = obstacle实现要点:
- 点云结构:
wb_lidar_get_layer_point_cloud/getLayerPointCloud返回某一层的一维点数组,每个点包含x、y、z、layer_id、time五个成员(结构与语义见 lidar.md)。其中 xyz 坐标相对 Lidar 节点原点,layer_id取值范围 0 到numberOfLayers - 1。 - 连通域计数技巧:控制器对中间层逐点扫描,用一个布尔量
previous_obstacle记住前一点是否为目标,每当从"无障碍"跳变为"有障碍"时计数加一,从而把连续的点云簇识别为单个物体——这正是一个简单的前沿检测(edge detection)思路。 - 读取中间层:
layers / 2利用"Layer 0 是最底层"的编号约定,取到垂直方向正中的扫描层,以避开罐体顶部与底部边缘。
与 Lidar 节点底层约束的衔接
SickLdMrs 的配置直接映射到底层 Lidar 节点的关键字段:horizontalResolution、fieldOfView、verticalFieldOfView、numberOfLayers、minRange、maxRange、noise。使用该模型时需留意 Lidar 的固有仿真约束(lidar.md):
numberOfLayers < verticalFieldOfView * horizontalResolution / fieldOfView该约束用于保证各层扫描线在垂直视场内分布合理。SickLdMrs 的默认参数(如 4 层、垂直视场0.8 * 5 = 4°、水平分辨率 170、水平视场 85°)满足该约束;若自行调整angularResolution或型号,仍应以此式校验。此外,minRange(0.5 m)以内与maxRange(300 m)以外的目标测距值返回无穷大(lidar.md),编程时需对point.x等坐标做有限值判断。
小结
SickLdMrs PROTO 是 Webots 设备库中针对工业级多线激光雷达的高保真建模:通过主 Lidar + 长距离 Lidar 双传感器结构还原了 LD-MRS 的重叠长距离扫描特性,用type、angularResolution、noise、enablePhysics四个核心字段覆盖了从型号选型到噪声注入、物理仿真的完整配置需求,并配有可直接运行的sick_point_cloud点云示例。无论是进行室外环境感知仿真、移动机器人导航验证,还是研究多线雷达数据处理算法,都可以直接基于该模型快速搭建场景并调用 Webots 的点云 API 开展开发。
- 科研
- 自动驾驶
- 物理引擎
【免费下载链接】webots
Webots Robot Simulator
相关推荐
Webots 中 Robotis LDS-01 激光雷达(Lidar)PROTO 节点详解:从参数配置到避障实战
Webots 中 Robotis LDS 01 激光雷达(Lidar)PROTO 节点详解:从参数配置到避障实战 导读 RobotisLds01 是 Webot
科研自动驾驶物理引擎Webots 中 Hokuyo URG-04LX 激光雷达 PROTO 完全指南:配置参数、底层实现与控制器编程
Webots 中 Hokuyo URG 04LX 激光雷达 PROTO 完全指南:配置参数、底层实现与控制器编程 Hokuyo URG 04LX 是一款专为轻量
科研自动驾驶物理引擎Webots 中的 Hokuyo UTM-30LX 激光雷达 PROTO 节点:规格、配置与控制器编程指南
Webots 中的 Hokuyo UTM 30LX 激光雷达 PROTO 节点:规格、配置与控制器编程指南 Hokuyo UTM 30LX 是一款为户外高速移动
科研自动驾驶物理引擎
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考