【译】R包介绍:Online Random Forest

本文介绍了一种名为在线随机森林(ORF)的机器学习方法,该方法由Amir Saffari等人提出,并由Arthur Lui使用Python实现。作者顾全在Python实现的基础上,进一步用R语言重构了代码,并使其支持增量学习和批量学习。文中提供了详细的安装指南和使用示例,包括分类任务和回归任务的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

作者:顾全,浙江大学软件工程硕士,现任桃树科技算法工程师

地址:

https://github.com/ZJUguquan/OnlineRandomForest

参与:Cynthia

翻译:本文为天善智能编译,未经容许,禁止转载


介绍

Online Random Forest(ORF) 是由Amir Saffari等人最先提出。之后,Arthur Lui使用Python实现了算法。非常感谢他们的工作。在论文内容和Lui的算法的基础上,我通过R和R6包重构了代码。此外,ORF在此包中的实现,与randomForest结合,使它同时支持增量学习和批量学习,例如:在ORF的基础上构建树,然后通过ORF进行更新。通过这种方法,它将比以前快得多。

安装

if(!require(devtools)) install.packages("devtools")
devtools::install_github("ZJUguquan/OnlineRandomForest")

快速启动

  • 最小举例:增量学习

library(OnlineRandomForest)
param <- list('minSamples'= 1, 'minGain'= 0.1, 'numClasses'= 3, 'x.rng'= dataRange(iris[1:4]))
orf <- ORF$new(param, numTrees = 10)
for (i in 1:150) orf$update(iris[i, 1:4], as.integer(iris[i, 5]))
cat("Mean depth of trees in the forest is:", orf$meanTreeDepth(), "\n")
orf$forest[[2]]$draw()

## Mean depth of trees in the forest is: 3

## Root X4 < 1.21
## |----L: X3 < 2.38
##      |----L: Leaf 1
##      |----R: Leaf 2
## |----R: X4 < 2.15
##      |----L: X1 < 4.92
##           |----L: Leaf 3
##           |----R: Leaf 3
##      |----R: Leaf 3

  • 分类举例

library(OnlineRandomForest)

# data preparation
dat <- iris; dat[,5] <- as.integer(dat[,5])
x.rng <- dataRange(dat[1:4])
param <- list('minSamples'= 2, 'minGain'= 0.2, 'numClasses'= 3, 'x.rng'= x.rng)
ind.gen <- sample(1:150,30) # for generate ORF
ind.updt <- sample(setdiff(1:150, ind.gen), 100) # for uodate ORF
ind.test <- setdiff(setdiff(1:150, ind.gen), ind.updt) # for test

# construct ORF and update
rf <- randomForest::randomForest(factor(Species) ~ ., data = dat[ind.gen, ], maxnodes = 2, ntree = 100)
orf <- ORF$new(param)
orf$generateForest(rf, df.train = dat[ind.gen, ], y.col = "Species")
cat("Mean size of trees in the forest is:", orf$meanTreeSize(), "\n")


## Mean size of trees in the forest is: 3


for (i in ind.updt) {
 orf$update(dat[i, 1:4], dat[i, 5])
}
cat("After update, mean size of trees in the forest is:", orf$meanTreeSize(), "\n")


## After update, mean size of trees in the forest is: 11.9


# predict
orf$confusionMatrix(dat[ind.test, 1:4], dat[ind.test, 5], pretty = T)


##
##  
##    Cell Contents
## |-------------------------|
## |                       N |
## |           N / Row Total |
## |           N / Col Total |
## |-------------------------|
##
##  
## Total Observations in Table:  20
##
##  
##              | actual
##   prediction |         1 |         2 |         3 | Row Total |
## -------------|-----------|-----------|-----------|-----------|
##            1 |         4 |         0 |         0 |         4 |
##              |     1.000 |     0.000 |     0.000 |     0.200 |
##              |     1.000 |     0.000 |     0.000 |           |
## -------------|-----------|-----------|-----------|-----------|
##            2 |         0 |         9 |         2 |        11 |
##              |     0.000 |     0.818 |     0.182 |     0.550 |
##              |     0.000 |     1.000 |     0.286 |           |
## -------------|-----------|-----------|-----------|-----------|
##            3 |         0 |         0 |         5 |         5 |
##              |     0.000 |     0.000 |     1.000 |     0.250 |
##              |     0.000 |     0.000 |     0.714 |           |
## -------------|-----------|-----------|-----------|-----------|
## Column Total |         4 |         9 |         7 |        20 |
##              |     0.200 |     0.450 |     0.350 |           |
## -------------|-----------|-----------|-----------|-----------|
##
##


# compare
table(predict(rf, newdata = dat[ind.test,]) == dat[ind.test, 5])


## FALSE  TRUE
##     9    11


table(orf$predicts(X = dat[ind.test,]) == dat[ind.test, 5])


## FALSE  TRUE
##     2    18


  • 回归举例

# data preparation
if(!require(ggplot2)) install.packages("ggplot2")
data("diamonds", package = "ggplot2")
dat <- as.data.frame(diamonds[sample(1:53000,1000), c(1:6,8:10,7)])
for (col in c("cut","color","clarity")) dat[[col]] <- as.integer(dat[[col]]) # Don't forget this
x.rng <- dataRange(dat[1:9])
param <- list('minSamples'= 10, 'minGain'= 1, 'maxDepth' = 10, 'x.rng'= x.rng)
ind.gen <- sample(1:1000, 800)
ind.updt <- sample(setdiff(1:1000, ind.gen), 100)
ind.test <- setdiff(setdiff(1:1000, ind.gen), ind.updt)


# construct ORF
rf <- randomForest::randomForest(price ~ ., data = dat[ind.gen, ], maxnodes = 20, ntree = 100)
orf <- ORF$new(param)
orf$generateForest(rf, df.train = dat[ind.gen, ], y.col = "price")
orf$meanTreeSize()


## [1] 39


# and update
for (i in ind.updt) {
 orf$update(dat[i, 1:9], dat[i, 10])

}
orf$meanTreeSize()


## [1] 105.7


# predict and compare
if(!require(Metrics)) install.packages("Metrics")
preds.rf <- predict(rf, newdata = dat[ind.test,])
Metrics::rmse(preds.rf, dat$price[ind.test])


## [1] 988.8055


preds <- orf$predicts(dat[ind.test, 1:9])
Metrics::rmse(preds, dat$price[ind.test]) # make progress


## [1] 869.9613


其他用途

  • 在 Tree 类中

ta <- Tree$new("abc", NULL, NULL)
tb <- Tree$new(1, Tree$new(36), Tree$new(3))
tc <- Tree$new(89, tb, ta)
tc$draw()

# update tc
tc$right$updateChildren(Tree$new("666"), Tree$new(999))
tc$right$right$updateChildren(Tree$new("666"), Tree$new(999))
tc$draw()


  • 通过random Forest包配置一个Online random Tree,并升级

# data preparation
library(randomForest)
dat1 <- iris; dat1[,5] <- as.integer(dat1[,5])
rf <- randomForest(factor(Species) ~ ., data = dat1, maxnodes = 3)
treemat1 <- getTree(rf, 1, labelVar=F)
treemat1 <- cbind(treemat1, node.ind = 1:nrow(treemat1))
x.rng1 <- dataRange(dat1[1:4])
param1 <- list('minSamples'= 5, 'minGain'= 0.1, 'numClasses'= 3, 'x.rng'= x.rng1)
ind.gen <- sample(1:150,50) # for generate ORT
ind.updt <- setdiff(1:150, ind.gen) # for update ORT

# origin
ort2 <- ORT$new(param1)
ort2$draw()


## Root 1
##  Leaf 1


# generate a tree


ort2$generateTree(treemat1, df.node = dat1[ind.gen,])
ort2$draw()


## Root X3 < 2.45
## |----L: Leaf 1
## |----R: X3 < 4.75
##      |----L: Leaf 2
##      |----R: Leaf 3


# update this tree
for(i in ind.updt) {
 ort2$update(dat1[i,1:4], dat1[i,5])
}
ort2$draw()


## Root X3 < 2.45
## |----L: Leaf 1
## |----R: X3 < 4.75
##      |----L: Leaf 2
##      |----R: X4 < 2.19
##           |----L: X2 < 3.68
##                |----L: X1 < 7.12
##                     |----L: X3 < 4.06
##                          |----L: Leaf 1
##                          |----R: Leaf 3
##                     |----R: Leaf 3
##                |----R: Leaf 1
##           |----R: Leaf 3


大家都在看

2017年R语言发展报告(国内)

R语言中文社区历史文章整理(作者篇)

R语言中文社区历史文章整理(类型篇)


公众号后台回复关键字即可学习

回复 R                  R语言快速入门及数据挖掘 
回复 Kaggle案例  Kaggle十大案例精讲(连载中)
回复 文本挖掘      手把手教你做文本挖掘
回复 可视化          R语言可视化在商务场景中的应用 
回复 大数据         大数据系列免费视频教程 
回复 量化投资      张丹教你如何用R语言量化投资 
回复 用户画像      京东大数据,揭秘用户画像
回复 数据挖掘     常用数据挖掘算法原理解释与应用
回复 机器学习     人工智能系列之机器学习与实践
回复 爬虫            R语言爬虫实战案例分享

vae@vae-ASUS-TUF-Gaming-A15-FA507UU-FA507UU:~/primitive_ws/src/Primitive-Planner/src/scripts$ roslaunch primitive_planner swarm.launch ... logging to /home/vae/.ros/log/bd228878-6248-11f0-9b88-51c660762ec6/roslaunch-vae-ASUS-TUF-Gaming-A15-FA507UU-FA507UU-36532.log Checking log directory for disk usage. This may take a while. Press Ctrl-C to interrupt Done checking log file disk usage. Usage is <1GB. started roslaunch server http://vae-ASUS-TUF-Gaming-A15-FA507UU-FA507UU:40573/ SUMMARY ======== PARAMETERS * /drone_0_bridge_node/broadcast_ip: 127.0.0.255 * /drone_0_bridge_node/drone_id: 0 * /drone_0_bridge_node/odom_max_freq: 70 * /drone_0_odom_visualization/color/a: 1.0 * /drone_0_odom_visualization/color/b: 0.0 * /drone_0_odom_visualization/color/g: 0.0 * /drone_0_odom_visualization/color/r: 0.0 * /drone_0_odom_visualization/covariance_scale: 100.0 * /drone_0_odom_visualization/drone_id: 0 * /drone_0_odom_visualization/robot_scale: 0.24 * /drone_0_odom_visualization/tf45: False * /drone_0_pcl_render_node/cam_cx: 321.04638671875 * /drone_0_pcl_render_node/cam_cy: 243.44969177246094 * /drone_0_pcl_render_node/cam_fx: 387.229248046875 * /drone_0_pcl_render_node/cam_fy: 387.229248046875 * /drone_0_pcl_render_node/cam_height: 480 * /drone_0_pcl_render_node/cam_width: 640 * /drone_0_pcl_render_node/estimation_rate: 30.0 * /drone_0_pcl_render_node/map/x_size: 20.63661977236758 * /drone_0_pcl_render_node/map/y_size: 20.63661977236758 * /drone_0_pcl_render_node/map/z_size: 3.0 * /drone_0_pcl_render_node/sensing_horizon: 5.0 * /drone_0_pcl_render_node/sensing_rate: 10.0 * /drone_0_poscmd_2_odom/init_x: 0.3183098861837907 * /drone_0_poscmd_2_odom/init_y: 0.0 * /drone_0_poscmd_2_odom/init_z: 0.5 * /drone_0_primitive_planner_node/fsm/fail_safe: True * /drone_0_primitive_planner_node/fsm/flight_type: 2 * /drone_0_primitive_planner_node/fsm/no_replan_thresh: 0.5 * /drone_0_primitive_planner_node/fsm/realworld_experiment: True * /drone_0_primitive_planner_node/fsm/thresh_replan_time: 0.2 * /drone_0_primitive_planner_node/fsm/waypoint0_x: -0.3183098861837907 * /drone_0_primitive_planner_node/fsm/waypoint0_y: -0.0 * /drone_0_primitive_planner_node/fsm/waypoint0_z: 0.5 * /drone_0_primitive_planner_node/fsm/waypoint1_x: 0.0 * /drone_0_primitive_planner_node/fsm/waypoint1_y: 0.0 * /drone_0_primitive_planner_node/fsm/waypoint1_z: 0.0 * /drone_0_primitive_planner_node/fsm/waypoint2_x: 0.0 * /drone_0_primitive_planner_node/fsm/waypoint2_y: 0.0 * /drone_0_primitive_planner_node/fsm/waypoint2_z: 0.0 * /drone_0_primitive_planner_node/fsm/waypoint_num: 1 * /drone_0_primitive_planner_node/manager/arc_length: 3.0 * /drone_0_primitive_planner_node/manager/boxX: 6.0 * /drone_0_primitive_planner_node/manager/boxY: 6.0 * /drone_0_primitive_planner_node/manager/boxZ: 6.0 * /drone_0_primitive_planner_node/manager/depthCloudStackNum: 1 * /drone_0_primitive_planner_node/manager/drone_id: 0 * /drone_0_primitive_planner_node/manager/lamda_b: 50.0 * /drone_0_primitive_planner_node/manager/lamda_l: 200.0 * /drone_0_primitive_planner_node/manager/map_size_x: 20.63661977236758 * /drone_0_primitive_planner_node/manager/map_size_y: 20.63661977236758 * /drone_0_primitive_planner_node/manager/map_size_z: 3.0 * /drone_0_primitive_planner_node/manager/max_vel: 1.0 * /drone_0_primitive_planner_node/manager/primitiveFolder: /home/vae/primiti... * /drone_0_primitive_planner_node/manager/sampleSize: 10000 * /drone_0_primitive_planner_node/manager/swarm_clearence: 0.24 * /drone_0_primitive_planner_node/manager/voxelSize: 0.1 * /drone_0_traj_server/init_x: 0.3183098861837907 * /drone_0_traj_server/init_y: 0.0 * /drone_0_traj_server/init_z: 0.5 * /drone_0_traj_server/traj_server/max_vel: 1.0 * /drone_0_traj_server/traj_server/primitiveFolder: /home/vae/primiti... * /drone_0_traj_server/traj_server/time_delay_idx: 0 * /drone_0_traj_server/traj_server/time_forward: 1.0 * /random_forest/ObstacleShape/lower_hei: 0.0 * /random_forest/ObstacleShape/lower_rad: 0.2 * /random_forest/ObstacleShape/radius_h: 0.5 * /random_forest/ObstacleShape/radius_l: 0.7 * /random_forest/ObstacleShape/theta: 0.5 * /random_forest/ObstacleShape/upper_hei: 3.0 * /random_forest/ObstacleShape/upper_rad: 0.5 * /random_forest/ObstacleShape/z_h: 0.8 * /random_forest/ObstacleShape/z_l: 0.7 * /random_forest/map/circle_num: 0.46484179349639226 * /random_forest/map/obs_num: 0.46484179349639226 * /random_forest/map/resolution: 0.1 * /random_forest/map/x_size: -0.9642010096410315 * /random_forest/map/y_size: -0.9642010096410315 * /random_forest/map/z_size: 3.0 * /random_forest/min_distance: 0.8 * /random_forest/pub_rate: 1.0 * /rosdistro: noetic * /rosversion: 1.17.4 NODES / drone_0_bridge_node (swarm_bridge/bridge_node_udp) drone_0_odom_visualization (odom_visualization/odom_visualization) drone_0_pcl_render_node (local_sensing_node/pcl_render_node) drone_0_poscmd_2_odom (poscmd_2_odom/poscmd_2_odom) drone_0_primitive_planner_node (primitive_planner/primitive_planner_node) drone_0_traj_server (primitive_planner/traj_server) random_forest (map_generator/random_forest) rviz (rviz/rviz) auto-starting new master process[master]: started with pid [36557] ROS_MASTER_URI=http://localhost:11311 setting /run_id to bd228878-6248-11f0-9b88-51c660762ec6 process[rosout-1]: started with pid [36582] started core service [/rosout] process[drone_0_bridge_node-2]: started with pid [36589] process[random_forest-3]: started with pid [36590] process[rviz-4]: started with pid [36591] process[drone_0_primitive_planner_node-5]: started with pid [36597] process[drone_0_traj_server-6]: started with pid [36599] process[drone_0_poscmd_2_odom-7]: started with pid [36600] process[drone_0_odom_visualization-8]: started with pid [36601] process[drone_0_pcl_render_node-9]: started with pid [36611] [ERROR] [1752672500.302585947]: Illegal pathID=-1 [rosmsg_tcp_bridge] start running [drone_0_primitive_planner_node-5] process has finished cleanly log file: /home/vae/.ros/log/bd228878-6248-11f0-9b88-51c660762ec6/drone_0_primitive_planner_node-5*.log [WARN] [1752672500.791081325]: Finished generate random map [pcl::KdTreeFLANN::setInputCloud] Cannot create a KDTree with an empty input cloud! [WARN] [1752672500.794334498]: Global Pointcloud received.. [pcl::KdTreeFLANN::setInputCloud] Cannot create a KDTree with an empty input cloud! [drone_0_pcl_render_node-9] process has died [pid 36611, exit code -11, cmd /home/vae/primitive_ws/devel/lib/local_sensing_node/pcl_render_node ~global_map:=/map_generator/global_cloud ~odometry:=/drone_0_visual_slam/odom ~pcl_render_node/cloud:=/drone_0_pcl_render_node/cloud __name:=drone_0_pcl_render_node __log:=/home/vae/.ros/log/bd228878-6248-11f0-9b88-51c660762ec6/drone_0_pcl_render_node-9.log]. log file: /home/vae/.ros/log/bd228878-6248-11f0-9b88-51c660762ec6/drone_0_pcl_render_node-9*.log [INFO] [1752672501.293613925]: [Traj server]: ready. [rospack] Error: failed to parse command-line options: too many positional options have been specified on the command line [librospack]: error while executing command [rospack] Error: failed to parse command-line options: too many positional options have been specified on the command line [librospack]: error while executing command [rospack] Error: failed to parse command-line options: too many positional options have been specified on the command line [librospack]: error while executing command [WARN] [1752672547.878321128]: Shutdown request received. [WARN] [1752672547.878370290]: Reason given for shutdown: [user request] [random_forest-3] process has finished cleanly log file: /home/vae/.ros/log/bd228878-6248-11f0-9b88-51c660762ec6/random_forest-3*.log
最新发布
07-17
<think>我们面对的问题有两个错误信息:1. Illegal pathID=-1;2. pcl::KdTreeFLANN::setInputCloud错误(即尝试用空点云创建KDTree)。根据引用[4]中的经验,第二个错误通常与点云数据为空有关。而第一个错误“Illegal pathID=-1”可能与路径规划或地图数据有关。下面我们逐步分析: ### 错误1: Illegal pathID=-1 这个错误通常出现在导航栈(navigation stack)中,尤其是在使用全局规划器(global planner)时。`pathID`是路径的标识符,当值为-1时表示无效路径。可能原因括: - 全局规划器未能生成有效路径(例如,起点或终点设置在障碍物上,或者地图数据异常) - 规划器参数配置不当 ### 错误2: pcl::KdTreeFLANN::setInputCloud 这个错误明确表示尝试为一个空的点云创建KDTree。KDTree是用于高效近邻搜索的数据结构,要求输入点云非空。可能原因括: - 点云话题未发布数据(可能是传感器未发布,或者话题名称不匹配) - 点云数据在传输或转换过程中丢失(例如,在ROS消息到PCL点云转换时出现异常) ### 解决步骤 #### 1. 检查点云话题 根据引用[4]的经验,点云话题名称不匹配是常见原因。请确保: - 你的启动文件中订阅的点云话题名称与实际发布的话题名称一致。 - 使用`rostopic list`查看当前发布的话题,确认点云话题(如`/velodyne_points`)存在。 - 使用`rostopic echo /velodyne_points | head`查看点云数据是否正常。 如果话题名称不一致,修改启动文件或节点代码中的话题名称。例如,引用[4]中提到,将`utility.h`文件中的激光点云话题名称改为`/velodyne_points`。 #### 2. 检查点云数据流 如果话题名称正确,但点云仍为空,需检查点云数据流: - 确保传感器驱动程序正常运行,发布点云数据。 - 检查是否有节点在点云话题上进行了过滤,导致输出为空。 #### 3. 检查点云转换代码 如果使用了自定义节点进行点云处理,参考引用[2]和[3]中的转换代码,确保从ROS消息到PCL点云的转换正确。例如,引用[3]中的代码展示了如何将`sensor_msgs::PointCloud2`转换为`pcl::PointCloud<pcl::PointXYZ>`,并检查是否为空: ```cpp void Motion::Laser::connectMsg(const sensor_msgs::PointCloud2ConstPtr &ptrMsg) { // ... 转换代码 if (ptrCloud->empty()) { // 处理空点云情况 } } ``` 确保在转换后检查点云是否为空,并处理空点云情况。 #### 4. 检查全局规划器配置 对于“Illegal pathID=-1”错误,请检查: - 全局规划器参数(如`base_global_planner`)设置是否正确。 - 起点和终点是否在代价地图的可通行区域内(使用RViz检查)。 - 代价地图是否正常更新(无异常障碍物)。 #### 5. 运行诊断工具 - 使用`rviz`可视化点云和地图,确认数据是否正常。 - 使用`rosnode info <node_name>`查看节点订阅和发布的话题,确认连接关系。 ### 示例解决方案 假设错误是由于点云话题名称不匹配引起,修改步骤如下(以引用[4]为例): 1. 找到定义点云话题名称的文件(如`utility.h`)。 2. 将点云话题名称改为实际发布的话题(如`/velodyne_points`)。 3. 重新编运行:`catkin_make`,然后重新启动。 如果问题仍未解决,请提供更多上下文信息(如启动文件内容、节点代码片段等),以便进一步分析。 §§相关问题§§ 1. ROS中如何查看当前发布的所有话题? 2. 如何调试ROS节点中的点云处理代码? 3. 全局规划器常见错误有哪些?</think>### ROS Launch文件错误排查 针对您遇到的`Illegal pathID=-1`和`pcl::KdTreeFLANN::setInputCloud`错误,以下是系统性排查方案: --- ### **错误1:`Illegal pathID=-1`** #### 可能原因 1. **路径规划参数错误**:全局/局部规划器配置异常(如无效目标点) 2. **地图数据缺失**:导航栈未加载有效地图(如空地图或坐标系错误) 3. **TF变换异常**:机器人坐标系(如`base_link`)与地图坐标系(如`map`)未正确关联 #### 解决步骤: 1. **检查TF树**: ```bash rosrun tf view_frames # 生成TF树PDF evince frames.pdf # 查看坐标系连接 ``` 确保`map`→`odom`→`base_link`链路完整[^4]。 2. **验证目标点有效性**: ```bash rostopic echo /move_base/goal # 检查目标点数据 ``` 确保目标点在代价地图的可通行区域内。 3. **重置导航栈**: ```bash rosservice call /move_base/clear_costmaps ``` --- ### **错误2:`pcl::KdTreeFLANN::setInputCloud`** #### 关键原因(引用[4]经验) > **空点云输入**:KDTree要求非空点云,但算法收到空点云数据 #### 解决流程: 1. **确认点云话题数据流**: ```bash rostopic list | grep point_cloud # 查找实际发布的话题 rostopic hz /velodyne_points # 检查数据频率(确保>1Hz) rostopic echo /velodyne_points | head -n 1 # 查看消息结构 ``` 2. **修正话题名称匹配**(引用[4]方案): - 编辑`utility.h`文件: ```cpp // 确保与bag文件发布的话题一致 const std::string POINT_CLOUD_TOPIC = "/velodyne_points"; ``` - 重新编: ```bash catkin_make clean && catkin_make ``` 3. **检查点云转换代码**(引用[2][3]): ```cpp pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>); pcl::fromROSMsg(*input_msg, *cloud); // ROS消息转PCL格式 // 必须添加空点云检查! if (cloud->empty()) { ROS_ERROR("Received empty point cloud!"); return; } kdtree.setInputCloud(cloud); // 确保此处cloud非空 ``` 4. **传感器驱动验证**: - 单独运行传感器驱动节点: ```bash roslaunch velodyne_pointcloud VLP16_points.launch ``` - 使用`rviz`可视化点云: ```bash rviz -d $(rospack find velodyne_pointcloud)/launch/velodyne.rviz ``` --- ### **综合调试建议** 1. **逐步启动法**: ```bash roslaunch --screen your_pkg launch_file.launch # 显示所有节点输出 ``` 观察报错节点的完整堆栈信息。 2. **检查依赖项**: ```bash rospack depends1 your_pkg # 检查依赖 rosdep check your_pkg # 验证依赖安装 ``` 3. **数据集兼容性**: - 确认使用的bag文件与传感器配置匹配(如VLP-16 vs Ouster) ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值