基于UE5和ROS2的激光雷达+深度RGBD相机小车的仿真指南(三)---创建自定义激光雷达Componet组件

前言

  • 本系列教程旨在使用UE5配置一个具备激光雷达+深度摄像机的仿真小车,并使用通过跨平台的方式进行ROS2UE5仿真的通讯,达到小车自主导航的目的。
  • 本教程默认有ROS2导航及其gazebo仿真相关方面基础,Nav2相关的学习教程可以参考本人的其他博客Nav2代价地图实现和原理–Nav2源码解读之CostMap2D(上)-CSDN博客
  • 往期教程:
    • 第一期:基于UE5和ROS2的激光雷达+深度RGBD相机小车的仿真指南(一)—UnrealCV获取深度+分割图像-CSDN博客
    • 第二期:基于UE5和ROS2的激光雷达+深度RGBD相机小车的仿真指南(二)—ROS2与UE5进行图像数据传输-CSDN博客
  • UE5系列教程:
    • 第一期:UE5-C++入门教程(一):使用代码创建一个指定目标的移动小球-CSDN博客
    • 第二期:UE5-C++入门教程(二)—编写Editor类别的自定义模型实现小球规划路线的可视化-CSDN博客
  • 本教程环境支持:
    • UE5.43
    • ubuntu 22.04 ros2 humble
  • 前两期我们讲了如何使用UnrealCVUE5中捕获深度,分割,原始图像,并借助rosbridge将图像数据实时传输到ubuntu22.04 ros2 humble中。本期我们来讲讲如何在UE5中模拟激光雷达的仿真数据。

激光雷达

介绍
  • 激光雷达(Lidar)是一种利用激光来探测和测量物体距离、速度、方位和形状的技术。它通过发射激光脉冲,并接收从目标反射回来的激光,从而计算出目标的位置和特性。激光雷达广泛应用于各种领域,如地理信息系统(GIS)、环境监测、遥感、自动驾驶汽车、考古学等。请添加图片描述

  • 激光雷达的基本工作原理如下:

    1. 发射激光:激光雷达系统发射激光脉冲,这些脉冲可以是连续波或者脉冲波。
    2. 反射激光:激光脉冲照射到目标物体后,部分光波会被反射回来。
    3. 接收反射光:激光雷达系统中的接收器会捕捉到反射回来的激光。
    4. 数据处理:系统通过计算激光发射和接收之间的时间差,以及激光的波长,来确定目标的距离。通过分析反射光的强度、频率变化等,还可以获取目标的速度、方位和形状等信息。
性能指标
  • 这里我们借助镭神智能公司旗下的16线机械式激光雷达来讲解激光雷达具备的基本参数(这里不是广告(迫真))请添加图片描述

    1. 激光波长905nm:
    • 激光波长是激光雷达发射的激光的波长,通常以纳米(nm)为单位。常用的波长包括905nm和1550nm。不同波长的激光具有不同的特性和应用,例如,905nm波长的激光雷达通常成本较低,但容易受到阳光和其他环境因素的干扰;而1550nm波长的激光雷达具有更好的抗干扰能力和较长的探测距离。
  1. 探测距离70/120/150/200m:
    • 探测距离是指激光雷达能够有效测量目标的最远距离。探测距离受激光功率、目标反射率、大气条件等因素的影响。通常,激光雷达的探测距离从几米到几百米不等。
  2. 视场角(FOV)- 水平视场角:360°,垂直视场角:-15°~15° / -10°~10°:
    • 视场角是指激光雷达能够覆盖的水平或垂直角度范围。水平视场角通常为360度,而垂直视场角则取决于激光雷达的具体设计。视场角越大,激光雷达能够感知的环境范围就越广。
  3. 测距精度±3cm:
    • 测距精度是指激光雷达测量距离的准确程度,通常以厘米或毫米为单位。高精度的激光雷达可以提供非常准确的距离测量,这对于需要高精度定位和测量的应用至关重要。
  4. 角分辨率垂直:2°,水平:0.09°@5Hz, 0.18°@10Hz, 0.36°@20Hz:
    • 角分辨率是指激光雷达能够分辨的最小角度变化。高角分辨率意味着激光雷达可以更细致地描绘目标的形状和轮廓。角分辨率通常分为水平角分辨率和垂直角分辨率。
  5. 出点数- 320,000点/秒(单回波):
    • 出点数是指激光雷达每秒钟能够发射的激光点数。出点数越多,激光雷达获取的环境信息越丰富,扫描速度越快。
  6. 线束16线:
    • 线束是指激光雷达在垂直方向上的激光束数量。多线激光雷达通过多个激光发射器在垂直方向上的分布,形成多条线束的扫描。线束越多,对环境的描述越充分。
  7. 安全等级 1级(人眼安全):
    • 激光雷达的安全等级需要满足特定的安全标准,例如Class 1,以确保在正常使用条件下不会对用户造成伤害。
  8. 输出参数
    • 输出参数包括障碍物的位置、速度、方向、时间戳、反射率等,这些参数对于后续的数据处理和分析至关重要。
  9. IP防护等级IP67:
    • IP防护等级表示激光雷达对固体颗粒和水的防护能力,对于在恶劣环境下工作的激光雷达尤为重要。
  10. 功率和供电电压
    • 功率和供电电压决定了激光雷达的能耗和适用场景。激光雷达的功率通常以瓦特(W)为单位,供电电压则取决于激光雷达的具体设计。
  11. 激光发射方式- 机械旋转:
    • 激光发射方式分为机械旋转和固态两种。机械旋转激光雷达通过旋转发射器来扫描环境,而固态激光雷达则通过电子方式控制激光束的方向。
  12. 使用寿命
    • 使用寿命是指激光雷达在正常工作条件下的预期寿命。机械旋转激光雷达的使用寿命一般在几千小时,而固态激光雷达的使用寿命可高达10万小时。

题外话-旧版本UE5插件支持(不使用)

  • 值得一提的是,在UE5的虚幻商城中,是存在一款免费的2D雷达仿真插件的,但是由于其支持的引擎版本,本期我们不使用该插件请添加图片描述

1.创建自定义雷达插件

  • 本小结我们将借助激光雷达的原理,不借助任何现成插件,尝试在UE5中借助内置函数,通过cpp代码实现完成上述激光雷达的仿真。
1-1 概念解析–插件
  • Unreal Engine 5 (UE5) 提供了一个强大的插件系统,允许开发者扩展和定制引擎的功能。插件可以是社区创建的,也可以是 Epic Games 官方提供的,它们可以添加新的工具、功能、内容或集成到 Unreal Engine 中。
  • UE5 插件的特点和优势包括:
    1. 模块化:插件通常以模块的形式集成到 Unreal Engine 中,这意味着它们可以独立于引擎的其他部分进行开发、编译和更新。
    2. 可定制性:开发者可以根据自己的需求定制插件,添加新的功能或改进现有功能。
    3. 可重用性:插件可以在不同的项目中重用,节省开发时间和资源。
    4. 易于安装:Unreal Engine 提供了一个插件市场,开发者可以轻松地浏览、安装和管理插件。
  • 要使用 UE5 插件,我们只需要将其导入到 Unreal Engine 项目中。一旦插件被导入,开发者可以在项目的插件管理器中启用或禁用插件,并根据需要配置插件的设置。请添加图片描述

1-2 创建自定义插件
  • 新建一个新的项目(这里取名为Plugins_project),选择C++而不是蓝图,否则我们将会只有一种类型的插件

  • 打开你的新建的项目(记得确保是C++),在左上角菜单栏点击编辑,在下拉菜单栏中找到插件,在新打开的插件窗口中选择+ 添加,会出现如下画面请添加图片描述

  • 这里我们把插件名字定义为LaserScannerSim请添加图片描述

    • 作者:我www
    • 描述为:a plugin which mantian at 2D laser scanning simualtion including laser displaying and laser messages publishing
  • VS2022打开项目(记得重新加载),在项目根目录下会多出一个Plugins文件夹请添加图片描述

  • .uplugin 文件是 Unreal Engine 中的插件描述文件,它定义了插件的各种元数据和设置,包括插件的名称、版本、描述、作者、加载阶段、模块列表等。这个文件是插件的重要组成部分,它告诉 Unreal Engine 如何加载、集成和管理插件。我们来关注LaserScannerSim.uplugin这个文件的结尾部分

"Modules": [{"Name": "LaserScannerSim","Type": "Runtime","LoadingPhase": "Default"}
]
  • Name: LaserScannerSim 这是模块的名称,它应该是独一无二的,并且会用作模块的标识符。在代码中,通常会与模块相关的文件和目录同名。
  • Type: "Runtime" 这表示模块类型为运行时模块。运行时模块包含在游戏或应用程序的运行时阶段加载的代码和资源。
  • LoadingPhase: "Default" - 这指定了模块的加载阶段。Default 加载阶段意味着模块将在默认的加载时间点被加载,这对于大多数插件来说是合适的。如果需要更细粒度的控制,可以指定其他加载阶段,例如 PostEngineInitPreLoadMapPostLoadMap
  • 这里我们把这个插件的LoadingPhase改为PostEngineInit,我希望模块在引擎初始化完成后加载。
"Modules": [{"Name": "LaserScannerSim","Type": "Runtime","LoadingPhase": "PostEngineInit"}
]

  • 紧接着我们来看看该插件文件夹下的两个文件夹
  • Public:LaserScannerSim.hpp
// Copyright Epic Games, Inc. All Rights Reserved.#pragma once#include "CoreMinimal.h"
#include "Modules/ModuleManager.h"class FLaserScannerSimModule : public IModuleInterface
{
public:/** IModuleInterface implementation */virtual void StartupModule() override;virtual void ShutdownModule() override;
};
  • Private:LaserScannerSim.cpp
// Copyright Epic Games, Inc. All Rights Reserved.#include "LaserScannerSim.h"#define LOCTEXT_NAMESPACE "FLaserScannerSimModule"void FLaserScannerSimModule::StartupModule()
{// This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module
}void FLaserScannerSimModule::ShutdownModule()
{// This function may be called during shutdown to clean up your module.  For modules that support dynamic reloading,// we call this function before unloading the module.
}#undef LOCTEXT_NAMESPACEIMPLEMENT_MODULE(FLaserScannerSimModule, LaserScannerSim)
  • StartupModuleShutdownModule。这两个函数分别在模块加载到内存后和卸载前调用。稍后我们将讲述如何运用
  • IModuleInterface类它定义了模块(Module)在Unreal Engine中加载和卸载时的行为。
1-3 报错提示-UE5.4版本BUG
  • 值得注意的是,在UE5.4中,在上述创建自定义插件后在VS2022进行编译会出现下述报错请添加图片描述

  • 这是因为你不能在UE的Live Coding enabled的时候进行编译,这时我们选择关闭UE的Live Coding enabled请添加图片描述

  • 重新编译,成功。


2 创建自定义Componet雷达组件

  • 我们来快速思考以下,我们要创建的雷达插件应该是可以广泛运用到用户的各类模型(Actor)上,用户可以根据调用我们的雷达组件,根据其喜好参数,把此组件运用到任意模组中,可以是车辆,或者是雷达模型上。因此我们要创建一个Componet组件,它可以被套用到用户希望的Actor上
2-1 创建自定义雷达组件Components
  • 创建组件的详细教程见->UE5-C++入门教程(一):使用代码创建一个指定目标的移动小球-CSDN博客

  • 这里我们快速创建一个组件,选择ActorComponent作为父类请添加图片描述

  • 为新的组件取名为LaserScanner2D注意添加到我们的插件模块下(并设置为私有)请添加图片描述


2-2 激光雷达实现函数
  • 这里介绍一个UE5提供的内置函数LineTraceSingleByChannel,我们打开官方API手册,搜索得到相关关于这个函数的API实现请添加图片描述

  • 函数 LineTraceSingleByChannel 用于执行光线投射(Line Tracing)。这个函数可以用来检测从起点到终点之间是否有碰撞,并返回碰撞信息。

    • FHitResult & OutHit 用于存储光线投射的结果。如果检测到碰撞,这个参数会被填充碰撞信息,例如碰撞的位置、碰撞的物体等。
    • const FVector & Start 这是光线投射的起点,类型为 FVector,表示三维空间中的一个点。
    • const FVector & End: 这是光线投射的终点,类型同样为 FVector
    • ECollisionChannel TraceChannel 这是一个枚举类型,用于指定需要检测的碰撞通道。
    • const FCollisionQueryParams & Params:这是一个引用参数,用于配置光线投射的查询参数,允许你设置诸如忽略特定的Actor、检测隐藏的Actor等选项。
    • const FCollisionResponseParams & ResponseParam:允许你设置碰撞后的响应行为
bool LineTraceSingleByChannel  
&40;  struct FHitResult & OutHit,  const FVector & Start,  const FVector & End,  ECollisionChannel TraceChannel,  const FCollisionQueryParams & Params,  const FCollisionResponseParams & ResponseParam  
&41; const  

2-3 激光雷达可视化
  • 这里我们使用DrawDebugLine对雷达的射线进行可视化请添加图片描述

  • WorldContextObject: 表示当前世界上下文的对象。通常,你会传递GetWorld()的返回值给这个参数,它会返回一个指向当前游戏世界的指针。

  • LineStart: 直线的起始位置,它是一个FVector类型,表示三维空间中的一个点。
  • LineEnd: 直线的结束位置,它也是一个FVector类型,表示三维空间中的另一个点。
  • LineColor: 直线的颜色,它是一个FLinearColor类型,允许你设置红、绿、蓝和透明度。
  • Duration: 直线在游戏世界中显示的时间(以秒为单位)。如果设置为-1.0f,直线会一直显示直到下一帧或显式地被清除。
  • Thickness: 直线的厚度(以世界单位为单位)。这允许你设置直线的宽度。
static void DrawDebugLine  
&40;  const UObject &42; WorldContextObject,  const FVector LineStart,  const FVector LineEnd,  FLinearColor LineColor,  float Duration,  float Thickness  
&41;  

2-4 编写雷达组件基本逻辑
  • 那么我们来编写一下雷达组件的实现逻辑
  • LaserScanner2D.hpp,我们为雷达组件添加以下逻辑的代码
    • FVector StartRelativeLocation; //起始位置
    • bool bScanEnabled = true; //是否使能
    • int32 Resolution = 1; // 分辨率,每1度检测一次
    • float ScanHz = 30.0f; // 扫描频率,每秒30次
    • float LaserMinDistance = 0.1f; // 最近检测距离
    • float LaserMaxDistance = 100.0f; // 最远检测距离
    • float debugLineStayDuration = 1.0f; // 射线持续时间
// Fill out your copyright notice in the Description page of Project Settings.#pragma once#include "CoreMinimal.h"
#include "Components/ActorComponent.h"
#include "LaserScanner2D.generated.h"UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
class ULaserScanner2D : public UActorComponent
{GENERATED_BODY()public:	// Sets default values for this component's propertiesULaserScanner2D();protected:// Called when the game startsvirtual void BeginPlay() override;
public:void ScanForObjects();
public:	// Called every framevirtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;private:UPROPERTY(EditAnywhere)FVector StartRelativeLocation; //起始位置UPROPERTY(EditAnywhere)bool bScanEnabled = true; //是否使能UPROPERTY(EditAnywhere)int32 Resolution = 1; // 分辨率,每10度检测一次UPROPERTY(EditAnywhere)float ScanHz = 30.0f; // 扫描频率,每秒30次UPROPERTY(EditAnywhere)float LaserMinDistance = 0.1f; // 最近检测距离UPROPERTY(EditAnywhere)float LaserMaxDistance = 100.0f; // 最远检测距离UPROPERTY(EditAnywhere)float debugLineStayDuration = 1.0f; // 射线持续时间
};
  • LaserScanner2D.cpp
  • 我们在BeginPlay()初始化一个起始位置
#include "LaserScanner2D.h"
ULaserScanner2D::ULaserScanner2D()
{PrimaryComponentTick.bCanEverTick = true;
}
void ULaserScanner2D::BeginPlay()
{Super::BeginPlay();StartRelativeLocation = FVector(0.0f, 0.0f, 0.0f);
}
  • TickComponent将会一直运行,我们让其根据我们指定的频率去调用我们写的雷达扫描函数
void ULaserScanner2D::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{Super::TickComponent(DeltaTime, TickType, ThisTickFunction);static float AccumulatedTime = 0.0f; // 累积时间AccumulatedTime += DeltaTime; // 累加Delta Time// 当累积时间达到扫描周期时,执行扫描if (AccumulatedTime >= 1.0f / ScanHz){ScanForObjects();AccumulatedTime -= 1.0f / ScanHz; }
}
  • 雷达扫描函数
    • for (int32 i = 0; i < 360; i += Resolution)我们按照指定分辨率去选择扫描
    • Rotation: 这个FRotator对象表示当前射线发射的方向。它是一个绕Y轴旋转的旋转器,其Z轴和X轴的值为0,Y轴的值为当前的角度i
    • EndLocation: 这是当前射线的结束位置。它通过将StartLocationRotation的向量相加以LaserMaxDistance的长度来计算得出。FMath::Clamp函数确保这个距离不会超过LaserMaxDistance的最远距离,也不会小于LaserMinDistance的最近距离。
    • OutHit: 这是一个FHitResult对象,它用于存储射线与场景中其他对象碰撞的信息。
    • Params: 这是一个FCollisionQueryParams对象,它定义了射线检测的参数。
    • AddIgnoredActor(GetOwner())调用确保激光雷达不会与自己所在的Actor发生碰撞。
    • 如果检测到膨胀,则绘制一条从StartLocationOutHit.Location的绿色直线。OutHit.Location是射线碰撞点的位置。如果没有检测到碰撞,则绘制一条从StartLocationEndLocation的红色直线。
  • GetWorld():
    • 在Unreal Engine中,GetWorld()是一个成员函数,用于获取当前ActorComponent所在的World对象。World对象是Unreal Engine中的一个核心概念,它代表了游戏世界的环境,包括场景中的所有Actor、地形、光照、音效等。
UWorld* GetWorld() const;
  • GetWorld()成员函数是许多类的接口的一部分,尤其是那些与游戏世界直接交互的类。以下是一些常见的具有GetWorld()函数的类:
    1. AActor: 代表游戏世界中的可移动对象。
    2. UActorComponent: 代表附加到Actor上的组件,它们通常需要访问游戏世界来进行各种操作。
    3. UGameInstance: 代表游戏会话的单例,它可以访问当前的游戏世界。
    4. ULevel: 代表游戏世界中的一个关卡。
    5. APlayerController: 代表玩家控制器,它可以访问游戏世界来控制玩家视角和输入。
    6. AGameModeBase: 代表游戏模式,它定义了游戏的基本规则和流程。
    7. UUserWidget: 代表游戏中的用户界面元素,它可能需要访问游戏世界来获取数据或执行操作。
    8. UFieldSystem: 代表场系统,用于在游戏世界中模拟物理场。
  • 然而,并不是所有的类都有GetWorld()函数。
void ULaserScanner2D::ScanForObjects()
{const FVector StartLocation = StartRelativeLocation;for (int32 i = 0; i < 360; i += Resolution){FRotator Rotation = FRotator(0.0f, i, 0.0f);FVector EndLocation = StartLocation + Rotation.Vector() * FMath::Clamp(LaserMaxDistance, LaserMinDistance, LaserMaxDistance);FHitResult OutHit;FCollisionQueryParams Params;Params.AddIgnoredActor(GetOwner());if (GetWorld()->LineTraceSingleByChannel(OutHit, StartLocation, EndLocation, ECC_Visibility, Params)){DrawDebugLine(GetWorld(), StartLocation, OutHit.Location, FColor::Green, false, debugLineStayDuration);}else{DrawDebugLine(GetWorld(), StartLocation, EndLocation, FColor::Red, false, debugLineStayDuration);}}
}

2-5 编译与验证
  • 点击VS2022的绿色透明小箭头,编译代码

  • 在内容处创建一个蓝图类Lidar(UE教程我们详细见过了,这里快速通过)请添加图片描述

  • 为蓝图类添加LaserScanner2D组件 请添加图片描述

  • 我们把新的Lidar蓝图类添加到常见中,并为主场景添加一些基本的物体请添加图片描述

  • 我们可以在雷达类下修改一些基本的参数请添加图片描述

  • 运行,可以看到我们的雷达成功完成目标请添加图片描述


小结

  • 本期我们通过自定义插件的方式实现了激光雷达的仿真
  • 下一期我们将讲述如何对雷达数据进行打包并转发给ubuntuROS2
  • 感谢大家对本教程的支持!如有错误,欢迎指出!

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

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

相关文章

数学建模学习(115):主成分分析(PCA)与Python实践

文章目录 一.主成分分析简介1.1 数学背景与维度诅咒1.2 PCA的定义与应用二.协方差矩阵——特征值和特征向量三.如何为数据集选择主成分数量四.特征提取方法五.LDA——与PCA的区别六.PCA的应用七.PCA在异常检测中的应用八.总结一.主成分分析简介 1.1 数学背景与维度诅咒 主成成…

视频智能分析平台烟火检测视频安防监控烟火算法识别应用方案

烟火检测算法的应用方案主要围绕其核心技术——深度学习&#xff08;特别是卷积神经网络CNN&#xff09;和计算机视觉技术展开&#xff0c;旨在实现对监控视频中的烟雾和火焰进行实时、准确的检测与识别。以下是一个详细的烟火检测算法应用方案&#xff1a; 一、技术原理 烟火…

高并发集群饿了么后端的登录模块

高并发集群饿了么后端的登录模块 1.数据库 非交互式python&#xff1a; 非交互式: 2.数据库的负载均衡&#xff1a;阿里巴巴的mycat 修改配置文件 /usr/local/mycat/conf/server.xml :对外的账号 密码 数据库 /usr/local/mycat/conf/schema.xml 如果出现启动异常&…

【微信小程序】自定义组件 - 数据监听器

1. 什么是数据监听器 2. 数据监听器的基本用法 组件的 UI 结构如下&#xff1a; 组件的 .js 文件代码如下&#xff1a; 3. 监听对象属性的变化 数据监听器 - 案例 案例效果 2. 渲染 UI 结构 3. 定义 button 的事件处理函数 4. 监听对象中指定属性的变化 5. 监听对象中所…

readpaper在读论文时候的默认规定

红色代表主旨思想 蓝色代表专业名词解析

【MySQL】 黑马 MySQL进阶 笔记

文章目录 存储引擎MySQL的体系结构存储引擎概念存储引擎特点InnoDBMyISAMMemory 存储引擎选择 索引概述结构B Tree(多路平衡查找树)B TreeHash为什么InnoDB存储引擎选择使用Btree索引结构? 分类思考题 语法SQL性能分析&#xff08;索引相关&#xff09;SQL执行频率慢查询日志p…

XSS game复现(DOM型)

目录 1.Ma Spaghet! 2.Jefff 3.Ugandan Knuckles 4.Ricardo Milos 5.Ah Thats Hawt 6.Ligma 7.Mafia 8.Ok, Boomer 1.Ma Spaghet! 通过简单的尝试发现传递参数可以直接进入h2标签 接下来我们尝试传入一个alert(1) 可以看到并没有触发。原因是在innerHTML中官方禁用了sc…

MySQL InnoDB引擎四大特性ACID实现方案分析

文章目录 概要InnoDb引擎ACID模型的实现方案小结 概要 对于Mysql&#xff0c;事物的支撑并不依赖于Server层&#xff0c;不同的存储引擎对于事物的支持也不一样&#xff0c;对于我们常用的InnoDB引擎&#xff0c;其提供了一套基于【ACID模型】的事物完整的解决方案。为什么MyIS…

【AI Agent极限挑战赛】三大赛题揭晓

由AIGC开放社区联合联想拯救者、英特尔共同主办的【2024 AI Agent极限挑战赛】于8月17日在上海中庚聚龙酒店成功举办。赛事全面考察参赛者将AI技术应用于实际问题的能力。比赛内容包括对大语言模型的理解、提示词&#xff08;Prompt&#xff09;的结构化调优技术、个人助理Agen…

如何使用ssm实现在线云音乐系统的设计与实现

TOC ssm042在线云音乐系统的设计与实现jsp 第1章 绪论 1.1背景及意义 系统管理也都将通过计算机进行整体智能化操作&#xff0c;对于在线云音乐系统所牵扯的管理及数据保存都是非常多的&#xff0c;例如用户管理、歌曲管理、推荐管理等&#xff0c;这给管理者的工作带来了巨…

基于华为昇腾910B和LLaMA Factory多卡微调的实战教程

大家好,我是herosunly。985院校硕士毕业,现担任算法研究员一职,热衷于大模型算法的研究与应用。曾担任百度千帆大模型比赛、BPAA算法大赛评委,编写微软OpenAI考试认证指导手册。曾获得阿里云天池比赛第一名,CCF比赛第二名,科大讯飞比赛第三名。授权多项发明专利。对机器学…

uniapp点击预览图片,两种效果

背景&#xff1a; 在使用uniapp框架中&#xff0c;我们对图片的展示需要点击放大展示(单张)&#xff1b;如果是多张图片&#xff0c;要支持左右滑动查看多张图片(多张)。 官网链接&#xff1a;点击跳转官网 一、单张&#xff0c;点击放大 代码&#xff1a; <template> …

Kubernetes服务发布基础

通过k8s的调度&#xff0c;我们可以成功的将服务部署到Kubernetes&#xff0c;应用部署后&#xff0c;最重要的就是对用户开放。 在传统的架构中&#xff0c;用户访问公司内的服务可能通过了多层代理、网关、防火墙等。在Kubernetes中&#xff0c;访问Kubernetes中的的应用同样…

Windows下使用QT5.14.2编译MySQL8.0对应的最新64位驱动程序步骤

不得不说mysql更新的速度是真的快&#xff0c;最近一两年都更新了好几个的小版本了。如果安装了高版本的 mysql软件&#xff0c;低版本的驱动就不支持了&#xff0c;因此需要重新使用QT来编译对应的mysql驱动。具体办法如下&#xff1a; 1、官网下载最新的mysql8.0安装包。下载…

ABAP 引用变量(TYPE REF TO )和字段符号(FIELD-SYMBOLS)全集

本文主要是记录了一些关于ABAP 引用变量(TYPE REF TO )和字段符号(FIELD-SYMBOLS)的相关内容&#xff0c;有些参考来自多个博客&#xff0c;以及官方文档 文章目录 FIELD-SYMBOLS字段符号官方文档Declaring Field SymbolsTyping Field Symbols 引用变量文章1引用变量介绍测试程…

Linux文件属性和打包压缩详解

1、文件属性体系 1.1 文件系统概述 [rootyunwei /]# ls -lhi 总用量 72K3505 lrwxrwxrwx. 1 root root 7 3月 7 2019 bin -> usr/bin 262152 dr-xr-xr-x. 5 root root 4.0K 12月 19 16:00 boot 399635 drwxr-xr-x 2 root root 4.0K 11月 5 2019 data1026 drw…

electron-vite封装UI级的消息提示

说明 Electron Vite Vue3 Element Plus Electron中写提示有两种方案&#xff1a; 系统级&#xff1a;electron带的dialog相关APIUI级&#xff1a;UI框架内部的提示&#xff0c;如ElMessage、ElMessageBox、ElNotification等 今天来封装一下UI级别的提示 代码 效果图 源…

冷却液温度传感器检测诊断

检测发动机冷却液温度&#xff0c;向ECU输入温度信号&#xff0c;作为燃油喷射和点火正时的修正信号&#xff0c;同时也是其他控制系统的控制信号。 冷却液温度传感器安装位置 冷却液温度传感器&#xff08;俗称水温传感器&#xff09;一般安装在缸体水道上&#xff0c;缸盖水…

知识竞赛答题设备及答题方式有哪些

根据我们多年的知识竞赛承办经验&#xff0c;我来谈谈在知识竞赛中常用的答题设备和答题方式。 一、常用答题设备 1.电脑 如果电脑资源充足&#xff0c;可以用笔记本电脑进行答题&#xff0c;笔记本电脑可以采取有线或无线方式进行连网&#xff0c;可以根据情况选择连网方案&…

利用GPT绘制流程图(无需下载任何软件

目录 什么是Flowchart Fun&#xff1f;如何利用GPT绘制流程图&#xff1f;步骤1&#xff1a;确定流程图的目的和内容步骤2&#xff1a;训练GPT编写流程图的文本描述步骤3&#xff1a;转换文本格式为可视化的流程图步骤4&#xff1a;调整和优化 结论小结&#xff1a; 什么是Flow…