XR和Steam VR项目合并问题
最近有一个项目是用Steam VR开发的,里面部分场景是用VRTK框架做的,还有一部分是用SteamVR SDK自带的Player预制直接开发的。
这样本身没有问题,因为最终都是通过SteamVR SDK处理的,VRTK也管理好了SteamVR的逻辑,并且支持动态切换,比如切换成Oculus的。
然后现在遇到一个问题,还有一个项目是用Unity自带的XR开发的,Package Manager导入XR相关的插件实现的。
需要将XR开发的项目移植到Steam VR项目来,然后事情就开始了。
SteamVR的场景可以运行,通过Pico以及Quest串流还有htc头盔都能正常识别,手柄也能控制。
但是XR场景就出现问题了,头盔无法识别。
经过一步步排查,发现是XR Plug-in Management这里需要设置不同的XRLoader。
而SteamVR是OpenVR Loader,而XR是OpenXR,因为OpenVR Loader在前,所以激活的是OpenVR Loader,这也是为什么SteamVR场景可以运行而XR场景不行。
我们看看unity的源代码是怎么写的,发现这里面是有activeLoader的概念,也就是一次只能一个Loader运行。
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;using UnityEditor;using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.UIElements;
using UnityEngine.Serialization;
using UnityEngine.XR.Management;[assembly: InternalsVisibleTo("Unity.XR.Management.Tests")]
[assembly: InternalsVisibleTo("Unity.XR.Management.EditorTests")]
namespace UnityEngine.XR.Management
{/// <summary>/// Class to handle active loader and subsystem management for XR. This class is to be added as a/// ScriptableObject asset in your project and should only be referenced by the <see cref="XRGeneralSettings"/>/// instance for its use.////// Given a list of loaders, it will attempt to load each loader in the given order. The first/// loader that is successful wins and all remaining loaders are ignored. The loader/// that succeeds is accessible through the <see cref="activeLoader"/> property on the manager.////// Depending on configuration the <see cref="XRManagerSettings"/> instance will automatically manage the active loader/// at correct points in the application lifecycle. The user can override certain points in the active loader lifecycle/// and manually manage them by toggling the <see cref="automaticLoading"/> and <see cref="automaticRunning"/>/// properties. Disabling <see cref="automaticLoading"/> implies the the user is responsible for the full lifecycle/// of the XR session normally handled by the <see cref="XRManagerSettings"/> instance. Toggling this to false also toggles/// <see cref="automaticRunning"/> false.////// Disabling <see cref="automaticRunning"/> only implies that the user is responsible for starting and stopping/// the <see cref="activeLoader"/> through the <see cref="StartSubsystems"/> and <see cref="StopSubsystems"/> APIs.////// Automatic lifecycle management is executed as follows////// * Runtime Initialize -> <see cref="InitializeLoader"/>. The loader list will be iterated over and the first successful loader will be set as the active loader./// * Start -> <see cref="StartSubsystems"/>. Ask the active loader to start all subsystems./// * OnDisable -> <see cref="StopSubsystems"/>. Ask the active loader to stop all subsystems./// * OnDestroy -> <see cref="DeinitializeLoader"/>. Deinitialize and remove the active loader./// </summary>public sealed class XRManagerSettings : ScriptableObject{[HideInInspector]bool m_InitializationComplete = false;#pragma warning disable 414// This property is only used by the scriptable object editing part of the system and as such no one// directly references it. Have to manually disable the console warning here so that we can// get a clean console report.[HideInInspector][SerializeField]bool m_RequiresSettingsUpdate = false;
#pragma warning restore 414[SerializeField][Tooltip("Determines if the XR Manager instance is responsible for creating and destroying the appropriate loader instance.")][FormerlySerializedAs("AutomaticLoading")]bool m_AutomaticLoading = false;/// <summary>/// Get and set Automatic Loading state for this manager. When this is true, the manager will automatically call/// <see cref="InitializeLoader"/> and <see cref="DeinitializeLoader"/> for you. When false <see cref="automaticRunning"/>/// is also set to false and remains that way. This means that disabling automatic loading disables all automatic behavior/// for the manager./// </summary>public bool automaticLoading{get { return m_AutomaticLoading; }set { m_AutomaticLoading = value; }}[SerializeField][Tooltip("Determines if the XR Manager instance is responsible for starting and stopping subsystems for the active loader instance.")][FormerlySerializedAs("AutomaticRunning")]bool m_AutomaticRunning = false;/// <summary>/// Get and set automatic running state for this manager. When set to true the manager will call <see cref="StartSubsystems"/>/// and <see cref="StopSubsystems"/> APIs at appropriate times. When set to false, or when <see cref="automaticLoading"/> is false/// then it is up to the user of the manager to handle that same functionality./// </summary>public bool automaticRunning{get { return m_AutomaticRunning; }set { m_AutomaticRunning = value; }}[SerializeField][Tooltip("List of XR Loader instances arranged in desired load order.")][FormerlySerializedAs("Loaders")]List<XRLoader> m_Loaders = new List<XRLoader>();// Maintains a list of registered loaders that is immutable at runtime.[SerializeField][HideInInspector]HashSet<XRLoader> m_RegisteredLoaders = new HashSet<XRLoader>();/// <summary>/// List of loaders currently managed by this XR Manager instance./// </summary>/// <remarks>/// Modifying the list of loaders at runtime is undefined behavior and could result in a crash or memory leak./// Use <see cref="activeLoaders"/> to retrieve the currently ordered list of loaders. If you need to mutate/// the list at runtime, use <see cref="TryAddLoader"/>, <see cref="TryRemoveLoader"/>, and/// <see cref="TrySetLoaders"/>./// </remarks>[Obsolete("'XRManagerSettings.loaders' property is obsolete. Use 'XRManagerSettings.activeLoaders' instead to get a list of the current loaders.")]public List<XRLoader> loaders{get { return m_Loaders; }
#if UNITY_EDITORset { m_Loaders = value; }
#endif}/// <summary>/// A shallow copy of the list of loaders currently managed by this XR Manager instance./// </summary>/// <remarks>/// This property returns a read only list. Any changes made to the list itself will not affect the list/// used by this XR Manager instance. To mutate the list of loaders currently managed by this instance,/// use <see cref="TryAddLoader"/>, <see cref="TryRemoveLoader"/>, and/or <see cref="TrySetLoaders"/>./// </remarks>public IReadOnlyList<XRLoader> activeLoaders => m_Loaders;/// <summary>/// Read only boolean letting us know if initialization is completed. Because initialization is/// handled as a Coroutine, people taking advantage of the auto-lifecycle management of XRManager/// will need to wait for init to complete before checking for an ActiveLoader and calling StartSubsystems./// </summary>public bool isInitializationComplete{get { return m_InitializationComplete; }}///<summary>/// Return the current singleton active loader instance.///</summary>[HideInInspector]public XRLoader activeLoader { get; private set; }/// <summary>/// Return the current active loader, cast to the requested type. Useful shortcut when you need/// to get the active loader as something less generic than XRLoader./// </summary>////// <typeparam name="T">Requested type of the loader</typeparam>////// <returns>The active loader as requested type, or null.</returns>public T ActiveLoaderAs<T>() where T : XRLoader{return activeLoader as T;}/// <summary>/// Iterate over the configured list of loaders and attempt to initialize each one. The first one/// that succeeds is set as the active loader and initialization immediately terminates.////// When complete <see cref="isInitializationComplete"/> will be set to true. This will mark that it is safe to/// call other parts of the API. This does not guarantee that init successfully created a loader. For that/// you need to check that ActiveLoader is not null.////// Note that there can only be one active loader. Any attempt to initialize a new active loader with one/// already set will cause a warning to be logged and immediate exit of this function.////// This method is synchronous and on return all state should be immediately checkable.////// <b>If manual initialization of XR is being done, this method can not be called before Start completes/// as it depends on graphics initialization within Unity completing.</b>/// </summary>public void InitializeLoaderSync(){if (activeLoader != null){Debug.LogWarning("XR Management has already initialized an active loader in this scene." +" Please make sure to stop all subsystems and deinitialize the active loader before initializing a new one.");return;}foreach (var loader in currentLoaders){if (loader != null){if (CheckGraphicsAPICompatibility(loader) && loader.Initialize()){activeLoader = loader;m_InitializationComplete = true;return;}}}activeLoader = null;}/// <summary>/// Iterate over the configured list of loaders and attempt to initialize each one. The first one/// that succeeds is set as the active loader and initialization immediately terminates.////// When complete <see cref="isInitializationComplete"/> will be set to true. This will mark that it is safe to/// call other parts of the API. This does not guarantee that init successfully created a loader. For that/// you need to check that ActiveLoader is not null.////// Note that there can only be one active loader. Any attempt to initialize a new active loader with one/// already set will cause a warning to be logged and immediate exit of this function.////// Iteration is done asynchronously and this method must be called within the context of a Coroutine.////// <b>If manual initialization of XR is being done, this method can not be called before Start completes/// as it depends on graphics initialization within Unity completing.</b>/// </summary>////// <returns>Enumerator marking the next spot to continue execution at.</returns>public IEnumerator InitializeLoader(){if (activeLoader != null){Debug.LogWarning("XR Management has already initialized an active loader in this scene." +" Please make sure to stop all subsystems and deinitialize the active loader before initializing a new one.");yield break;}foreach (var loader in currentLoaders){if (loader != null){if (CheckGraphicsAPICompatibility(loader) && loader.Initialize()){activeLoader = loader;m_InitializationComplete = true;yield break;}}yield return null;}activeLoader = null;}/// <summary>/// Attempts to append the given loader to the list of loaders at the given index./// </summary>/// <param name="loader">/// The <see cref="XRLoader"/> to be added to this manager's instance of loaders./// </param>/// <param name="index">/// The index at which the given <see cref="XRLoader"/> should be added. If you set a negative or otherwise/// invalid index, the loader will be appended to the end of the list./// </param>/// <returns>/// <c>true</c> if the loader is not a duplicate and was added to the list successfully, <c>false</c>/// otherwise./// </returns>/// <remarks>/// This method behaves differently in the Editor and during runtime/Play mode. While your app runs in the Editor and not in/// Play mode, attempting to add an <see cref="XRLoader"/> will always succeed and register that loader's type/// internally. Attempting to add a loader during runtime/Play mode will trigger a check to see whether a loader of/// that type was registered. If the check is successful, the loader is added. If not, the loader is not added and the method/// returns <c>false</c>./// </remarks>public bool TryAddLoader(XRLoader loader, int index = -1){if (loader == null || currentLoaders.Contains(loader))return false;#if UNITY_EDITORif (!EditorApplication.isPlaying && !m_RegisteredLoaders.Contains(loader))m_RegisteredLoaders.Add(loader);
#endifif (!m_RegisteredLoaders.Contains(loader))return false;if (index < 0 || index >= currentLoaders.Count)currentLoaders.Add(loader);elsecurrentLoaders.Insert(index, loader);return true;}/// <summary>/// Attempts to remove the first instance of a given loader from the list of loaders./// </summary>/// <param name="loader">/// The <see cref="XRLoader"/> to be removed from this manager's instance of loaders./// </param>/// <returns>/// <c>true</c> if the loader was successfully removed from the list, <c>false</c> otherwise./// </returns>/// <remarks>/// This method behaves differently in the Editor and during runtime/Play mode. During runtime/Play mode, the loader/// will be removed with no additional side effects if it is in the list managed by this instance. While in the/// Editor and not in Play mode, the loader will be removed if it exists and/// it will be unregistered from this instance and any attempts to add it during/// runtime/Play mode will fail. You can re-add the loader in the Editor while not in Play mode./// </remarks>public bool TryRemoveLoader(XRLoader loader){var removedLoader = true;if (currentLoaders.Contains(loader))removedLoader = currentLoaders.Remove(loader);#if UNITY_EDITORif (!EditorApplication.isPlaying && !currentLoaders.Contains(loader))m_RegisteredLoaders.Remove(loader);
#endifreturn removedLoader;}/// <summary>/// Attempts to set the given loader list as the list of loaders managed by this instance./// </summary>/// <param name="reorderedLoaders">/// The list of <see cref="XRLoader"/>s to be managed by this manager instance./// </param>/// <returns>/// <c>true</c> if the loader list was set successfully, <c>false</c> otherwise./// </returns>/// <remarks>/// This method behaves differently in the Editor and during runtime/Play mode. While in the Editor and not in/// Play mode, any attempts to set the list of loaders will succeed without any additional checks. During/// runtime/Play mode, the new loader list will be validated against the registered <see cref="XRLoader"/> types./// If any loaders exist in the list that were not registered at startup, the attempt will fail./// </remarks>public bool TrySetLoaders(List<XRLoader> reorderedLoaders){var originalLoaders = new List<XRLoader>(activeLoaders);
#if UNITY_EDITORif (!EditorApplication.isPlaying){registeredLoaders.Clear();currentLoaders.Clear();foreach (var loader in reorderedLoaders){if (!TryAddLoader(loader)){TrySetLoaders(originalLoaders);return false;}}return true;}
#endifcurrentLoaders.Clear();foreach (var loader in reorderedLoaders){if (!TryAddLoader(loader)){currentLoaders = originalLoaders;return false;}}return true;}private bool CheckGraphicsAPICompatibility(XRLoader loader){GraphicsDeviceType deviceType = SystemInfo.graphicsDeviceType;List<GraphicsDeviceType> supportedDeviceTypes = loader.GetSupportedGraphicsDeviceTypes(false);// To help with backward compatibility, if the compatibility list is empty we assume that it does not implement the GetSupportedGraphicsDeviceTypes method// Therefore we revert to the previous behavior of building or starting the loader regardless of gfx api settings.if (supportedDeviceTypes.Count > 0 && !supportedDeviceTypes.Contains(deviceType)){Debug.LogWarning(String.Format("The {0} does not support the initialized graphics device, {1}. Please change the preffered Graphics API in PlayerSettings. Attempting to start the next XR loader.", loader.name, deviceType.ToString()));return false;}return true;}/// <summary>/// If there is an active loader, this will request the loader to start all the subsystems that it/// is managing.////// You must wait for <see cref="isInitializationComplete"/> to be set to true prior to calling this API./// </summary>public void StartSubsystems(){if (!m_InitializationComplete){Debug.LogWarning("Call to StartSubsystems without an initialized manager." +"Please make sure wait for initialization to complete before calling this API.");return;}if (activeLoader != null){activeLoader.Start();}}/// <summary>/// If there is an active loader, this will request the loader to stop all the subsystems that it/// is managing.////// You must wait for <see cref="isInitializationComplete"/> to be set to tru prior to calling this API./// </summary>public void StopSubsystems(){if (!m_InitializationComplete){Debug.LogWarning("Call to StopSubsystems without an initialized manager." +"Please make sure wait for initialization to complete before calling this API.");return;}if (activeLoader != null){activeLoader.Stop();}}/// <summary>/// If there is an active loader, this function will deinitialize it and remove the active loader instance from/// management. We will automatically call <see cref="StopSubsystems"/> prior to deinitialization to make sure/// that things are cleaned up appropriately.////// You must wait for <see cref="isInitializationComplete"/> to be set to tru prior to calling this API.////// Upon return <see cref="isInitializationComplete"/> will be rest to false;/// </summary>public void DeinitializeLoader(){if (!m_InitializationComplete){Debug.LogWarning("Call to DeinitializeLoader without an initialized manager." +"Please make sure wait for initialization to complete before calling this API.");return;}StopSubsystems();if (activeLoader != null){activeLoader.Deinitialize();activeLoader = null;}m_InitializationComplete = false;}// Use this for initializationvoid Start(){if (automaticLoading && automaticRunning){StartSubsystems();}}void OnDisable(){if (automaticLoading && automaticRunning){StopSubsystems();}}void OnDestroy(){if (automaticLoading){DeinitializeLoader();}}// To modify the list of loaders internally use `currentLoaders` as it will return a list reference rather// than a shallow copy.// TODO @davidmo 10/12/2020: remove this in next major version bump and make 'loaders' internal.internal List<XRLoader> currentLoaders{get { return m_Loaders; }set { m_Loaders = value; }}// To modify the set of registered loaders use `registeredLoaders` as it will return a reference to the// hashset of loaders.internal HashSet<XRLoader> registeredLoaders{get { return m_RegisteredLoaders; }}}
}
事情变的有趣起来,我们知道了这样的原理之后,那鱼蛋我就想着尝试下,在Runtime里动态切换行吧,SteamVR场景切换到OpenVR Loader,而XR场景切换到OpenXR,代码如下。
using System.Collections.Generic;
using Unity.XR.OpenVR;
using UnityEngine;
using UnityEngine.XR.Management;
using UnityEngine.XR.OpenXR;namespace EgoGame
{/// <summary>/// 该类有问题,废弃了/// </summary>public class AutoXRLoader:MonoBehaviour{public List<XRLoader> xrLoaders;public List<XRLoader> vrLoaders;public bool isXR;private void Awake(){SetLoader(isXR);}private void OnDestroy(){SetLoader(!isXR);}void SetLoader(bool xr){//不这样,会频繁的退出loader,VR会没画面if (xr && XRGeneralSettings.Instance.Manager.activeLoader is OpenXRLoader){return;}if (!xr && XRGeneralSettings.Instance.Manager.activeLoader is OpenVRLoader){return;}var loaders = xr ? xrLoaders : vrLoaders;Debug.Log("切换Loader:" + xr+"=="+XRGeneralSettings.Instance.Manager.activeLoader);XRGeneralSettings.Instance.Manager.DeinitializeLoader();XRGeneralSettings.Instance.Manager.TrySetLoaders(loaders);XRGeneralSettings.Instance.Manager.InitializeLoaderSync();XRGeneralSettings.Instance.Manager.StartSubsystems();}}
}
果然奏效了,XR场景能在头盔里识别并运行了,手柄也能控制。但是,切到SteamVR场景就出现了问题,Steam VR SDK报错了,报错提示有另一个应用在使用SteamVR。
最后的结果就是,没法实现动态切换XR或VR,如果看到此处的人,有办法请告诉我,我尝试了两天用了各种办法,都没法做到。
最后推荐大家开发VR应用不要直接用SteamVR SDK或XR SDK或Oculus SDK开发,而是用那些集成的插件,如VR Interaction Framework、VRTK等,这样在多个VR设备也能快速部署。
相关文章:

XR和Steam VR项目合并问题
最近有一个项目是用Steam VR开发的,里面部分场景是用VRTK框架做的,还有一部分是用SteamVR SDK自带的Player预制直接开发的。 这样本身没有问题,因为最终都是通过SteamVR SDK处理的,VRTK也管理好了SteamVR的逻辑,并且支…...
uni-app:利用Vue的原型对象Vue.prototype设置全局方法及其引用
一、在main.js中设置方法checkPermission绑定到Vue.prototype 核心代码 Vue.prototype.$checkPermission function(username) {console.log(Checking permission for:, username); }; 完整代码 import App from ./App// 添加 checkPermission 方法到 Vue.prototype 上,检查…...
django接入djangorestframework-simplejwt步骤
版本:django 4.2 python: 3.8 安装 pip install djangorestframework-simplejwtuser子应用models.py文件 from django.db import models from django.contrib.auth.models import AbstractUserclass User(AbstractUser):mobile models.CharField(max_length11, u…...

前端工程化工具系列(十)—— Browserslist:浏览器兼容性配置工具
Browserslist 是一个能够在不同的前端工具间共享目标浏览器的配置,各工具根据该配置进行代码转译等操作。 具体的这些前端工具为:Autoprefixer、Babel、postcss-preset-env、eslint-plugin-compat、stylelint-no-unsupported-browser-features、postcss-…...

双列集合底层源码
tips: 竖着的箭头:重写 横着的箭头:继承...

【Ardiuno】实验使用ESP32连接Wifi(图文)
ESP32最为精华和有特色的地方当然是wifi连接,这里我们就写程序实验一下适使用ESP32主板连接wifi,为了简化实验我们这里只做了连接部分,其他实验在后续再继续。 由于本实验只要在串口监视器中查看结果状态即可,因此电路板上无需连…...

优化家庭网络,路由器无线中继配置全攻略(中兴E1600无线中继设置/如何解决没有预埋有线网络接口的问题/使用闲置路由实现WIFI扩展)
文章目录 📖 介绍 📖🏡 演示环境 🏡📒 网络优化 📒📒 操作步骤 📒💡适用场景🚨 常见问题及解决方案⚓️ 相关链接 ⚓️📖 介绍 📖 在现代家庭生活中,WiFi已经渗透到我们生活的每一个角落,成为了日常生活中不可或缺的一部分。然而,不少用户常常遇到W…...

【ArcGIS微课1000例】0114:基于DEM地形数据整体抬升或下降高程
相关阅读:【GlobalMapper精品教程】083:基于DEM整体抬升或下降地形高程的两种方式 文章目录 一、任务分析二、栅格计算器简介三、地形整体修改四、注意事项一、任务分析 打开软件,加载配套实验数据中的0112.rar中的dem数据,如下所示,dem的高程范围为256.75~342.37米,现在…...

AGP4+ 打包运行闪退,AGP7+ 正常(has code but is marked native or abstract)
问题 安装应用,点击图标启动立马闪退! 诡异的闪退:AGP4 打包运行闪退,AGP7 正常 unity 导出的 Android 日志两个主要点: com.android.boot.App 是 Android 的 application 子类,程序入口 java.lang.Class…...

ChatGPT3.5和ChatGPT4.0、ChatGPT4o对比
一、ChatGPT3.5、ChatGPT4.0、ChatGPT4o对比 目前ChatGPT有三个主要版本,分别是ChatGPT3.5、ChatGPT4.0、ChatGPT4o,这三个版本之间有什么差异呢? 对比项ChatGPT3.5ChatGPT4.0ChatGPT4o参数数量1750亿约1万亿未公开输入文本文本、图片文本、…...
【知识拓展】HTTP、WebSocket 和 RPC:区别与使用场景详解
在工作中,HTTP、WebSocket 和 RPC 是三种常见的协议或通信方式,根据资料查阅,本文主要记录它们的区别及其适用的使用场景 HTTP(超文本传输协议) 概述 HTTP(Hypertext Transfer Protocol)是一…...
C语言printf( ) 函数和 scanf( ) 函数格式符的修饰符 “*”有什么作⽤?
一、问题 在 printf( ) 函数和 scanf( ) 函数的格式修饰符有很多,以浮点型数据为例,有%f、%lf、 %3.0f、%.4f等。不同的修饰符表示不同的含义,那么修饰符“*”有什么含义呢? 二、解答 下⾯通过例⼦来证明⼀下这个格式符在 printf…...
java 使用WebClient发送https请求
核心逻辑 绕过ssl证书检查 具体操作 话不多说上代码 // 构建WebClient public static WebClient createWebClient() throws SSLException {SslContext context SslContextBuilder.forClient().trustManager(InsecureTrustManagerFactory.INSTANCE).build();HttpClient htt…...
Python 中的内存管理机制
Python 的内存管理机制主要由两个部分组成:垃圾回收机制和引用计数。 垃圾回收机制主要负责检测和回收不再被使用的内存。Python 使用的是自动垃圾回收机制,也就是说程序员不需要手动释放内存。Python 的垃圾回收机制采用了引用计数的方法来追踪和回收不…...
Mac电脑重置网络命令
在Mac电脑上重置网络设置可以通过终端命令来实现。以下是几种方法,包括刷新DNS缓存、重置网络接口,以及重置Wi-Fi设置。 刷新DNS缓存 要刷新DNS缓存,可以使用以下命令: sudo dscacheutil -flushcache; sudo killall -HUP mDNSR…...

C++期末复习总结(2)
目录 1.运算符重载 2.四种运算符重载 (1)关系运算符的重载 (2) 左移运算符的重载 (3)下标运算符的重载 (4)赋值运算符的重载 3.继承的方式 4.继承的对象模型 5.基类的构造 6…...

[word] word大括号怎么打两行 #其他#其他#微信
word大括号怎么打两行 Word给用户提供了用于创建专业而优雅的文档工具,帮助用户节省时间,并得到优雅美观的结果。 一直以来,Microsoft Office Word 都是最流行的文字处理程序。 作为 Office 套件的核心程序, Word 提供了许多易…...

【python】python指南(二):命令行参数解析器ArgumentParser
一、引言 对于算法工程师来说,语言从来都不是关键,关键是快速学习以及解决问题的能力。大学的时候参加ACM/ICPC一直使用的是C语言,实习的时候做一个算法策略后台用的是php,毕业后做策略算法开发,因为要用spark&#x…...

香橙派 Orange AIpro 测评记录视频硬件解码
香橙派 Orange AIpro 测评记录视频硬件解码 香橙派官网:http://www.orangepi.cn/ 收到了一块Orange Pi AIpro开发板,记录一下我的测评~测评简介如下:1.连接网络2.安装流媒体进行硬件解码测试3.安装IO测试 简介 Orange Pi AI Pro 是香橙派联合…...

四天工作制,比你想象的更近了一点
原文:Andrew Keshner - 2024.05.30 软件公司、大型企业甚至警察部门都在试验这一看似遥不可及的概念。 教育软件公司 Kuali 的会议精简,除非绝对必要,员工尽量避免安排会议。即使有会议,也鼓励员工跳过与自己工作无关的部分。在…...
进程地址空间(比特课总结)
一、进程地址空间 1. 环境变量 1 )⽤户级环境变量与系统级环境变量 全局属性:环境变量具有全局属性,会被⼦进程继承。例如当bash启动⼦进程时,环 境变量会⾃动传递给⼦进程。 本地变量限制:本地变量只在当前进程(ba…...

基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真
目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销,平衡网络负载,延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...
DockerHub与私有镜像仓库在容器化中的应用与管理
哈喽,大家好,我是左手python! Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库,用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...
线程与协程
1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指:像函数调用/返回一样轻量地完成任务切换。 举例说明: 当你在程序中写一个函数调用: funcA() 然后 funcA 执行完后返回&…...

Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)
目录 1.TCP的连接管理机制(1)三次握手①握手过程②对握手过程的理解 (2)四次挥手(3)握手和挥手的触发(4)状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...

什么是库存周转?如何用进销存系统提高库存周转率?
你可能听说过这样一句话: “利润不是赚出来的,是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业,很多企业看着销售不错,账上却没钱、利润也不见了,一翻库存才发现: 一堆卖不动的旧货…...

Python实现prophet 理论及参数优化
文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候,写过一篇简单实现,后期随着对该模型的深入研究,本次记录涉及到prophet 的公式以及参数调优,从公式可以更直观…...
鸿蒙DevEco Studio HarmonyOS 5跑酷小游戏实现指南
1. 项目概述 本跑酷小游戏基于鸿蒙HarmonyOS 5开发,使用DevEco Studio作为开发工具,采用Java语言实现,包含角色控制、障碍物生成和分数计算系统。 2. 项目结构 /src/main/java/com/example/runner/├── MainAbilitySlice.java // 主界…...
PAN/FPN
import torch import torch.nn as nn import torch.nn.functional as F import mathclass LowResQueryHighResKVAttention(nn.Module):"""方案 1: 低分辨率特征 (Query) 查询高分辨率特征 (Key, Value).输出分辨率与低分辨率输入相同。"""def __…...

基于Java+MySQL实现(GUI)客户管理系统
客户资料管理系统的设计与实现 第一章 需求分析 1.1 需求总体介绍 本项目为了方便维护客户信息为了方便维护客户信息,对客户进行统一管理,可以把所有客户信息录入系统,进行维护和统计功能。可通过文件的方式保存相关录入数据,对…...