Ubuntu20.04配置Kinect 2.0驱动安装和ROS环境下配置以及录制bag包和制作ORB-SLAM数据集

目录

  • 1. 安装libfreenect2
    • 1.1 下载官方文件
    • 1.2 安装build工具
    • 1.3 安装libusb
    • 1.4 安装urboJPEG
    • 1.5 安装OpenGL
    • 1.6 安装OpenCL
    • 1.7 安装OpenNI
    • 1.8 进入libfreenect2 文件夹,编译安装
    • 1.9 设定udev rules
    • 1.10 测试
  • 2. 配置ROS环境
    • 2.1 下载iai_kinect2包并安装
    • 2.2 相机上电,测试
  • 3 录制bag包和制作ORB-SLAM2数据集
    • 3.1 启动roscore,并启动相机
    • 3.2 录制
    • 3.3 提取录制的rosbag包内的rgb和depth
    • 3.4. 生成rgb.txt和depth.txt
    • 3.5 associate.py将rgb.txt和depth.txt进行匹配

1. 安装libfreenect2

1.1 下载官方文件

git clone https://github.com/OpenKinect/libfreenect2.git
cd libfreenect2

1.2 安装build工具

sudo apt-get install build-essential cmake pkg-config

1.3 安装libusb

sudo apt-get install libusb-1.0-0-dev

1.4 安装urboJPEG

sudo apt-get install libturbojpeg0-dev

1.5 安装OpenGL

sudo apt-get install libglfw3-dev

1.6 安装OpenCL

sudo apt-get install beignet-dev

1.7 安装OpenNI

sudo apt-get install libopenni2-dev

1.8 进入libfreenect2 文件夹,编译安装

cd libfreenect2
mkdir build && cd build
cmake ..
make
make install

注:在对libfreenect2进行make时报错:

fatal error: helper_math.h: No such file or directory

错误原因:
11.6版本之前的CUDA安装时会附带安装CUDA Samples,helper_math.h文件在/xxxx/NVIDIA_CUDA-10.1_Samples/common/inc/helper_math.h位置;11.6版本之后不再附带Samples,从而找不到该文件。

解决方法:
手动下载Samples
1.1. 从github下载Samples库,选择与那cuda同版本的sample库
https://github.com/NVIDIA/cuda-samples
在这里插入图片描述
1.2. 在cmake之前添加相应路径到CPATH
cd <sample_dir>
make

1.3 将help_math.h复制到那报错的路径下
cp /home/kunyuwan/cuda-samples/Common/helper_math.h [Where the error occurs]

1.9 设定udev rules

sudo cp /home/kunyuwan/libfreenect2/platform/linux/udev/90-kinect2.rules /etc/udev/rules.d/

1.10 测试

./bin/Protonect

不出意外,看到以下界面
在这里插入图片描述

错误内容 :在运行./bin/Protonect可能遇到的问题
在这里插入图片描述

解决方法
修改~./bashrc
添加一行在文件里面:export MESA_GL_VERSION_OVERRIDE=3.3
之后执行 soure ~/.bashrc即可

2. 配置ROS环境

2.1 下载iai_kinect2包并安装

cd ~/catkin_ws/src/
git clone https://github.com/code-iai/iai_kinect2.git
cd iai_kinect2
rosdep install -r --from-paths .
cd ~/catkin_ws
catkin_make

编译过程可能出现以下的问题
(1)CXX14 error:
在这里插入图片描述

解决方法
在kinect2_viewer文件夹下的CMakeLists.txt中,
在开头,把CHECK_CXX_COMPILER_FLAG(“-std=c++11” COMPILER_SUPPORTS_CXX11)
改成CHECK_CXX_COMPILER_FLAG(“-std=c++14” COMPILER_SUPPORTS_CXX14)
后面的一句也改为SET(CMAKE_CXX_FLAGS “${CMAKE_CXX_FLAGS} -std=c++14”)

(2)OpenCV各种宏定义找不到:
如果按照的是OpenCV4的版本,可能会出现各种宏定义找不到的问题

解决方法:把所有include了opencv的cpp文件都添加了同样的库文件
kinect2_bridge/src/kinect2_bridge.cpp
kinect2_calibration/src/kinect2_calibration.cpp
kinect2_viewer/src/viewer.cpp
在这三个文件中添加以下头文件
#include <opencv2/imgproc/types_c.h>
#include <opencv2/imgproc/imgproc_c.h>
#include <opencv2/imgcodecs/legacy/constants_c.h>
#include <opencv2/highgui/highgui.hpp>

(3)/home/mh/catkin_ws/devel/lib//libkinect2_bridge_nodelet.so: undefined symbol: _ZN2cv3MatC1Ev
报错全部内容为:

/home/mh/catkin_ws/devel/lib//libkinect2_bridge_nodelet.so: undefined symbol: _ZN2cv3MatC1Ev
[FATAL] [1712663692.831371988]: Failed to load nodelet '/kinect2_points_xyzrgb_sd` of type `depth_image_proc/point_cloud_xyzrgb` to manager `kinect2'
[FATAL] [1712663692.831424141]: Failed to load nodelet '/kinect2_bridge` of type `kinect2_bridge/kinect2_bridge_nodelet` to manager `kinect2'
[kinect2-1] process has died [pid 7561, exit code 127, cmd /opt/ros/melodic/lib/nodelet/nodelet manager __name:=kinect2 __log:=/home/mh/.ros/log/1b531282-f666-11ee-bc63-088fc3ed4c91/kinect2-1.log].
log file: /home/mh/.ros/log/1b531282-f666-11ee-bc63-088fc3ed4c91/kinect2-1*.log
[kinect2_bridge-2] process has died [pid 7562, exit code 255, cmd /opt/ros/melodic/lib/nodelet/nodelet load kinect2_bridge/kinect2_bridge_nodelet kinect2 __name:=kinect2_bridge __log:=/home/mh/.ros/log/1b531282-f666-11ee-bc63-088fc3ed4c91/kinect2_bridge-2.log].
log file: /home/mh/.ros/log/1b531282-f666-11ee-bc63-088fc3ed4c91/kinect2_bridge-2*.log
[kinect2_points_xyzrgb_sd-3] process has died [pid 7563, exit code 255, cmd /opt/ros/melodic/lib/nodelet/nodelet load depth_image_proc/point_cloud_xyzrgb kinect2 rgb/camera_info:=kinect2/sd/camera_info rgb/image_rect_color:=kinect2/sd/image_color_rect depth_registered/image_rect:=kinect2/sd/image_depth_rect depth_registered/points:=kinect2/sd/points __name:=kinect2_points_xyzrgb_sd __log:=/home/mh/.ros/log/1b531282-f666-11ee-bc63-088fc3ed4c91/kinect2_points_xyzrgb_sd-3.log].
log file: /home/mh/.ros/log/1b531282-f666-11ee-bc63-088fc3ed4c91/kinect2_points_xyzrgb_sd-3*.log

解决方法:
导致该问题的原因可能是电脑中存在多个OpenCV的版本,使用find无法找到OpenCV的路径,可以在iai_kinect2文件里面的所以cmakelist里面指定OpenCV的绝对路径,从而可以直接找到OpenCV

2.2 相机上电,测试

打开一个新的终端测试话题订阅

cd ~/catkin_ws
source devel/setup.bash
roslaunch kinect2_bridge kinect2_bridge.launch

打开一个新的终端查看实时画面。

rqt

输入rostopic list可以查看订阅的对应话题
此时再打开一个新的终端,运行以下命令:

cd ~/catkin_ws
source devel/setup.bash
rosrun kinect2_viewer kinect2_viewer kinect2 sd cloud

显示点云相机窗口,则代表启动成功!!!

3 录制bag包和制作ORB-SLAM2数据集

3.1 启动roscore,并启动相机

打开两个终端,分别执行以下命令

roscore
cd ~/catkin_ws
source devel/setup.bash
roslaunch kinect2_bridge kinect2_bridge.launch

3.2 录制

在打开一个终端

rosbag record  -o xxx.bag /kinect2/qhd/image_color_rect /kinect2/qhd/image_depth_rect

3.3 提取录制的rosbag包内的rgb和depth

注意修改路径和订阅的话题!!!

# coding:utf-8
#!/usr/bin/python# Extract images from a bag file.#PKG = 'beginner_tutorials'
import roslib;   #roslib.load_manifest(PKG)
import rosbag
import rospy
import cv2
from sensor_msgs.msg import Image
from cv_bridge import CvBridge
from cv_bridge import CvBridgeError# Reading bag filename from command line or roslaunch parameter.
#import os
#import sysrgb_path = '/home/kunyuwan/test_kinectv2_3/rgb/'    # 已经建立好的存储rgb彩色图文件的目录(最好改成绝对路径)
depth_path= '/home/kunyuwan/test_kinectv2_3/depth/' # 已经建立好的存储深度图文件的目录(最好改成绝对路径)class ImageCreator():def __init__(self):self.bridge = CvBridge()with rosbag.Bag('/home/kunyuwan/test_kinectv2_3/4_2024-04-03-21-40-12.bag', 'r') as bag:  #要读取的bag文件(最好改成绝对路径);for topic,msg,t in bag.read_messages(): if topic == "/kinect2/qhd/image_color_rect": #图像的topic 注意不要错了;try:cv_image = self.bridge.imgmsg_to_cv2(msg,"bgr8")except CvBridgeError as e:print(e)timestr = "%.6f" %  msg.header.stamp.to_sec()#%.6f表示小数点后带有6位,可根据精确度需要修改;image_name = timestr+ ".png" #图像命名:时间戳.pngcv2.imwrite(rgb_path + image_name, cv_image)  #保存;elif topic == "/kinect2/qhd/image_depth_rect": #图像的topic;try:cv_image = self.bridge.imgmsg_to_cv2(msg,"16UC1")except CvBridgeError as e:print(e)timestr = "%.6f" %  msg.header.stamp.to_sec()#%.6f表示小数点后带有6位,可根据精确度需要修改;image_name = timestr+ ".png" #图像命名:时间戳.pngcv2.imwrite(depth_path + image_name, cv_image)  #保存;if __name__ == '__main__':#rospy.init_node(PKG)try:image_creator = ImageCreator()except rospy.ROSInterruptException:pass

3.4. 生成rgb.txt和depth.txt

#include <iostream>
#include <fmt/os.h>
#include <fmt/core.h>
#include <fmt/format.h>
#include <string>
#include <vector>
#include <algorithm>
extern "C"
{
#include <sys/types.h>
#include <sys/dir.h>
#include <dirent.h>
}
using namespace std;void getNamesToText(const char *filepath,const char *filetype)
{DIR *streamp = nullptr;dirent *dep = nullptr;string filename(filepath);auto out = fmt::output_file("./"+string(filetype));vector<string> names;streamp = opendir(filepath);errno = 0;while ((dep = readdir(streamp)) != NULL){if ((dep->d_name == ".") || (dep->d_name == "..")){continue;}names.push_back(dep->d_name);}if (errno != 0){fmt::print("error");}closedir(streamp);for (vector<string>::iterator ite = names.begin(); ite != names.end();){if ((*ite == ".") || (*ite == "..")){ite = names.erase(ite); }else{++ite;}}sort(names.begin(), names.end());for (auto &item : names){auto pos = item.find_last_of('.');string filenum;for (int i = 0; i < pos; i++){filenum += item[i];}if(strcmp(filetype,"rgb.txt")==0){out.print("{} rgb/{}\n",filenum,item);}else if(strcmp(filetype,"depth.txt")==0){out.print("{} depth/{}\n",filenum,item);}}fmt::print("{} finished\n",filetype);
}int main(int argc, char *argv[])
{if(argc<3){fmt::print("Usage: [executable] [rgb/depth path] [type]");return 0;}const char *filepath =argv[1];const char *filetype =argv[2];getNamesToText(filepath,filetype);return 0;
}

注意安装fmt

git clone  https://github.com/fmtlib/fmt.git
cd fmt
mkdir build
cd build
cmake ..
make
sudo make install

运行命令

g++ 文件名.cpp -lfmt
./a.out rgb rgb.txt # 文件夹路径和生成文件路径
./a.out depth depth.txt # 文件夹路径和生成文件路径

3.5 associate.py将rgb.txt和depth.txt进行匹配

#!/usr/bin/python
# Software License Agreement (BSD License)
#
# Copyright (c) 2013, Juergen Sturm, TUM
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
#  * Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
#  * Redistributions in binary form must reproduce the above
#    copyright notice, this list of conditions and the following
#    disclaimer in the documentation and/or other materials provided
#    with the distribution.
#  * Neither the name of TUM nor the names of its
#    contributors may be used to endorse or promote products derived
#    from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
# Requirements: 
# sudo apt-get install python-argparse"""
The Kinect provides the color and depth images in an un-synchronized way. This means that the set of time stamps from the color images do not intersect with those of the depth images. Therefore, we need some way of associating color images to depth images.For this purpose, you can use the ''associate.py'' script. It reads the time stamps from the rgb.txt file and the depth.txt file, and joins them by finding the best matches.
"""import argparse
import sys
import os
import numpydef read_file_list(filename):"""Reads a trajectory from a text file. File format:The file format is "stamp d1 d2 d3 ...", where stamp denotes the time stamp (to be matched)and "d1 d2 d3.." is arbitary data (e.g., a 3D position and 3D orientation) associated to this timestamp. Input:filename -- File nameOutput:dict -- dictionary of (stamp,data) tuples"""file = open(filename)data = file.read()lines = data.replace(","," ").replace("\t"," ").split("\n") list = [[v.strip() for v in line.split(" ") if v.strip()!=""] for line in lines if len(line)>0 and line[0]!="#"]list = [(float(l[0]),l[1:]) for l in list if len(l)>1]return dict(list)def associate(first_list, second_list,offset,max_difference):"""Associate two dictionaries of (stamp,data). As the time stamps never match exactly, we aim to find the closest match for every input tuple.Input:first_list -- first dictionary of (stamp,data) tuplessecond_list -- second dictionary of (stamp,data) tuplesoffset -- time offset between both dictionaries (e.g., to model the delay between the sensors)max_difference -- search radius for candidate generationOutput:matches -- list of matched tuples ((stamp1,data1),(stamp2,data2))"""first_keys = list(first_list)second_keys = list(second_list)potential_matches = [(abs(a - (b + offset)), a, b) for a in first_keys for b in second_keys if abs(a - (b + offset)) < max_difference]potential_matches.sort()matches = []for diff, a, b in potential_matches:if a in first_keys and b in second_keys:first_keys.remove(a)second_keys.remove(b)matches.append((a, b))matches.sort()return matchesif __name__ == '__main__':# parse command lineparser = argparse.ArgumentParser(description='''This script takes two data files with timestamps and associates them   ''')parser.add_argument('first_file', help='first text file (format: timestamp data)')parser.add_argument('second_file', help='second text file (format: timestamp data)')parser.add_argument('--first_only', help='only output associated lines from first file', action='store_true')parser.add_argument('--offset', help='time offset added to the timestamps of the second file (default: 0.0)',default=0.0)parser.add_argument('--max_difference', help='maximally allowed time difference for matching entries (default: 0.02)',default=0.02)args = parser.parse_args()first_list = read_file_list(args.first_file)second_list = read_file_list(args.second_file)matches = associate(first_list, second_list,float(args.offset),float(args.max_difference))    if args.first_only:for a,b in matches:print("%f %s"%(a," ".join(first_list[a])))else:for a,b in matches:print("%f %s %f %s"%(a," ".join(first_list[a]),b-float(args.offset)," ".join(second_list[b])))

运行指令

chmod 777 associate.py
./associate.py rgb.txt depth.txt > associate.txt

最终得到的文件夹内部的结构如图即可:
在这里插入图片描述

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

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

相关文章

十六进制前缀为Ox还是0x???

16进制的前缀是0x&#xff0c;数字零和英文字母X。 十六进制&#xff08;英文名称&#xff1a;Hexadecimal&#xff09;&#xff0c;是计算机中数据的一种表示方法。同我们日常生活中的表示法不一样。它由0-9&#xff0c;A-F组成&#xff0c;字母不区分大小写。与10进制的对应…

网络安全---RSA公钥加密与签名

实验项目&#xff1a;RSA公钥加密与签名实验 1.实验目的 本实验的学习目标是让学生获得 RSA 算法的动手经验。 通过课堂学习&#xff0c;学生应该已经了解 RSA 算法的理论部分&#xff0c; 知道在数学上如何生成公钥、私钥以及如何执行加密、解密和签名生成、验证。 通过使用…

数字图像处理与交叉学科中名词的拧巴

特征提取 图像处理——对图像、目标或特征点进行定量描述的方法及过程。 模式识别——对原特征进行特征变换&#xff0c;从高维空间到低维空间映射。 特征向量 模式识别、图像处理——一个观测包括多个变量&#xff0c;样本的多个特征组成特征向量。 线性代数——特征值对应的…

构建强健身体的未来:健身管理平台微服务架构解析

在现代社会&#xff0c;人们越来越关注健康和身体素质的提升。健身管理平台应运而生&#xff0c;为用户提供个性化的健身计划、监测和管理工具。微服务架构作为一种灵活且可扩展的系统设计方法&#xff0c;为健身管理平台提供了高效、可靠的基础。 1. 概述健身管理平台微服务架…

python|sort_values()排序

sort_value()可以用来对值&#xff08;比如说年龄&#xff09;进行排序 根据 ‘Age’ 列进行升序排序&#xff0c;如果 ‘Age’ 相同则根据 ‘Name’ 列进行降序排序 df_sorted_multi df.sort_values(by[Age, Name], ascending[True, False]) print(df_sorted_multi)

正则表达式 速成

正则表达式的作用 正则表达式&#xff0c;又称规则表达式,&#xff08;Regular Expression&#xff0c;在代码中常简写为regex、regexp或RE&#xff09;&#xff0c;是一种文本模式&#xff0c;包括普通字符&#xff08;例如&#xff0c;a 到 z 之间的字母&#xff09;和特殊字…

Tailwind 4.0 即将到来:前端开发的“速度与激情”

随着前端开发技术的不断进步&#xff0c;我们每天都在寻找更快、更简洁的解决方案来提升我们的开发效率和用户体验。今天&#xff0c;我要为大家介绍一项令人振奋的新技术进展——Tailwind 4.0的来临&#xff01; 对于经常使用Tailwind的朋友们来说&#xff0c;这个消息无疑是激…

规则引擎之LiteFlow应用

官网地址&#xff1a;LiteFlow DEMO 整体结构 1.引入maven依赖 <dependency><groupId>com.yomahub</groupId><artifactId>liteflow-spring-boot-starter</artifactId><version>2.11.4.2</version> </dependency> 2. 配置yml …

mysql数据库备份脚本.sh

mysql数据库备份脚本.sh #!/bin/bash #备份路径 BAKDIR/home/peter/date %Y-%m-%d #要备份的数据库 MYSQLDBtest #使用哪个用户备份 MYSQLUSRroot #判断是否是root用户执行此脚本 if [ $UID -ne 0 ] then echo This scripts must use the root user!!! sleep 2 exit…

HDFS [MSST‘10] 论文阅读笔记

原论文:The Hadoop Distributed File System (MSST’10) HDFS关键技术要点概览 设计目标:HDFS旨在可靠地存储大型数据集,并以高带宽流式传输这些数据集到用户应用程序。它通过在大量服务器上分布存储和计算资源,使得资源可以随着需求的增长而扩展,同时保持经济高效。架构组…

24年权威数学建模报名通知汇总(含妈妈杯、国赛、美赛、电工杯、数维杯、五一数模、深圳杯......)

1、MathorCup比赛 报名时间&#xff1a;2024年4月11日中午12点&#xff08;周四&#xff09; 比赛开始时间&#xff1a;2024年4月12日上午8时&#xff08;周五&#xff09; 比赛结束时间&#xff1a;2024年4月16日上午9时&#xff08;周二&#xff09; 报名费用&#xff1a…

HarmonyOS 开发-Worker子线程中解压文件

介绍 本示例介绍在Worker 子线程使用ohos.zlib 提供的zlib.decompressfile接口对沙箱目录中的压缩文件进行解压操作&#xff0c;解压成功后将解压路径返回主线程&#xff0c;获取解压文件列表。 效果图预览 使用说明 点击解压按钮&#xff0c;解压test.zip文件&#xff0c;显…

基于springboot实现医院管理系统项目【项目源码+论文说明】

基于springboot实现医院管理系统演示 摘要 随着信息互联网信息的飞速发展&#xff0c;医院也在创建着属于自己的管理系统。本文介绍了医院管理系统的开发全过程。通过分析企业对于医院管理系统的需求&#xff0c;创建了一个计算机管理医院管理系统的方案。文章介绍了医院管理系…

RabbitMQ如何保证消息的幂等性???

在RabbitMQ中&#xff0c;保证消费者的幂等性主要依赖于业务设计和实现&#xff0c;而非RabbitMQ本身提供的一种直接功能。 在基于Spring Boot整合RabbitMQ的场景下&#xff0c;要保证消费者的幂等性&#xff0c;通常需要结合业务逻辑设计以及额外的技术手段来实现。以下是一个…

Redis的双写一致性问题

双写一致性问题 1.先删除缓存或者先删除数据库都可能出现脏数据。 2.删除两次缓存&#xff0c;可以在一定程度上降低脏数据的出现。 3.延时是因为数据库一般采用主从分离&#xff0c;读写分离。延迟一会是让主节点把数据同步到从节点。 1.读写锁保证数据的强一致性 因为一般放…

【CVE复现计划】CVE-2024-0195

CVE-2024-0195 简介&#xff1a; SpiderFlow是新一代开源爬虫平台&#xff0c;以图形化方式定义爬虫流程&#xff0c;不写代码即可完成爬虫。基于springbootlayui开发的前后端不分离,也可以进行二次开发。该系统/function/save接口存在RCE漏洞&#xff0c;攻击者可以构造恶意命…

蓝桥杯加训

1.两只塔姆沃斯牛&#xff08;模拟&#xff09; 思路&#xff1a;人和牛都记录三个数据&#xff0c;当前坐标和走的方向&#xff0c;如果人和牛的坐标和方向走重复了&#xff0c;那就说明一直在绕圈圈&#xff0c;无解 #include<iostream> using namespace std; const i…

评论发布完整篇(react版)

此篇文章阐述评论的最新、最热之间的tab标签切换&#xff08;包括当前所在tab标签的高亮显示问题&#xff09;&#xff1b;当前评论的删除&#xff1b;除此之外还延伸了用户的评论实时发布功能。其中最新tab标签所展示的内容是根据当前评论点赞数来进行排序&#xff0c;点赞数量…

人工智能前沿成科技竞争新高地

以下文章来源&#xff1a;经济参考报 近日&#xff0c;首届中国具身智能大会&#xff08;CEAI 2024&#xff09;在上海举行。作为人工智能领域的前沿热点&#xff0c;具身智能正逐步走进现实&#xff0c;成为当前全球科技竞争的新高地、未来产业的新赛道、经济发展的新引擎。 “…

厂房起火3D消防灭火安全救援模拟演练

深圳VR公司华锐视点依托前沿的VR虚拟现实制作、三维仿真和图形图像渲染技术&#xff0c;将参训者带入栩栩如生的火灾现场。佩戴VR头盔&#xff0c;参训者将真切体验火势蔓延的紧张与危机&#xff0c;身临其境地感受火灾的恐怖。 并且消防安全VR虚拟现实演练系统精心模拟了住宅、…