当前位置: 首页 > news >正文

2025-01-01 NO2. XRHands 介绍

文章目录

  • 软件配置
  • 1 XR Hands 简介
  • 2 XRHand
    • 2.1 Pose
    • 2.2 Handedness
  • 3 XRHandJoint
    • 3.1 XRHandJointID
    • 3.2 XRHandJointTrackingState
  • 4 XRHandSubsystem
    • 4.1 数据属性
      • 4.1.1 UpdateSuccessFlags
      • 4.1.2 UpdateType
    • 4.2 处理器管理:注册和注销
    • 4.3 更新手部数据:`TryUpdateHands` 方法
      • 4.3.1 检查运行,交由第三方处理
      • 4.3.2 手部状态追踪与更新
      • 4.3.3 数据预处理和处理器
      • 4.3.4 动态更新和手势支持
      • 4.3.5 回调处理

软件配置

  • Unity 版本:Unity6000.0.26
  • XRHands 版本:1.5.0

1 XR Hands 简介

​ XR Hands 包定义了允许从支持手部跟踪的设备访问手部跟踪数据的 API。要访问手部跟踪数据,还必须启用实现 XR 手部跟踪子系统的提供程序插件。

Hand tracking cover image

​ XR Hand 套件提供:

  1. XR Hand Subsystem :定义用于手部跟踪数据的 XR 子系统接口。

  2. OpenXR HandTracking feature:此功能为 OpenXR 提供程序插件实现 XRHandSubsystem 。在项目中同时安装了 OpenXR 和 XR Hand 软件包,就可以访问手部数据。其他提供程序插件必须更新以实现 XRHandSubsystem,然后才能在使用它们时访问手部数据。

  3. Open XR Meta Aim Hand:此功能将来自 XR_FB_hand_tracking_aim 扩展的数据提供给 OpenXR 规范。此扩展提供基本的手势识别。

  4. XR Hand:单个跟踪手的数据。

  5. XR Hand Joint:手部单个关节或其他跟踪点的数据。

  6. Meta Aim Hand:来自 Meta Aim 手 OpenXR 功能的捏合和瞄准手势数据。

注意:

​ XR Hands 包定义了用于手部跟踪的 API,但本身并未实现该功能。要在目标平台上使用手部跟踪,您还需要该平台的单独提供程序插件包,该插件包已更新以向 XR Hand Subsystem(该包定义的子系统)提供手部跟踪数据。

2 XRHand

​ 代表来自 XRHandSubsystem 的手数据对象,用于管理和表示手的状态和关节信息。它包含了关于手的信息和操作,例如获取手部关节、手部位姿和手部跟踪状态。

​ 该类不被直接创建,而是通过 XRHandSubsystem.leftHandXRHandSubsystem.rightHand 属性来访问。

public struct XRHand : IEquatable<XRHand>
{// 获取手的根位姿,位于手腕部位。public Pose rootPose { get; }// 该手是左手还是右手public Handedness handedness { get; }// 当前手的根位姿和关节是否被追踪public bool isTracked { get; }// 返回指定 ID 的关节数据// 由于关节数据存储在本地的 NativeArray 中,调用此方法时,会获取到最新的手数据。public XRHandJoint GetJoint(XRHandJointID id) { ... }...
}

2.1 Pose

Pose 是 Unity 中用于表示物体在三维空间中的位置和旋转,封装了 Vector3Quaternion 的数据结构,分别用于存储位置和旋转,适合用于表示游戏对象、虚拟角色、手部模型等在空间中的姿势。

public struct Pose : IEquatable<Pose>
{public Vector3 position;   // 位置public Quaternion rotation; // 旋转// 将当前 Pose 应用到一个给定的 Pose/Transform 上,通常用于将 Pose 从一个坐标系转换到另一个坐标系public Pose GetTransformedBy(Pose lhs) { ... }public Pose GetTransformedBy(Transform lhs) { ... }// 公共属性public Vector3 forward { get; }public Vector3 right { get; }public Vector3 up { get; }public Vector3 forward { get; }
}

2.2 Handedness

​ 用于表示左右手:

// Decompiled with JetBrains decompiler
// Type: UnityEngine.XR.Hands.Handedness
// Assembly: Unity.XR.Hands, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
// MVID: A6E3BCB6-F905-44B3-8327-8AFFABC5770A
// Assembly location: P:\Unity Project\Learning\XRHands-Learning\Library\ScriptAssemblies\Unity.XR.Hands.dll#nullable disable
namespace UnityEngine.XR.Hands
{/// <summary>/// Denotes which hand this joint is on./// </summary>public enum Handedness{Invalid,Left,Right,}
}

3 XRHandJoint

​ 表示 XR 中手部关节的结构体,封装了与手部关节相关的多种信息,例如关节的 位置旋转半径线速度角速度 等。

[StructLayout(LayoutKind.Sequential)]
public struct XRHandJoint : IEquatable<XRHandJoint>
{public XRHandJointID id { get; } // 关节唯一标识符public Handedness handedness { get; } // 属于哪只手public XRHandJointTrackingState trackingState { get; } // 关节追踪状态// 尝试获取该关节的半径(如果有)。// 返回 true 表示成功获取,false 表示未能获取到有效数据。// 成功时,radius 参数将被赋值为关节的半径。public bool TryGetRadius(out float radius) { ... }// 尝试获取该关节的 姿势(位置和旋转)。// 如果姿势数据有效,返回 true,并将姿势信息赋值给 pose 参数。// 如果无效,则返回 false 并将 pose 设置为 Pose.identity。public bool TryGetPose(out Pose pose) { ... }// 尝试获取该关节的 线速度。// 如果线速度数据有效,返回 true,并将线速度赋值给 linearVelocity 参数。// 如果无效,则返回 false,并将 linearVelocity 设置为 Vector3.zero。public bool TryGetLinearVelocity(out Vector3 linearVelocity) { ... }// 尝试获取该关节的 角速度。// 如果角速度数据有效,返回 true,并将角速度赋值给 angularVelocity 参数。// 如果无效,则返回 false,并将 angularVelocity 设置为 Vector3.zero。public bool TryGetAngularVelocity(out Vector3 angularVelocity) { ... }...
}

3.1 XRHandJointID

​ XR Hand 将手部关节分为 26 种,包括指关节、指尖、手腕和手掌。

Tracked points of a hand

​ XR Hand 使用 XRHandJointID 枚举类表示该 26 个 Joint:

// Decompiled with JetBrains decompiler
// Type: UnityEngine.XR.Hands.XRHandJointID
// Assembly: Unity.XR.Hands, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
// MVID: A6E3BCB6-F905-44B3-8327-8AFFABC5770A
// Assembly location: P:\Unity Project\Learning\XRHands-Learning\Library\ScriptAssemblies\Unity.XR.Hands.dll#nullable disable
namespace UnityEngine.XR.Hands
{/// <summary>/// The ID of this joint./// </summary>public enum XRHandJointID{Invalid = 0,BeginMarker = 1,Wrist = 1,Palm = 2,ThumbMetacarpal = 3,ThumbProximal = 4,ThumbDistal = 5,ThumbTip = 6,IndexMetacarpal = 7,IndexProximal = 8,IndexIntermediate = 9,IndexDistal = 10, // 0x0000000AIndexTip = 11, // 0x0000000BMiddleMetacarpal = 12, // 0x0000000CMiddleProximal = 13, // 0x0000000DMiddleIntermediate = 14, // 0x0000000EMiddleDistal = 15, // 0x0000000FMiddleTip = 16, // 0x00000010RingMetacarpal = 17, // 0x00000011RingProximal = 18, // 0x00000012RingIntermediate = 19, // 0x00000013RingDistal = 20, // 0x00000014RingTip = 21, // 0x00000015LittleMetacarpal = 22, // 0x00000016LittleProximal = 23, // 0x00000017LittleIntermediate = 24, // 0x00000018LittleDistal = 25, // 0x00000019LittleTip = 26, // 0x0000001AEndMarker = 27, // 0x0000001B}
}

​ 例如,在 HandVisualizer 示例场景中,Left Hand Tracking 物体上关联了手的所有 XRHandJointID

image-20250101220927694

3.2 XRHandJointTrackingState

​ 表示正在跟踪的特定关节的值,分别有:

// Decompiled with JetBrains decompiler
// Type: UnityEngine.XR.Hands.XRHandJointTrackingState
// Assembly: Unity.XR.Hands, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
// MVID: A6E3BCB6-F905-44B3-8327-8AFFABC5770A
// Assembly location: P:\Unity Project\Learning\XRHands-Learning\Library\ScriptAssemblies\Unity.XR.Hands.dllusing System;#nullable disable
namespace UnityEngine.XR.Hands
{[Flags]public enum XRHandJointTrackingState{None = 0,              // 没有跟踪到数据Radius = 1,            // 关节半径Pose = 2,              // 关节姿势LinearVelocity = 4,    // 关节线速度AngularVelocity = 8,   // 关节角速度WillNeverBeValid = 16, // 永远失效,通常因为该关节不存在HighFidelityPose = 32, // 运行时精确追踪,而非基于推测或推算。通常来源于准确的传感器数据}
}

​ 需要注意,该枚举类被标识为 [Flags],因此可以多选。

4 XRHandSubsystem

XRHandSubsystem 是一个抽象类或基类,通常由特定平台或设备的实现类继承和扩展,专门处理与手部追踪相关的数据,并提供框架来处理手部的状态、姿势、关节和手势等信息。

4.1 数据属性

public partial class XRHandSubsystem : SubsystemWithProvider<XRHandSubsystem, XRHandSubsystemDescriptor, XRHandSubsystemProvider>
{// 左、右手信息public XRHand leftHand { get; }public XRHand rightHand { get; } // 存储手部关节的布局信息(每个关节是否存在)public NativeArray<bool> jointsInLayout { get; }// 在最近一次手部数据更新过程中,左右手的哪些数据被成功更新。// 该属性每次手部数据更新时都会被更新。public UpdateSuccessFlags updateSuccessFlags { get; } // 与左、右手相关的常见手势的识别数据public XRCommonHandGestures leftHandCommonGestures { get; }public XRCommonHandGestures rightHandCommonGestures { get; }// 手部跟踪成功的回调事件public Action<XRHand> trackingAcquired;// 用于在手部数据的关节信息处理之前进行预处理。public Action<XRHandSubsystem, UpdateSuccessFlags, UpdateType> preprocessJoints;// 该回调会在手部数据更新时被调用。public Action<XRHandSubsystem, UpdateSuccessFlags, UpdateType> updatedHands;// 手部跟踪丢失的回调事件public Action<XRHand> trackingLost;...
}

​ 回调的执行顺序为:

​ trackingAcquired -> preprocessJoints -> updatedHands -> trackingLost。

注意:

updatedHands 事件每帧执行两次,最大化手部数据的更新频率:

  • 第一次:在 MonoBehaviour.Update 事件附近执行。
  • 第二次:在 Application.onBeforeRender 事件附近执行。

4.1.1 UpdateSuccessFlags

​ 包括以下:

/// <summary>
/// 在每次手部数据更新中,哪些手部数据被成功更新。
/// </summary>
[Flags]
public enum UpdateSuccessFlags
{// 没有任何数据被成功更新None = 0,// 左手根姿势数据已成功更新LeftHandRootPose = 1 << 0,// 左手关节数据已成功更新LeftHandJoints = 1 << 1,// 右手根姿势数据已成功更新RightHandRootPose = 1 << 2,// 右手关节数据已成功更新RightHandJoints = 1 << 3,// 所有有效的数据已成功更新All = LeftHandRootPose | LeftHandJoints | RightHandRootPose | RightHandJoints
}

4.1.2 UpdateType

/// <summary>
/// The timing of a hand update during a frame.
/// </summary>
public enum UpdateType
{// 类似 MonoBehaviour.Update 时机更新Dynamic,// 类似 Application.onBeforeRender 时机更新BeforeRender
}

4.2 处理器管理:注册和注销

XRHandSubsystem 支持在手部数据处理流程中插入自定义的处理器,通过 RegisterProcessorUnregisterProcessor 方法来进行管理。

public partial class XRHandSubsystem : SubsystemWithProvider<XRHandSubsystem, XRHandSubsystemDescriptor, XRHandSubsystemProvider>
{...List<IXRHandProcessor> m_Processors = new List<IXRHandProcessor>();public void RegisterProcessor<TProcessor>(TProcessor processor)where TProcessor : class, IXRHandProcessor{if (processor == null)throw new ArgumentException("Processor cannot be null.", nameof(processor));m_Processors.Add(processor);m_Processors.Sort(CompareProcessors);}public void UnregisterProcessor<TProcessor>(TProcessor processor)where TProcessor : class, IXRHandProcessor{m_Processors.Remove(processor);}...
}

​ 处理器需要实现 IXRHandProcessor 接口,负责处理和修改手部关节数据。每个处理器可以根据自己的优先级顺序进行数据处理,这个顺序由 callbackOrder 来决定。

​ 例如,在 HandVisualizer 场景中,Hand Visualizer 物体上挂载的 HandProcessor.cs 脚本就是一个处理器,依据 ProcessorExampleMode 来对 Hands 进行平滑或翻转处理。

image-20250101225219326

4.3 更新手部数据:TryUpdateHands 方法

​ 在 XRHandProviderUtility.cs 脚本中,m_Subsystem.TryUpdateHands() 方法被 Update() 方法调用。因此,TryUpdateHands() 方法用于每帧更新 Hands 数据。

​ 在 XRHandProviderUtility.cs 中的 OnUpdate() 和 OnBeforeRender() 方法分别调用了 Update() 方法,因此 m_Subsystem.TryUpdateHands() 方法每帧被更新 2 次,即 4.1 节中的注意内容。

image-20250101230034753

4.3.1 检查运行,交由第三方处理

​ 如果未运行,则直接返回。

​ 同时,向手部数据提供者发送请求,更新左右手的数据。

public virtual unsafe UpdateSuccessFlags TryUpdateHands(UpdateType updateType)
{if (!running)return UpdateSuccessFlags.None;updateSuccessFlags = provider.TryUpdateHands(updateType,ref m_LeftHand.m_RootPose,m_LeftHand.m_Joints,ref m_RightHand.m_RootPose,m_RightHand.m_Joints);...
}

4.3.2 手部状态追踪与更新

public virtual unsafe UpdateSuccessFlags TryUpdateHands(UpdateType updateType)
{...// 清除手指的状态缓存,确保每次计算时使用的是最新的数据。XRFingerShapeMath.ClearFingerStateCache(Handedness.Left);XRFingerShapeMath.ClearFingerStateCache(Handedness.Right);// 检测左右手追踪状态,判断是否触发 trackingAcquired 或 trackingLostvar wasLeftHandTracked = m_LeftHand.isTracked;var success = UpdateSuccessFlags.LeftHandRootPose | UpdateSuccessFlags.LeftHandJoints;m_LeftHand.isTracked = (updateSuccessFlags & success) == success;if (!wasLeftHandTracked && m_LeftHand.isTracked)trackingAcquired?.Invoke(m_LeftHand);else if (wasLeftHandTracked && !m_LeftHand.isTracked)trackingLost?.Invoke(m_LeftHand);var wasRightHandTracked = m_RightHand.isTracked;success = UpdateSuccessFlags.RightHandRootPose | UpdateSuccessFlags.RightHandJoints;m_RightHand.isTracked = (updateSuccessFlags & success) == success;if (!wasRightHandTracked && m_RightHand.isTracked)trackingAcquired?.Invoke(m_RightHand);else if (wasRightHandTracked && !m_RightHand.isTracked)trackingLost?.Invoke(m_RightHand);...
}

​ 对于左手:

  • wasLeftHandTracked:记录更新前左手的追踪状态。

  • success:判断左手根姿势和关节数据是否成功更新。

  • m_LeftHand.isTracked:根据 success 判断左手是否成功追踪。

    如果左手的追踪状态发生了变化(从未追踪到追踪,或从追踪中丧失),则触发 trackingAcquiredtrackingLost 回调。

​ 右手同理。

4.3.3 数据预处理和处理器

public virtual unsafe UpdateSuccessFlags TryUpdateHands(UpdateType updateType)
{...// 对手部关节数据进行预处理preprocessJoints?.Invoke(this, updateSuccessFlags, updateType);// 每个处理器都对关节数据进行处理for (int processorIndex = 0; processorIndex < m_Processors.Count; ++processorIndex)m_Processors[processorIndex].ProcessJoints(this, updateSuccessFlags, updateType);...
}

4.3.4 动态更新和手势支持

​ 如果更新类型是动态(Dynamic),并且手部数据提供者支持常见的手势数据,系统会更新不同的手势数据,例如:

  • AimPose:目标对准姿势。
  • GraspPose:抓握姿势。
  • PinchPose:捏合姿势。
  • GripPose:抓握姿势。

​ 对每种手势数据,XRHandSubsystem 会尝试从 provider 获取数据,并更新到对应的手势识别组件(m_LeftHandCommonGesturesm_RightHandCommonGestures)。如果数据不可用,则调用 Invalidate 方法使手势数据失效。

public virtual unsafe UpdateSuccessFlags TryUpdateHands(UpdateType updateType)
{...if (updateType == UpdateType.Dynamic && provider.canSurfaceCommonPoseData){if (subsystemDescriptor.supportsAimPose){if (provider.TryGetAimPose(Handedness.Left, out var aimPoseLeft))m_LeftHandCommonGestures.UpdateAimPose(aimPoseLeft);elsem_LeftHandCommonGestures.InvalidateAimPose();}// 其它手势处理类似:GraspPose, PinchPose, GripPose等...}...
}

4.3.5 回调处理

​ 在数据更新后,通过 updatedHandshandsUpdated 回调通知外部系统手部数据已经更新。

updatedHands 是较新的回调方法,而 handsUpdated 已经被弃用,但仍然保持兼容。

public virtual unsafe UpdateSuccessFlags TryUpdateHands(UpdateType updateType)
{...if (updatedHands != null)updatedHands.Invoke(this, updateSuccessFlags, updateType);#pragma warning disable 618if (handsUpdated != null)handsUpdated.Invoke(updateSuccessFlags, updateType); // 弃用,但保持兼容
#pragma warning restore 618return updateSuccessFlags;
}

相关文章:

2025-01-01 NO2. XRHands 介绍

文章目录 软件配置1 XR Hands 简介2 XRHand2.1 Pose2.2 Handedness 3 XRHandJoint3.1 XRHandJointID3.2 XRHandJointTrackingState 4 XRHandSubsystem4.1 数据属性4.1.1 UpdateSuccessFlags4.1.2 UpdateType 4.2 处理器管理&#xff1a;注册和注销4.3 更新手部数据&#xff1a;…...

Java开发-后端请求成功,前端显示失败

文章目录 报错解决方案1. 后端未配置跨域支持2. 后端响应的 Content-Type 或 CORS 配置问题3. 前端 request 配置问题4. 浏览器缓存或代理问题5. 后端端口未被正确映射 报错 如下图&#xff0c;后端显示请求成功&#xff0c;前端显示失败 解决方案 1. 后端未配置跨域支持 …...

未来20年在大语言模型相关研究方向--大语言模型的优化与改进

未来20年在大语言模型相关研究方向 模型性能优化 模型架构创新:研究新型的模型架构,如探索更高效的Transformer变体、融合递归神经网络(RNN)和卷积神经网络(CNN)的优点,以提高模型的性能、可扩展性和适应性,满足不同应用场景对模型效率和效果的要求。高效训练算法:开…...

[react] 纯组件优化子

有组件如下,上面变化秒数, 下面是大量计算的子组件,上面每一秒钟变化一次,这时候子组件会不断重新渲染, 浪费资源 父组件如下 import React, { memo, useEffect, useMemo, useState } from react; import type { ReactNode, FC } from react; import HugeCount from ./Te; int…...

美观强大的文件保险库Chibisafe

简介 什么是 Chibisafe &#xff1f; Chibisafe 是一款用 Typescript 编写的快速文件上传服务&#xff0c;非常实用。它接受文件、照片、文档以及您能想到的任何内容&#xff0c;并返回可共享的链接&#xff0c;供您发送给其他人。它易于使用、易于部署、免费且开源&#xff0…...

详细教程:SQL2008数据库备份与还原全流程!

数据的安全性至关重要&#xff0c;无论是操作系统、重要文件、磁盘存储&#xff0c;还是企业数据库&#xff0c;备份都是保障其安全和完整性的关键手段。拥有备份意味着即使发生误删、系统崩溃或病毒攻击等问题&#xff0c;也能迅速通过恢复功能解决&#xff0c;避免数据丢失带…...

HTML——49.header和footer标签

<!DOCTYPE html> <html><head><meta charset"UTF-8"><title>header和footer标签</title></head><body><!--header和footer标签:是html5中新标签--><!--header:定义文档的页眉&#xff0c;通常用来定义可见…...

【蓝桥杯选拔赛真题87】python输出字符串 第十五届青少年组蓝桥杯python选拔赛真题 算法思维真题解析

目录 python输出字符串 一、题目要求 1、编程实现 2、输入输出 二、算法分析 三、程序编写 四、程序说明 五、运行结果 六、考点分析 七、 推荐资料 1、蓝桥杯比赛 2、考级资料 3、其它资料 python输出字符串 第十五届蓝桥杯青少年组python比赛选拔赛真题详细解析…...

OpenStack-Dashboard界面简单修改

OpenStack Dashboard界面替换图片 一、dashboard界面Logo的路径及文件 dashboard的Logo存放&#xff08;在Controller节点&#xff09;的路径&#xff1a; /usr/share/openstack-dashboard/openstack_dashboard/static/dashboard/img/涉及需要修改的文件&#xff08;3个&…...

DevOps工程技术价值流:Ansible自动化与Semaphore集成

在DevOps的浪潮中&#xff0c;自动化运维工具扮演着举足轻重的角色。Ansible&#xff0c;作为一款新兴的自动化运维工具&#xff0c;凭借其强大的功能和灵活性&#xff0c;在运维领域迅速崭露头角。本文将深入探讨Ansible的特点、架构、工作原理&#xff0c;以及其应用场景&…...

【服务器】上传文件到服务器并训练深度学习模型下载服务器文件到本地

前言&#xff1a;本文教程为&#xff0c;上传文件到服务器并训练深度学习模型&#xff0c;与下载服务器文件到本地。演示指令输入&#xff0c;完整的上传文件到服务器&#xff0c;并训练模型过程&#xff1b;并演示完整的下载服务器文件到本地的过程。 本文使用的服务器为云服…...

第四届电子信息工程与数据处理(EIEDP 2025)

第四届电子信息工程与数据处理 2025 4th International Conference on Electronic Information Engineering and Data Processing 2025年1月17-19日 马来西亚 吉隆坡 重要信息 会议官网&#xff1a;www.eiedp.net 大会时间&#xff1a;2025年1月17-19日 大会地点&#…...

模型预测控制(MPC)算法介绍

模型预测控制&#xff08;Model Predictive Control&#xff0c;MPC&#xff09;是一种先进的控制策略&#xff0c;广泛应用于工业过程控制、机器人控制、电力系统等领域。它基于系统的模型&#xff0c;通过滚动优化来预测系统未来的行为&#xff0c;并据此确定当前的最优控制输…...

设计模式 创建型 建造者模式(Builder Pattern)与 常见技术框架应用 解析

建造者模式&#xff0c;又称生成器模式&#xff0c;是一种对象构建模式。它主要用于构建复杂对象&#xff0c;通过将复杂对象的构建过程与其表示分离&#xff0c;使得同样的构建过程可以创建出具有不同表示的对象。该模式的核心思想是将一个复杂对象的构建过程分解为多个简单的…...

嵌入式系统中C++的基本使用方法

大家好,今天主要给大家分享一下,最近操作C++代码的控制方法。 什么是构造函数?构造函数在对象实例化时被系统自动调用,仅且调用一次。 什么是析构函数?与构造函数相反, 在对象结束其生命周期时系统自动执行析构函数。 第一个:析构函数与构造函数区别 实例代码: #inclu…...

机器人C++开源库The Robotics Library (RL)使用手册(四)

建立自己的机器人3D模型和运动学模型 这里以国产机器人天机TR8为例,使用最普遍的DH运动学模型,结合RL所需的描述文件,进行生成。 最终,需要的有两个文件,一个是.wrl三维模型描述文件;一个是.xml运动学模型描述文件。 1、通过STEP/STP三维文件生成wrl三维文件 机器人的…...

在 uni-app 中使用 wxml-to-canvas 的踩坑经验总结

在 uni-app 中使用 wxml-to-canvas 的踩坑经验总结 wxml-to-canvas 是一款非常强大的小程序工具&#xff0c;可以将 WXML 转换为 Canvas 绘图&#xff0c;用于生成海报、分享图片等。将其应用于 uni-app 项目中&#xff0c;可以为多端开发带来极大的便利&#xff0c;但也有一些…...

视频智能翻译

i68,爱六八,链接你我他 EasyVideoTrans英文视频转换成中文视频 EasyVideoTrans简要 最快的英文视频转中文方案由B站多位程序员Up主共同协作开发开源的项目在线Demo:EasyVideoTrans前端项目:https://github.com/sutro-planet/easyvideotrans-frontend后端项目:https://github…...

《Python加解密小实验:探索数据加密与解密的世界》

铺垫&#xff08;1&#xff09;-源码 import hashlib source "你好" # print(hashlib.md5(source.encode()).hexdigest())# 文件加解密 with open(../文件引用/index.png, rb) as file:data file.read() # print(hashlib.md5(data).hexdigest())# SHA也是摘要算法…...

C高级day四shell脚本

1.思维导图 2.终端输入一个C源文件名&#xff08;.c结尾&#xff09;判断文件是否有内容&#xff0c;如果没有内容删除文件&#xff0c;如果有内容编译并执行该文件。 #!/bin/bashread -p "请输入一个.c脚本名&#xff1a;" n if [ -s "$n" ] thenecho $n…...

定时器任务——若依源码分析

分析util包下面的工具类schedule utils&#xff1a; ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类&#xff0c;封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz&#xff0c;先构建任务的 JobD…...

macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用

文章目录 问题现象问题原因解决办法 问题现象 macOS启动台&#xff08;Launchpad&#xff09;多出来了&#xff1a;Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显&#xff0c;都是Google家的办公全家桶。这些应用并不是通过独立安装的…...

反射获取方法和属性

Java反射获取方法 在Java中&#xff0c;反射&#xff08;Reflection&#xff09;是一种强大的机制&#xff0c;允许程序在运行时访问和操作类的内部属性和方法。通过反射&#xff0c;可以动态地创建对象、调用方法、改变属性值&#xff0c;这在很多Java框架中如Spring和Hiberna…...

C# 类和继承(抽象类)

抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...

uniapp微信小程序视频实时流+pc端预览方案

方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度​WebSocket图片帧​定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐​RTMP推流​TRTC/即构SDK推流❌ 付费方案 &#xff08;部分有免费额度&#x…...

微信小程序云开发平台MySQL的连接方式

注&#xff1a;微信小程序云开发平台指的是腾讯云开发 先给结论&#xff1a;微信小程序云开发平台的MySQL&#xff0c;无法通过获取数据库连接信息的方式进行连接&#xff0c;连接只能通过云开发的SDK连接&#xff0c;具体要参考官方文档&#xff1a; 为什么&#xff1f; 因为…...

基于TurtleBot3在Gazebo地图实现机器人远程控制

1. TurtleBot3环境配置 # 下载TurtleBot3核心包 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone -b noetic-devel https://github.com/ROBOTIS-GIT/turtlebot3.git git clone -b noetic https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git git clone -b noetic-dev…...

人机融合智能 | “人智交互”跨学科新领域

本文系统地提出基于“以人为中心AI(HCAI)”理念的人-人工智能交互(人智交互)这一跨学科新领域及框架,定义人智交互领域的理念、基本理论和关键问题、方法、开发流程和参与团队等,阐述提出人智交互新领域的意义。然后,提出人智交互研究的三种新范式取向以及它们的意义。最后,总结…...

人工智能(大型语言模型 LLMs)对不同学科的影响以及由此产生的新学习方式

今天是关于AI如何在教学中增强学生的学习体验&#xff0c;我把重要信息标红了。人文学科的价值被低估了 ⬇️ 转型与必要性 人工智能正在深刻地改变教育&#xff0c;这并非炒作&#xff0c;而是已经发生的巨大变革。教育机构和教育者不能忽视它&#xff0c;试图简单地禁止学生使…...

JavaScript 数据类型详解

JavaScript 数据类型详解 JavaScript 数据类型分为 原始类型&#xff08;Primitive&#xff09; 和 对象类型&#xff08;Object&#xff09; 两大类&#xff0c;共 8 种&#xff08;ES11&#xff09;&#xff1a; 一、原始类型&#xff08;7种&#xff09; 1. undefined 定…...