EasyAR4.0使用说明(Unity3D)(七)----稀疏空间地图

2023-11-09

稀疏空间地图的对应用环境的要求和平面图像识别可以比照理解,周围环境需要足够丰富,不能有大片的单色区域,透明区域。此外,光照,角度都会对建立地图和定位产生影响。

官方给出了建立地图和定位地图的建议。https://help.easyar.cn/EasyAR%20Sense/v4/Guides/EasyAR-Sparse-Spatial-Map.html

总体说明

稀疏空间地图的基础是运动跟踪,所有在场景种首先要有运动跟踪的全套游戏对象包括设置。然后主要的是 SparseSpatialMapWorker 和 SparseSpatialMap 这两个游戏对象。

总体说明

SparseSpatialMapWorker 游戏对象相关

SparseSpatialMapWorker游戏对象相关

  • Locailzation Mode 属性在建立地图的时候通常选“UntilSuccess”,在定位的时候,通常选“KeepUpdate”。
  • Use Global Service Config 选项可以设置是否使用全局定义的稀疏空间地图信息。
  • BuilderMapController.Host(…)方法是保存地图的方法,需要输入的参数是地图的名称和地图的缩略图,缩略图可以输入“null”。
  • BuilderMapController.MapHost 事件用于返回地图保存情况的事件。事件有 3 个参数,是地图保存成功后的名称,ID,是否保存成功的状态,还有错误信息。
  • Localizer.startLocalization()和 Localizer.stopLocalization()方法是用来启动和停止本地稀疏空间定位的方法。如果 SparseSpatialMap 游戏对象设置了地图的 ID 和名称的时候,默认会自动启动地图定位。

SparseSpatialMap 游戏对象相关

SparseSpatialMap 游戏对象是稀疏空间地图在 Unity 中的载体,每个稀疏空间地图在定位的时候对应一个 SparseSpatialMap 游戏对象,同一个场景可以同时有多个稀疏空间地图。希望在某个稀疏空间地图中放置的虚拟物体,将其对应的游戏对象放置到对应的 SparseSpatialMap 游戏对象下成为其子游戏对象即可。

SparseSpatialMap游戏对象相关

  • Source Type 属性用于设置稀疏空间地图的作用,即是用于建立地图“Map Builder”还是用于定位“Map Manager”。
  • Map Worker 属性必须关联对应的 SparseSpatialMapWorker 游戏对象。通常不需要设置。
  • Show Point Cloud 选项可以设置是否点云的效果。在建图的时候,显示点云的效果能帮助使用者更好的建立稀疏空间地图。
  • MapLoad 事件是指定的稀疏空间地图从服务器端下载到本地触发的事件。
  • MapLocalized、MapStopLocalize 事件是地图实现定位和停止定位的事件。MapLocalized 可以被触发多次,或者理解为可以不断修正位置。

建立地图

  • 设置场景中的 Main Camera 的 Clear Flags 属性为 Solid Color。
  • 将 EasyAR/Prefabs/Composites 目录下的 EasyAR_SparseSpatialMapWorker 预制件拖到场景中。

建立地图

  • 将 EasyAR/Prefabs/Primitives 目录下的 WorldRoot 预制件拖到场景中。
  • 选中 EasyAR_ SparseSpatialMapWorker 游戏对象,将 WorldRoot 游戏对象拖到 World Root Controller 属性中为其赋值。

建立地图

  • 将 EasyAR/Prefabs/Primitives 目录下的 SparseSpatialMap 预制件拖到场景中。

建立地图

在 SparseSpatialMap 游戏对象下再添加用于分辨方向的模型,用形状来和 WorldRoot 游戏对象下的进行区分。

建立地图

添加界面和脚本。界面中有保存按钮和显示反馈信息的文本框。

建立地图

脚本说明:
保存完地图需要将获取的ID和Name保存下来。官方没有提供稀疏空间地图访问的API。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using easyar;
using System;

public class BuildMapController : MonoBehaviour
{
    //稀疏空间地图相关对象
    private ARSession session;
    private SparseSpatialMapWorkerFrameFilter mapWorker;
    private SparseSpatialMapController map;
    /// <summary>
    /// 保存按钮
    /// </summary>
    private Button btnSave;
    /// <summary>
    /// 显示文本
    /// </summary>
    private Text text;

    void Start()
    {
        //稀疏空间地图初始
        session = FindObjectOfType<ARSession>();
        mapWorker = FindObjectOfType<SparseSpatialMapWorkerFrameFilter>();
        map = FindObjectOfType<SparseSpatialMapController>();
        //注册追踪状态变化事件
        session.WorldRootController.TrackingStatusChanged += OnTrackingStatusChanged;
        //初始化保存按钮
        btnSave = GameObject.Find("/Canvas/Button").GetComponent<Button>();
        btnSave.onClick.AddListener(Save);
        btnSave.interactable = false;
        if (session.WorldRootController.TrackingStatus == MotionTrackingStatus.Tracking)
        {
            btnSave.interactable = true;
        }
        else
        {
            btnSave.interactable = false;
        }
        //初始化显示文本
        text = GameObject.Find("/Canvas/Panel/Text").GetComponent<Text>();
    }

    /// <summary>
    /// 保存地图方法
    /// </summary>
    private void Save()
    {
        btnSave.interactable = false;
        //注册地图保存结果反馈事件
        mapWorker.BuilderMapController.MapHost += SaveMapHostBack;
        //保存地图
        try
        {
            //保存地图
            mapWorker.BuilderMapController.Host("LearnMap" + DateTime.Now.ToString("yyyyMMddHHmm"), null);
            text.text = "开始保存地图,请稍等。";
        }
        catch (Exception ex)
        {
            btnSave.interactable = true;
            text.text = "保存出错:" + ex.Message;
        }
    }

    /// <summary>
    /// 保存地图反馈
    /// </summary>
    /// <param name="mapInfo">地图信息</param>
    /// <param name="isSuccess">成功标识</param>
    /// <param name="error">错误信息</param>
    private void SaveMapHostBack(SparseSpatialMapController.SparseSpatialMapInfo mapInfo, bool isSuccess, string error)
    {
        if (isSuccess)
        {
            PlayerPrefs.SetString("MapID", mapInfo.ID);
            PlayerPrefs.SetString("MapName", mapInfo.Name);
            text.text = "地图保存成功。\r\nMapID:" + mapInfo.ID + "\r\nMapName:" + mapInfo.Name;
        }
        else
        {
            btnSave.interactable = true;
            text.text = "地图保存出错:" + error;
        }
    }

    /// <summary>
    /// 摄像机状态变化
    /// </summary>
    /// <param name="status">状态</param>
    private void OnTrackingStatusChanged(MotionTrackingStatus status)
    {
        if (status == MotionTrackingStatus.Tracking)
        {
            btnSave.interactable = true;
            text.text = "进入跟踪状态。";
        }
        else
        {
            btnSave.interactable = false;
            text.text = "退出跟踪状态。" + status.ToString();
        }
    }
}

打包以后在设备上运行。进入以后,会显示点云效果。稀疏空间地图SparseSpatialMap游戏对象和运动跟踪WorldRoot游戏对象两者的原点方向都是一致的。当扫描完周围空间以后,点击保存按钮,就可以将地图保存到服务器。在提示文本中会显示地图的ID和名称。

建立地图

本地化地图

  • 将建立地图场景另存为作为本地化的场景。
  • 选中SparseSpatialMapWorker游戏对象,修改Localization Mode属性为Keep Update。

本地化地图

  • 选中SparseSpatialMap游戏对象,修改Source Type属性为Map Manager。

本地化地图

修改界面,设置界面里有2个输入框,分别用于输入地图ID和地图名称,有一个文本框显示提示内容,2个按钮,用于本地化地图和停止定位。

本地化地图

替换脚本。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System;
using easyar;


public class LocalizeMapController : MonoBehaviour
{
    //稀疏空间地图相关对象
    private ARSession session;
    private SparseSpatialMapWorkerFrameFilter mapWorker;
    private SparseSpatialMapController map;
    /// <summary>
    ///地图 ID输入框
    /// </summary>
    public InputField inputID;
    /// <summary>
    /// 地图名称输入框
    /// </summary>
    public InputField inputName;
    /// <summary>
    /// 文本显示
    /// </summary>
    public Text text;


    void Start()
    {
        //稀疏空间地图初始
        session = FindObjectOfType<ARSession>();
        mapWorker = FindObjectOfType<SparseSpatialMapWorkerFrameFilter>();
        map = FindObjectOfType<SparseSpatialMapController>();

        //如果之前有建立过地图且文本框没有预设值
        if (inputID.text.Length <= 0)
        {
            inputID.text = PlayerPrefs.GetString("MapID", "");
            inputName.text = PlayerPrefs.GetString("MapName", "");
        }

        map.MapLoad += MapLoadBack; //注册地图加载事件
        map.MapLocalized += LocalizedMap;   //注册定位成功事件
        map.MapStopLocalize += StopLocalizeMap; //注册停止定位事件

        StartLocalization();
    }

    /// <summary>
    /// 地图加载反馈
    /// </summary>
    /// <param name="mapInfo">地图信息</param>
    /// <param name="isSuccess">是否成功</param>
    /// <param name="error">错误信息</param>
    private void MapLoadBack(SparseSpatialMapController.SparseSpatialMapInfo mapInfo, bool isSuccess, string error)
    {
        if (isSuccess)
        {
            text.text = "地图" + mapInfo.Name + "加载成功。";
        }
        else
        {
            text.text = "地图加载失败。" + error;
        }
    }
    /// <summary>
    /// 地图定位成功
    /// </summary>
    private void LocalizedMap()
    {
        text.text = "稀疏空间地图定位成功。" + DateTime.Now.ToShortTimeString();
    }
    /// <summary>
    /// 停止地图定位
    /// </summary>
    private void StopLocalizeMap()
    {
        text.text = "稀疏空间地图停止定位。" + DateTime.Now.ToShortTimeString();
    }
    /// <summary>
    /// 开始本地化地图
    /// </summary>
    public void StartLocalization()
    {
        //文本框内容不为空
        if (inputID.text.Length > 0 && inputName.text.Length > 0)
        {
            map.MapManagerSource.ID = inputID.text;
            map.MapManagerSource.Name = inputName.text;
        }
        text.text = "开始本地化地图。";
        mapWorker.Localizer.startLocalization();
    }
    /// <summary>
    /// 停止本地化
    /// </summary>
    public void StopLocalization()
    {
        mapWorker.Localizer.stopLocalization();
    }

}

打包后在设备上运行,默认获取之前建立的地图。期间可以停止定位以后,输入新的地图ID和名称再点击Start开始本地化地图。

地图的原点和方向即SparseSpatialMap游戏对象的位置方向和本地化时候设备的状态无关,和建立地图时候的状态一致。

本地化地图

视频版地址:https://www.bilibili.com/video/BV1Xg4y1z7d8/

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

EasyAR4.0使用说明(Unity3D)(七)----稀疏空间地图 的相关文章

  • Unity Animator 动画没切换

    恶魔射手 Survival Shooter 项目 有两个动画 一个是静止时的Idle 一个是走路时候的Move 如下图 设置好动画状态机后发现按方向键后还是Idle 没反应 而一直按着方向键后呢又动起来了 最后找到了真相 原来选中了 Has
  • Unity 安卓打包

    Unity打包的方式有很多种 自动打包和手动打包 今天小弟就鼓捣鼓捣unity手动打包 如果想动态打包的话 可以去看其他大佬的帖帖哈 unity打包先配置环境 下载unity的时候可以顺道把unity的安卓包下载下来 如果忘了也没事 可以从
  • unity网络资源导入

    1 找到需要导入的文件 这里导入fbx格式 2 打开unity界面 在Asset目录下创建文件夹FBX 将需要导入的fbx预制体或整个文件夹拖入创建的FBX文件夹下 3 选中需要的fbx预制体并拖至场景中 4 双击定位到当前物体 5 找到需
  • Unity中级客户端开发工程师的进阶之路

    上期UWA技能成长系统之 Unity高级客户端开发工程师的进阶之路 得到了很多Unity开发者的肯定 通过系统的学习 可以掌握游戏性能瓶颈定位的方法和常见的CPU GPU 内存相关的性能优化方法 UWA技能成长系统是UWA根据学员的职业发展
  • FBX导入Unity中模型没有材质的处理

    一 3dMax导出FBX时的注意事项 导出时 确保maps文件存在 里面放着fbx用到的image 二 在Unity中的设置 1 文件拖入Unity的Assets文件夹中 2 查看模型的材质是否存在 如下所示 材质为None 此时拖入sce
  • [3dsMax]2018版下拉菜单项的子菜单无法选中

    软件自身问题 安装更新补丁即可解决 不想更新补丁也可以使用键盘的方向键进行选中 补丁百度云链接 https pan baidu com s 1LDxRFwQnR0GSONuz7wcEfA 提取码 6gpk
  • Unity Shader入门精要第七章 基础纹理之遮罩纹理

    Unity系列文章目录 文章目录 Unity系列文章目录 前言 一 实践 参考 前言 遮罩纹理 mask texture 是本章要介绍的最后一种纹理 它非常有用 在很多商业游戏中 都可以见到它的身影 那么什么是遮罩呢 简单来讲 遮罩允许我们
  • unity的LOD组件

    本文转载自http blog csdn net huutu article details 52106468 LOD是Level Of Detais 的简称 多细节层次 在游戏场景中 根据摄像机与模型的距离 来决定显示哪一个模型 一般距离近
  • unity中创建询问弹出窗口

    在开发过程中进程会遇到需要弹出一个窗口询问用户是否进行的操作 今天就来制作一个这样弹出窗口 然后根据弹出窗口的选择内容不同进行不同的操作 本例中主要是为了删除一个数据 而在删除数据操作前需要得到用户的一个确认操作 这里面主要用到了Notif
  • unity工程崩溃资源找回

    1 Unity死机未保存场景 当你在Unity中编辑场景 突然死机时 可以在项目文件目录中找到Temp文件夹 双击文件夹 找到 Backupscenes文件夹 把后缀为 backup的文件后缀改为 unity 然后拖进Unity的Proje
  • unity3d大型互动照片墙

    1 本次应客户需求 制作一个大型照片墙互动 输出分辨率为9600 4320 注 unity3d官方推荐最大分辨率为8192 3686 4 经过现场长达24小时暴力测试中途未发生问题 姑且判定可以达到正常标准 废话不多说 先上效果 unity
  • unity: C#的Action Event Delegate的异同

    目录 一 Action 二 Event 三 Action和Event区别 四 Delegate 总结 Action Event Delegate的异同 前言 Action Event和Delegate都是C 语言中的重要概念 分别用于管理函
  • VLC for unity 插件如何使用

    VLC for unity 插件如何使用 先去下载一个VLC播放器 安装完成后 然后导入插件链接https download csdn net my 这个插件我的另一个上传资源里有 或者到商店去下载 这个插件链接下载完是一个txt文档 里面
  • 【Unity】按Esc进入操作菜单

    本文章是基于如下视频的自我总结 https www youtube com watch v JivuXdrIHK0 步骤如下 1 在Canvas 界面添加一个Panel Panel中添加一个按钮 调整按钮的大小为合适大小 调整字体的大小为合
  • Mecanim Any State

    Any State表示任意状态 任意状态是 一个一直存在的特殊状态 他的存在是为了保证你在无意转移至某个你当前正处于的特殊状态而准备的 为你的状态机中的每个状态设置相同的对外转移是一个快捷的方式 假如有Walk Run Fly Die这四个
  • Unity旋转以及万向锁问题

    我之前研读了一些关于unity旋转相关的博客 一直想抽个时间写个总结 但是由于实习太忙一直没有写 趁着今天请了假晚上有时间把这段时间一些学习心得写出来 Unity inspector面板中的Rotation 在unity中 想必大家最先接触
  • Unity在UI界面上显示3D模型/物体,控制模型旋转

    https blog csdn net ChinarCSDN article details 81058773
  • Unity万向节死锁解决方案(2023/12/4)

    1 万向节死锁无法解决 这是因为它的特性就是如此 就像玻璃杯就是玻璃 这不可否认 别钻牛角尖昂 2 大多数情况下欧拉角足够用 例如 CF 摄像机不可能绕z轴旋转 x轴旋转也不会超过九十度 因为那样人物的腰子会被扭断 塔防游戏 保卫萝卜 吃鸡
  • unity3d image组件不显示

    需要将UI组件放到画布下面
  • 【原神游戏开发日志1】缘起

    原神游戏开发日志1 缘起 版权声明 本文为 优梦创客 原创文章 您可以自由转载 但必须加入完整的版权声明 文章内容不得删减 修改 演绎 相关学习资源见文末 大家好 最近看到原神在TGA上频频获奖 作为一个14年经验的游戏开发行业的老兵 我就

随机推荐

  • LFSR:线性反馈移位寄存器及其应用

    LFSR简介 LFSR Linear feedback shift register 是一种特殊的的移位寄存器 他的输入取决于其先前状态 LFSR的使用异常广泛 可以说涉及到方方面面 以下是Wikipedia列举的一些应用 INTELSAT
  • jquery 计算时间差

    用正则 且精确到秒 function Days1 date1 date2 var date3 date1 getTime date2 getTime 时间差的毫秒数 计算出相差天数 var days Math floor date3 24
  • Vue3使用方法

    Vue3相比于Vue2 解决了 Vue2中新增属性 删除属性 界面不会更新的问题 解决了 Vue2中直接通过下标修改数组 界面不会刷新的问题 vue cli版本必须是4 5以上 查看版本命令 vue V 创建工程命令 vue create
  • PAT(甲级)1148 Werewolf - Simple Version(枚举)

    Description 狼人杀游戏 第几个人说第几个人是狼人或者是人 规定所有人中有两个狼人 其中只有一个狼人和一个人说谎 要求找出两个狼人 Input 第一行n 代表n个人 接下来n行 正数 Di 代表 第i个人说第Di人是human 负
  • 内网服务器外网连接SSH远程端口转发实战详解

    问题 前段时间在外地没有在实验室 随身携带了一个笔记本电脑 但是笔记本性能不够 想用SSH远程连接实验室的电脑 问如何连接 现有以下设备 设备 IP 备注 系统 实验室电脑C1 192 168 0 24 内网 可访问外网 SSH登陆端口为3
  • 人脸关键点检测与 MMPose

    一 任务划分 MMPose 是利用深度学习算法对人体姿态进行估计的算法库 而人体姿态估计 是指 从给定图像中识别人脸 手部 身体等关键点 其中 输入 图像 I 输出 所有关键点的像素坐标 x 1 y 1 x 2 y 2 x j y j 这里
  • 【计算机网络】实验6:cisco交换机配置 在PacketTracer中对交换机设备使用命令行(CLI)进行配置

    一 实验目的 1 了解交换机的基本配置命令 2 了解交换机的VLAN配置 二 实验内容 1 packet Tracer 配置Cisco交换机 2 VLAN的配置 1 Packet Tracer 配置Cisco交换机 要配置好Cisco交换机
  • aix ---lspv command

    lspv 列出os中所有的pv pvname pvid vgname status hdisk0 00c3f005d072189b rootvg active hdisk1 00c3f435d0f4916c rootvg active hd
  • 高级软件测试成长路线-hogwarts

    高级软件测试成长路线
  • Echarts给柱状统计图、进度图的字体及柱子加不同的颜色及阴影

    今天记录一个Echart统计图中的几个小知识点以及方法 写的不好 仅供参考 如有不恰当之处 劳烦留言交流 手动抱拳 原图入选所示第一张图 改造后的图是第二张 改造前 改造后 首先看到这个图的颜色 颜色的选择按照自己的喜好和统计图所应用的场景
  • 小程序云开发入门到实践:云函数的配置与部署

    目录 1 4 云函数的配置与部署 1 4 1 云函数的开发环境 1 下载安装Node js 1 4 2 部署并上传云函数
  • Vue3封装 Message消息提示实例函数

    Vue3封装 消息提示实例函数 实现效果 Vue2 0使用 Vue prototype message function vue3 0使用app config globalProperties挂载原型方法app config globalP
  • 10 种跨域解决方案(附终极方案)

    写在前面 嗯 又来了 又说到跨域了 这是一个老生常谈的话题 以前我觉得这种基础文章没有什么好写的 会想着你去了解底层啊 不是很简单吗 但是最近在开发一个 vscode 插件 发现 当你刚入门一样东西的时候 你不会想这么多 因为你对他不熟悉
  • 苹果iOS 12.2开发者预览版beta 6发布

    3月19日消息 苹果今天推送了iOS 12 2开发者预览版Beta 6系统更新 还包括macOS 10 14 4 Mojave watchOS 5 2和tvOS 12 2的新版本 用户可以通过OTA推送升级 其中苹果iOS 12 2的Bet
  • 珍惜,那个主动联系你的人

    听过这样一句话 如果不是在乎你 谁会愿意一直主动付出 如果不是太爱你 谁又愿意低眉顺目 深以为然 感情里 一直都会主动联系你的人 才是真正在乎你 爱你的人 都说乍见之欢易 长相厮守难 再好的感情 也抵不过平淡岁月的冲刷磨砺 两个人相处久了
  • shell命令:ln -s 创建软链接采用相对路径时的奇怪用法

    目前基于测试结果得到结论 暂时无权威资料显示出原因 参考了 https blog csdn net weixin 42183399 article details 80498750 但是这个博客给的结果只是特殊用法 无法归结至一般结论 下面
  • vue中window.addEventListener(‘scroll‘, xx)失效解决办法

    多次尝试都无法获取到滚动事件 后来加上true之后就可以了 window addEventListener scroll this clintHeight true
  • js中startsWith()使用

    startsWith函数 时Java中的 在js使用时他并不是每个浏览器都有的 所以我们一般要重写一下这个函数 采用正则表达式实现startWith endWith效果函数 String prototype startWith functi
  • CPU 风扇清理灰尘加油全过程图解

    主机电源风扇由于使用时间长 风扇轴承的润滑油耗尽 导致风扇转速下降或是不转 引起电源热量无法有效排除而造成电脑经常死机 解决办法有几种 现图解说明最简单省钱的办法如下 1 把电源从主机上拆下 如下图再取出电源背面的4个固定镙丝 2008 5
  • EasyAR4.0使用说明(Unity3D)(七)----稀疏空间地图

    稀疏空间地图的对应用环境的要求和平面图像识别可以比照理解 周围环境需要足够丰富 不能有大片的单色区域 透明区域 此外 光照 角度都会对建立地图和定位产生影响 官方给出了建立地图和定位地图的建议 https help easyar cn Ea