【Chrono Engine学习总结】5-sensor-5.1-sensor基础并创建一个lidar

由于Chrono的官方教程在一些细节方面解释的并不清楚,自己做了一些尝试,做学习总结。

1、Sensor模块

Sensor模块是附加模块,需要单独安装。参考:【Chrono Engine学习总结】1-安装配置与程序运行

Sensor Module Tutorial
Sensor Overview

Sensor模块包括的内容如下:
在这里插入图片描述
其中:

  • Sensors模块是核心,包括各种传感器(IMU、GPS、相机、Lidar、Radar等),以及传感器管理器等;
  • Sensor Filters是对sensor原始数据进行滤波(我认为更准确说应该是“处理方式”),即从原始数据得到我们想要的数据。https://api.projectchrono.org/group__sensor__filters.html
  • Scene是和camera相关的场景设置,例如背景色、光照等;
  • 其他内容不展开介绍。

传感器当中,“光学”传感器,例如相机、lidar、radar等,依赖OptiX这个库。具体的依赖关系如下:
在这里插入图片描述

2、创建Sensor的流程

这里全部以lidar为例,进行介绍。

2.0 创建传感器管理器

在chrono中,所有传感器需要注册在sensor manager当中,由其统一进行管理。

管理器的创建、添加一个具体的sensor、仿真时数据更新,3行代码如下:

// 创建管理器
auto manager = chrono_types::make_shared<ChSensorManager>(&sys);
// 添加一个sensor:AddSensor(std::shared_ptr<ChSensor> sensor)
manager->AddSensor(lidar);
// 在仿真循环中,更新所有传感器数据:
manager->Update();

2.1 从JSON文件载入预定义好的sensor

官方提供了一些已经定义好的sensor,包括:通用相机、VLP16雷达、HDL32雷达、通用GPS、通用IMU等,这些的调用只需要一行代码即可实现创建。例如,直接创建一个VLP16的雷达:

auto vlp16 = Sensor::CreateFromJSON(GetChronoDataFile("sensor/json/Velodyne/VLP-16.json"), box_body, offset_pose);
manager->AddSensor(vlp16);

我们可以打开这个JSON文件,查看VLP16的具体参数:
在这里插入图片描述

2.2 通过代码方式逐步创建一个sensor

通过代码方式创建,就是通过代码将JSON中的格式,完全自己配置一遍,例如:

auto lidar =chrono_types::make_shared<ChLidarSensor>(box_body,                               // body lidar is attached toupdate_rate,                            // scanning rate in Hzoffset_pose,                            // offset pose900,                                    // number of horizontal samples30,                                     // number of vertical channelshorizontal_fov,                         // horizontal field of viewmax_vert_angle, min_vert_angle, 100.0f  // vertical field of view);
lidar->SetName("Lidar Sensor 1");
lidar->SetLag(lag);
lidar->SetCollectionWindow(collection_time);lidar->PushFilter(chrono_types::make_shared<ChFilterDIAccess>());			// 允许后续获取depth和intensity的filter
lidar->PushFilter(chrono_types::make_shared<ChFilterVisualize>(horizontal_samples / 2, vertical_samples * 5, "Raw Lidar Depth Data"));			// 将雷达数据可视化为深度图像的可视化filter
lidar->PushFilter(chrono_types::make_shared<ChFilterPCfromDepth>());		// 通过深度获取点云的filter
lidar->PushFilter(chrono_types::make_shared<ChFilterLidarNoiseXYZI>(0.01f, 0.001f, 0.001f, 0.01f));	// 对XYZI增加噪声的filter
lidar->PushFilter(chrono_types::make_shared<ChFilterVisualizePointCloud>(640, 480, 2, "Lidar Point Cloud"));		// 点云可视化的filter
lidar->PushFilter(chrono_types::make_shared<ChFilterXYZIAccess>());		// 获取XYZI数据的filter
manager->AddSensor(lidar);		// 添加lidar到管理器

可以看出,设置了一些列的filter。当然,在上面的JSON中,也有许多filter,有些filter有参数,例如ChFilterLidarNoiseXYZI,有些没有例如ChFilterPCfromDepth。这些filter是干什么的呢?我个人理解,这些光学传感器获得的原始数据,需要加上这些filter之后,才具备我们平常使用这些sensor的数据格式。

例如,对于lidar来说,设置了ChFilterXYZIAccess后,才可以获取XYZI的数据;设置ChFilterLidarNoiseXYZI后,可以对XYZI增加高斯噪声;设置ChFilterVisualizePointCloud和ChFilterVisualize后,会出现三维点云和二位深度图的可视化(如下图)。所以,filter认为是“功能实现途径”比较合适。
在这里插入图片描述
所以:sensor的原始数据只是从光学系统中获得的特性,并没有转化成我们希望的“传感器数据格式”,需要通过filter进行实现。这些filter(对于lidar)负责添加噪声、二维图像可视化、三维点云可视化、获取点云XYZI格式、获取深度信息,(对于camera)转灰度图、像素噪声等。详细参考:【chrono::sensor::ChFilter Class Reference】

2.3 通过JSON方式自定义创建sensor

除了官方自定义的两个lidar的JSON外,还可以自定义lidar的配置。就创建对应的JSON并修改配置即可,无需多言。

3、参考代码

#include <cmath>
#include <cstdio>
#include <iomanip>
#include "chrono/assets/ChVisualShapeTriangleMesh.h"
#include "chrono/assets/ChVisualMaterial.h"
#include "chrono/assets/ChVisualShape.h"
#include "chrono/geometry/ChTriangleMeshConnected.h"
#include "chrono/physics/ChBodyEasy.h"
#include "chrono/physics/ChSystemNSC.h"
#include "chrono/utils/ChUtilsCreators.h"
#include "chrono_thirdparty/filesystem/path.h"#include "chrono_sensor/sensors/ChLidarSensor.h"
#include "chrono_sensor/ChSensorManager.h"
#include "chrono_sensor/filters/ChFilterAccess.h"
#include "chrono_sensor/filters/ChFilterPCfromDepth.h"
#include "chrono_sensor/filters/ChFilterVisualize.h"
#include "chrono_sensor/filters/ChFilterVisualizePointCloud.h"
#include "chrono_sensor/filters/ChFilterLidarReduce.h"
#include "chrono_sensor/filters/ChFilterLidarNoise.h"
#include "chrono_sensor/filters/ChFilterSavePtCloud.h"
#include "chrono_sensor/sensors/Sensor.h"using namespace chrono;
using namespace chrono::geometry;
using namespace chrono::sensor;// Noise model attached to the sensor
enum NoiseModel {CONST_NORMAL_XYZI,  // Gaussian noise with constant mean and standard deviationNONE                // No noise model
};
NoiseModel noise_model = CONST_NORMAL_XYZI;// Lidar return mode
// Either STRONGEST_RETURN, MEAN_RETURN, FIRST_RETURN, LAST_RETURN
LidarReturnMode return_mode = LidarReturnMode::STRONGEST_RETURN;// Update rate in Hz
float update_rate = 5.f;// Number of horizontal and vertical samples
unsigned int horizontal_samples = 4500;
unsigned int vertical_samples = 32;// Horizontal and vertical field of view (radians)
float horizontal_fov = (float)(2 * CH_C_PI);  // 360 degree scan
float max_vert_angle = (float)CH_C_PI / 12;   // 15 degrees up
float min_vert_angle = (float)-CH_C_PI / 6;   // 30 degrees down// Lag time
float lag = 0.f;// Collection window for the lidar
float collection_time = 1 / update_rate;  // typically 1/update rate// Simulation step size
double step_size = 1e-3;
// Simulation end time
float end_time = 2000.0f;
// Save lidar point clouds
bool save = false;
// Render lidar point clouds
bool vis = false;int main(int argc, char* argv[]) {GetLog() << "Copyright (c) 2019 projectchrono.org\nChrono version: " << CHRONO_VERSION << "\n\n";chrono::SetChronoDataPath("E:/codeGit/chrono/chrono/build/data/");              // change the default data loading path.// 创建物理仿真环境// -----------------// Create the system// -----------------ChSystemNSC sys;// 在左、右、下方各创建一面墙// --------------------------------------------// add a few box bodies to be sensed by a lidar// --------------------------------------------auto box_body = chrono_types::make_shared<ChBodyEasyBox>(100, 100, 1, 1000, true, false);box_body->SetPos({ 0, 0, -1 });box_body->SetBodyFixed(true);sys.Add(box_body);auto box_body_1 = chrono_types::make_shared<ChBodyEasyBox>(100, 1, 100, 1000, true, false);box_body_1->SetPos({ 0, -10, -3 });box_body_1->SetBodyFixed(true);sys.Add(box_body_1);auto box_body_2 = chrono_types::make_shared<ChBodyEasyBox>(100, 1, 100, 1000, true, false);box_body_2->SetPos({ 0, 10, -3 });box_body_2->SetBodyFixed(true);sys.Add(box_body_2);// 创建sensor管理器// -----------------------// Create a sensor manager// -----------------------auto manager = chrono_types::make_shared<ChSensorManager>(&sys);manager->SetVerbose(false);// -----------------------------------------------// Create a lidar and add it to the sensor manager// -----------------------------------------------// 自定义代码方式,创建一个lidarauto offset_pose = chrono::ChFrame<double>({ -4, 0, 1 }, Q_from_AngAxis(0, { 0, 1, 0 }));auto lidar =chrono_types::make_shared<ChLidarSensor>(box_body,                               // body lidar is attached toupdate_rate,                            // scanning rate in Hzoffset_pose,                            // offset pose900,                                    // number of horizontal samples30,                                     // number of vertical channelshorizontal_fov,                         // horizontal field of viewmax_vert_angle, min_vert_angle, 100.0f  // vertical field of view);lidar->SetName("Lidar Sensor 1");lidar->SetLag(lag);lidar->SetCollectionWindow(collection_time);// 添加相应的滤波器filter// Renders the raw lidar datalidar->PushFilter(chrono_types::make_shared<ChFilterVisualize>(horizontal_samples / 2, vertical_samples * 5, "Raw Lidar Depth Data"));// Convert Depth,Intensity data to XYZI pointlidar->PushFilter(chrono_types::make_shared<ChFilterPCfromDepth>());// Add a noise model filter to the lidar sensorswitch (noise_model) {case CONST_NORMAL_XYZI:lidar->PushFilter(chrono_types::make_shared<ChFilterLidarNoiseXYZI>(0.1f, 0.001f, 0.001f, 0.01f));break;case NONE:// Don't add any noise modelsbreak;} Render the point cloudlidar->PushFilter(chrono_types::make_shared<ChFilterVisualizePointCloud>(640, 480, 2, "Lidar Point Cloud"));// Access the lidar data as an XYZI bufferlidar->PushFilter(chrono_types::make_shared<ChFilterXYZIAccess>());// add sensor to the managermanager->AddSensor(lidar);// 从JSON文件直接载入VLP16雷达配置// Lidar from JSON file - Velodyne VLP-16auto vlp16 = Sensor::CreateFromJSON(GetChronoDataFile("sensor/json/Velodyne/VLP-16.json"), box_body, offset_pose);manager->AddSensor(vlp16);float ch_time = 0.0;std::chrono::high_resolution_clock::time_point t1 = std::chrono::high_resolution_clock::now();while (ch_time < end_time) {// 传感器数据更新// Will render/save/filter automaticallymanager->Update();// 系统动力学更新sys.DoStepDynamics(step_size);// Get the current time of the simulationch_time = (float)sys.GetChTime();}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/680748.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【国产MCU】-CH32V307-基本定时器(BCTM)

基本定时器(BCTM) 文章目录 基本定时器(BCTM)1、基本定时器(BCTM)介绍2、基本定时器驱动API介绍3、基本定时器使用实例CH32V307的基本定时器模块包含一个16 位可自动重装的定时器(TIM6和TIM7),用于计数和在更新新事件产生中断或DMA 请求。 本文将详细介绍如何使用CH32…

苹果Mac键盘如何将 F1 到 F12 取消按Fn

苹果电脑安装了Win10操作系统之后&#xff0c;F1到F12用不了怎么办的解决方法。本文将介绍一些解决方法&#xff0c;帮助您解决无法使用F1到F12功能键的问题。 使用 Mac系统的人都知道&#xff0c;Mac系统默认是没有开启 F1-F12 的使用的&#xff0c;平时我们使用的系统都可以使…

AcWing 802. 区间和 离散化

文章目录 题目链接题目描述解题思路代码实现总结 题目链接 链接: AcWing 802. 区间和 题目描述 解题思路 离散化是一种常用的技巧&#xff0c;它能够将原始的连续数值转换为一组离散的值&#xff0c;从而简化问题的处理。在这段代码中&#xff0c;离散化的过程主要分为三个步…

2024全栈元年-thinkphp-数据操作

thinkphp 数据相关操作 1.单数据查询 1、单数据查询 ,Db::table(‘tp_stu’) 必须加前缀 2、如果只是查询符合条件的使用where find,如果没有符合条件的返回null 3、使用 findOrFail 没有数据会抛出异常 4、使用 findOrEmpty 没有数据会返回【】 5、得到最近一个原生SQL …

C++重新入门-指针篇

C 中的指针是一种非常重要的数据类型&#xff0c;它们存储了内存地址&#xff0c;可以用来直接访问和操作内存中的数据。指针提供了灵活性和直接性&#xff0c;但也需要谨慎使用&#xff0c;因为误用指针可能导致程序崩溃或安全漏洞。以下是对 C 指针的详细解释&#xff1a; 1…

那些也许你不知道的操作符!

前言 操作符有很多种&#xff0c;目前我们已经了解了一部分 例如最简单的、-、*、/、&#xff0c;还有我们学到的&&&#xff0c;||&#xff0c;!等&#xff0c;但是操作符可不是就只有这么些的&#xff0c;让我们一起来看看吧 目录 1. 移位操作符 原码、反码、补码…

当go get获取不到软件包时

当使用go get命令获取软件包时&#xff0c;如果无法成功获取&#xff0c;您可以尝试以下方法来解决问题&#xff1a; 检查网络连接&#xff1a;首先&#xff0c;确保您的计算机能够访问互联网&#xff0c;并且没有任何网络防火墙或代理设置阻止了go get命令的正常运行。 设置代…

Stream Query Denoising for Vectorized HD Map Construction

参考代码&#xff1a;截止2024.02未开源 动机与出发点 这篇文章是在StreamMapNet的基础上做的&#xff0c;为了在局部地图感知任务上提升时序上的感知稳定性&#xff0c;参考DN-DETR中的去噪方案&#xff0c;为局部地图感知提出一种针对局部地图元素的加噪声方案以及去噪逻辑。…

【开源】JAVA+Vue.js实现海南旅游景点推荐系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 用户端2.2 管理员端 三、系统展示四、核心代码4.1 随机景点推荐4.2 景点评价4.3 协同推荐算法4.4 网站登录4.5 查询景点美食 五、免责说明 一、摘要 1.1 项目介绍 基于VueSpringBootMySQL的海南旅游推荐系统&#xff…

深入理解XGBoost:集成学习与堆叠模型

导言 XGBoost是一种强大的集成学习算法&#xff0c;但在解决复杂问题时&#xff0c;单个模型可能无法达到最佳性能。集成学习和堆叠模型是两种有效的方法&#xff0c;可以进一步提高模型的性能。本教程将深入探讨如何在Python中应用集成学习和堆叠模型&#xff0c;使用代码示例…

Linux命令-break命令(结束for,while或until循环。)

说明 结束for&#xff0c;while或until循环&#xff0c;可指定退出几层循环。 语法 break [n]参数 n&#xff08;可选&#xff09;&#xff1a;大于等于1的整数&#xff0c;用于指定退出几层循环。 返回值 返回成功除非n小于1。 示例 # break的可选参数n缺省值为1。 # …

蓝牙BLE学习-安全

1.基本概念 蓝牙标准规定了5种基本的安全服务 身份验证:根据通信设备的蓝牙地址验证其身份。蓝牙不提供本地用户身份验证。保密性:确保只有授权的设备才能访问和查看传输的数据&#xff0c;防止窃听造成的信息泄露。授权(Authorization):在允许设备使用某项服务之前&#xff…

Verilog刷题笔记29

题目&#xff1a; Create a 100-bit binary ripple-carry adder by instantiating 100 full adders. The adder adds two 100-bit numbers and a carry-in to produce a 100-bit sum and carry out. To encourage you to actually instantiate full adders, also output the ca…

C++异常特性以及使用

异常 1.C传统的处理错误方式2.异常概念3.异常使用规则抛出和匹配规则 4.异常的重新抛出4.异常安全5.异常规范6.使用自定义的异常7.C标准异常体系7.异常优缺点 1.C传统的处理错误方式 终止程序&#xff1a;如assert&#xff0c;缺陷&#xff1a;用户难以接受。如发生内存错误&a…

[CUDA 学习笔记] Reduce 算子优化

Reduce 算子优化 注: 本文主要是对文章 【BBuf的CUDA笔记】三&#xff0c;reduce优化入门学习笔记 - 知乎 的学习整理 Reduce 又称之为归约, 即根据数组中的每个元素得到一个输出值, 常见的包括求和(sum)、取最大值(max)、取最小值(min)等. 前言 本文同样按照英伟达官方 PP…

C++ //练习 5.6 改写上一题的程序,使用条件运算符(参见4.7节,第134页)代替if else语句。

C Primer&#xff08;第5版&#xff09; 练习 5.6 练习 5.6 改写上一题的程序&#xff0c;使用条件运算符&#xff08;参见4.7节&#xff0c;第134页&#xff09;代替if else语句。 环境&#xff1a;Linux Ubuntu&#xff08;云服务器&#xff09; 工具&#xff1a;vim 代码…

EasyRecovery软件2024永久绿色免费版下载

EasyRecovery软件在数据恢复领域享有良好的声誉&#xff0c;并且被许多用户认为是一款好用且功能强大的软件。以下是对其功能和用户评价的简要概述&#xff1a; 恢复功能&#xff1a; EasyRecovery提供全面的数据恢复功能&#xff0c;可以恢复因删除、格式化、分区丢失、硬盘故…

Ubuntu20.04更新Cmake版本详解

最近在跑一个融合惯导定位的slam框架ins_eskf_kitti&#xff0c;在框架的安装过程中&#xff0c;需要对从GitHub上克隆下来的glog进行编译。其命令如下&#xff1a; glog&#xff1a; git clone https://github.com/google/glog.git cd glog mkdir build cd build cmake .. m…

3月第一批次❗教资认定流程简易版来啦

&#x1f4dd;材料准备 1、身份证 2、户口本/学生证/居住证/毕业证 3、考试合格证明(免试人员需要师范生职业能力证书) 4、普通话证书 5、学历证书或认证报告 6、近期一寸白底证件照 7、有效期内体检报告 8、个人承诺书(网上签署) 网上申报 1、上传个人承诺书 2、校验普通话证书…

使用 C++23 从零实现 RISC-V 模拟器(2):内存和总线

&#x1f449;&#x1f3fb; 文章汇总「从零实现模拟器、操作系统、数据库、编译器…」&#xff1a;https://okaitserrj.feishu.cn/docx/R4tCdkEbsoFGnuxbho4cgW2Yntc 内存和总线 上一部分将内存全部放到了 CPU 里面&#xff0c;总线的概念是隐含着的。这一部分将内存拆分出来…