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

机器人操作系统:ROS2 仿真入门

塞巴斯蒂安

·

一、说明

在机器人项目中,仿真是一个具有多种用途的重要方面。首先,您可以测试希望机器人执行的行为代码。其次,您可以使用仿真来测试不同类型的硬件,例如距离传感器、相机或 3D 点云传感器,看看哪种效果最好。第三,可视化模拟的相同软件可以与真正的机器人实时使用,在机器人扫描和导航环境的同时查看环境。

        在我的机器人项目中,我从 ROS1 开始,并提供了一个可以使用 RVIZ 可视化的基本机器人模型。然后,我构建了一个实用的原型,完全基于Arduino,不涉及ROS。在项目的当前阶段,我致力于构建一个与视觉传感器兼容的 Gazebo 模型。

        本文继续该系列,使用 Gazebo 快速启动 ROS2 模拟。我们将了解创建模拟的基本工具 - ROS启动文件和Gazebo - 并学习应用基本步骤 - 选择3D模型,将它们放置在世界上。

        本文的技术背景是 Ubuntu 20.04、ROS2 Foxy、Gazebo11,但它也应该适用于较新的版本。

二、基本机器人仿真术语

        本段简要列出了理解物理仿真方面所必需的所有术语。如果您对词汇量很坚定,请跳过本节。

  • 运动学:运动学是物理学的一个分支,它控制着身体在时间、位置、速度和加速度方面的运动方式,而不考虑身体的重量或向外力,如重力
  • 动力学:物理学的另一个分支,它考虑当物体有质量并受到力影响时物体的位置、速度和加速度如何变化。(在机器人中,这也称为机器人动力学)
  • 里程计:一种通过连续记录运动数据来估计物体位置并计算物体移动的距离和轨迹的方法
  • 惯性:这种力是运动物体对任何其他会改变其方向、速度或加速度的力的阻力
  • 摩擦力:当两个物体靠近另一个物体移动并抵抗该移动时施加的力
  • 关节:关节是连接两个物体的机械元件。关节有不同的类型来描述连接的物体如何移动。

来源:ROS机器人编程书

  • RPY 值:此首字母缩略词代表横滚、俯仰、偏航,用于描述物体在 3D 空间中的运动。对象可以根据下图在这三个轴上移动:

来源: wikipedia.org

三、循序渐进:如何创建模拟世界

Gazebo是在ROS之外开始的,但后来完全整合了。它更侧重于机器人和世界的完整物理模拟。特别是,世界通过物理引擎提供正确的物理模拟:机器人可以撞到物体,这些物体会移动,最终甚至撞到你的机器人身上。Gazebo 带有预定义的世界模型,您甚至可以定义自己的模型。

在本教程中,我们将启动一个带有空世界的凉亭模拟,然后在里面生成一个机器人。简而言之,基本步骤是:

  • 创建新的 ROS 包并设置目录结构
  • 创建一个空的坐标定位文件
  • 创建启动文件
  • 在机器人 URDF 模型中添加其他物理属性
  • 参数化机器人 URDF 模型以使用 Gazebo 或 RVIZ 运行。
  • 用启动文件开始空的世界

以下各节详细介绍了这些任务。

3.1 第 1 步:包创建和目录结构

        我们将创建一个如下所示的包结构:

radu_gazebo/
├── config
│   └── rviz.config
├── launch
│   └── launch.py
├── radu_bot
│   └── __init__.py
├── resource
├── scripts
├── test
├── urdf
│   └── core.xacro
└── worlds
│   └── room.world
├── package.xml
├── setup.cfg
├── setup.py

为方便起见,只需运行以下命令:

ros2 pkg create  --build-type python radu_gazebo
mkdir radu_gazebo/launch radu_gazebo/world
mkdir radu_gazebo/launch radu_gazebo/world/room.world
touch radu_gazebo/launch/room.launch

3.2 第 2 步:清空坐标定位文件

        该文件是一个SDF文件,将包含我们想要模拟的所有内容的标签:墙壁,窗户和家具等对象。我们将从一个简单的空白世界开始,并逐步添加新对象。room.world<model>

<!-- FILE: world/room.world -->
<?xml version='1.0'?>
<sdf version="1.6">
<world name="room"><include><uri>model://sun</uri></include><include><uri>model://ground_plane</uri></include>
</world>
</sdf>

您可以手动将此文件加载到凉亭中。但是由于我们最终也将在这个模型中生成一个机器人,因此最好继续直接启动文件。

3.3 步骤 3:启动文件

        正如我们在上一篇文章中了解到的,ROS2 不再支持 XML 启动文件,而是使用 Python 文件。

        我们使用的启动文件包装包中的启动命令,并提供一个世界参数。gazebo_ros

#!/usr/bin/python3
import os
from ament_index_python.packages import get_package_share_directory
from launch import LaunchDescription
from launch.actions import DeclareLaunchArgument
from launch.actions import IncludeLaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSource
package_name = 'radu_bot'
world_file = 'room.world'
def generate_launch_description():pkg_gazebo_ros = get_package_share_directory('gazebo_ros')pkg_radu_simulation = get_package_share_directory(package_name)# launch Gazebo by including its definitiongazebo = IncludeLaunchDescription(PythonLaunchDescriptionSource(os.path.join(pkg_gazebo_ros, 'launch', 'gazebo.launch.py'),))# load the world fileworld_arg = DeclareLaunchArgument('world',default_value=[os.path.join(pkg_radu_simulation, 'worlds', world_file), ''],description='SDF world file')return LaunchDescription([gazebo,world_arg])

3.4 第 4 步:使用 Gazebo 标签扩展机器人模型

        为了在凉亭中使用RViz的URDF模型,我们需要对模型进行一些更改。

        首先,我们需要为机器人提供额外的物理方面,以便它在模拟中正确运行。其次,机器人的视觉外观不同。RVIZ 模型的颜色和文本定义不适用。如果使用网格,也需要更改它们。第三,我们还需要额外的插件,以便 Gazebo 工具正常工作

        让我们逐步查看这些更改。

3.5 物理模拟属性

惯性

物体的惯性是当其当前运动受到另一个物体影响时施加的反作用力。在凉亭模型中,标签用于表示这一方面。<inertial>

下面是一个示例:

<link name="base_link"><inertial><origin xyz="0 0 0" rpy="0 0 0"/><mass value="0.25" /><inertia ixx="0.000486" ixy="0.0" ixz="0.0" iyy="0.000486" iyz="0.0" izz="0.000729"/></inertial><visual><origin rpy="0 0 0" xyz="0 0 0"/><geometry><cylinder radius="0.09" length="0.09"/></geometry></visual>
</link>

        标签相对于其父链接定位链接,在这里您可以更改值以移动估计的质量中心。通过您指定此链接质量(以千克为单位)。最后,该元素是 x、y 和 z 上的力如何影响链接的矩阵。您可以在维基百科上阅读物理文章,或使用这个方便的python脚本。<origin>xyz<mass><inertial>

摩擦

        另一组变量控制机器人中链接的摩擦。你用四个值来表达这一点。首先,提供静态和动态接触刚度。在这里,我们使用值和,这是许多ROS项目中使用的默认值。其次,值和是静态和动态摩擦系数,您可以根据链接的材料在维基百科上查找。<kp><kd>1000001.0<mu1><mu2>

<gazebo reference="base_link"><kp>100000.0</kp><kd>1.0</kd><mu1>10.0</mu1><mu2>10.0</mu2>  
</gazebo>

碰撞

        这定义了机器人的硬材料边界——它会影响在模拟中将重力和其他力施加到机器人上的方式。这些属性由链接中的标记表示。它的属性非常简单:只需复制原始链接和值,如下所示。<collision><geometry><origin>

<link name="base_link"><inertial><origin xyz="0 0 0" rpy="0 0 0"/><mass value="0.25" /><inertia ixx="0.000486" ixy="0.0" ixz="0.0" iyy="0.000486" iyz="0.0" izz="0.000729"/></inertial><visual><origin rpy="0 0 0" xyz="0 0 0"/><geometry><cylinder radius="0.09" length="0.09"/></geometry></visual><collision><origin rpy="0 0 0" xyz="0 0 0"/><geometry><cylinder radius="0.09" length="0.09"/></geometry></collision>
</link>

关节特性

机器人中的关节应进一步建模,以表达其真实世界的行为。

  • 对于所有非静态、非连续接头,集合和值<upper><lower>
  • 对于所有连续接头,添加和限制<effort><velocity>
<joint name="camera_joint"><limit upper="0.5" lower="-0.5"/>
</joint>
<joint name="left_wheel_joint"><limit effort="0.1" velocity="0.005"/>
</joint>

3.6 可视化模拟属性

要更改机器人的视觉效果,您有以下选项:

简单的颜色

这与 RViz 中的工作方式相同:在链接标签中,您可以引用一个元素。<visual><color>

<material name="blue"><color rgba="0 0 0.8 1"/>
</material>
<link name="camera"><visuals><material name="blue"></visuals>
</link>

预定义网格

        Gazebo 提供了一组内置网格,这些网格在此源代码文件中列出。应用它们,在标签内添加标签,如下所示。<material><gazebo>

<gazebo reference="base_link"><material>Gazebo/Grey</material>  
</gazebo>

自定义网格

        使用自定义网格表示链接时,只需在链接的标记中引用它们,如下所示:<geometry>

<link name="camera"><mesh filename:"package://radu_bot/model/meshes/camera.dae" />
</link>

        重要提示:建议不要在标签中使用自定义网格文件,因为这会影响仿真性能。相反,请根据可用的盒子、圆柱体和球体类型定义值。<collision><geometry>

3.7 第 5 步:参数化机器人 URDF 模型以使用 Gazebo 或 RViz 跑步

        如您所见,所需的更改是根本性的。而且它们不向后兼容:Gazebo 所需的所有更改都无法被 RVIZ 解析。

        由于这些原因,复杂的机器人项目将URDF方面分成不同的XACRO文件。经过一些实验,我想出了以下层次结构。

  • core- 包含用于渲染机器人链接和关节的核心宏
  • rviz- RVIZ主文件,它定义参数并导入其他文件
  • rviz_viusals- 定义机器人在RViz中的可视化方式
  • gazebo- 凉亭核心文件,就像定义参数和导入其他文件一样
  • gazebo_visuals- 定义如何在凉亭中可视化机器人
  • gazebo_physics- 计算链接和标签的附加宏<inertial><collision>
  • gazebo_sensor- 添加传感器数据
  • gazebo_controll- 添加了 ROS 控制插件并定义用于渲染标签的宏<transmission>

让我们看看这种方法在实践中是如何工作的。运行 Xacro 渲染模型时,将使用命令 -o radu_rviz_compiled.urdf'。此文件将...xacro rviz.xacro

  1. 导入其他必需的文件
<xacro:include filename="$(find radu_bot)/urdf2/core.xacro"/>
<xacro:include filename="$(find radu_bot)/urdf2/visuals.xacro"/>

2. 定义控制宏执行的基本参数

<xacro:property name="gazebo_build" value="false" />
<xacro:property name="rviz_build" value="true" />

3. 执行宏以创建 URDF 模型

<xacro:box_link name="base_link" size="0.6 0.3 0.05" color="${torso_color_name}" color_rgb="${torso_color_rgb}" />
<xacro:wheel_link name="right_wheel_frontside" />
<xacro:wheel_joint name="base_link_right_wheel_frontside" parent="base_link" child="right_wheel_frontside" xyz="0.2 -0.2 -0.05" />
<xacro:wheel_link name="right_wheel_backside" />
<xacro:wheel_joint name="base_link_right_wheel_backside" parent="base_link" child="right_wheel_backside" xyz="-0.2 -0.2 -0.05" />
<xacro:wheel_link name="left_wheel_frontside" /> 
<xacro:wheel_joint name="base_link_left_wheel_frontside" parent="base_link" child="left_wheel_frontside" xyz="0.2 0.2 -0.05" />
<xacro:wheel_link name="left_wheel_backside" /> 
<xacro:wheel_joint name="base_link_left_wheel_backside" parent="base_link" child="left_wheel_backside" xyz="-0.2 0.2 -0.05" />

        在使用这种方法一段时间后,我意识到处理可变性的核心逻辑在文件内部:用于呈现链接和关节的宏具有将由主文件触发的不同块。请参阅以下定义。在第 3 行中,评估条件以添加特定于 RViz 的视觉对象。在第 14 行中,另一个条件检查凉亭物理属性并将其应用于模型。core.xacro<link><xacro:if>

<xacro:macro name="box_link" params="name size color color_rgb" ><link name="${name}"><xacro:if value="${rviz_build}"><visual><origin xyz="0 0 0" rpy="0 0 0"/><geometry><box size="${size}"/></geometry><material name="${color}"><color rgba="${color_rgb}"/></material></visual></xacro:if><xacro:if value="${gazebo_build}"><pose>0 0 0 0 0 0</pose><xacro:box_inertia m="0.6" x="0.7" y="0.4" z="0.2"/><collision name="collision_${name}"><origin xyz="0 0 0" rpy="0 0 0"/><geometry><box size="${size}"/></geometry></collision></xacro:if>  </link>
</xacro:macro>

3.8 第 6 步:生成机器人

        Gazebo 节点通过启动文件启动,但机器人需要生成到节点中。感谢博客文章如何在 ROS2 中生成机器人,我创建了以下启动文件。

#!/usr/bin/python3
import os
import sys
import rclpy
from gazebo_msgs.srv import SpawnEntity
from ament_index_python.packages import get_package_share_directory
package_name = 'radu_bot'
def main(args=None):rclpy.init(args=args)node = rclpy.create_node('minimal_client')cli = node.create_client(SpawnEntity, '/spawn_entity')sdf_file_path = (os.path.join(get_package_share_directory(package_name), 'urdf', 'radu_gazebo_compiled.urdf')),model = open(sdf_file_path[0], 'r').read()print("MODEL %s" %model)req = SpawnEntity.Request(name = "radu_bot",xml = model,robot_namespace = "radu",reference_frame = "world",)while not cli.wait_for_service(timeout_sec=1.0):node.get_logger().info('service not available, waiting again...')future = cli.call_async(req)rclpy.spin_until_future_complete(node, future)if future.result() is not None:node.get_logger().info('Result ' + str(future.result().success) + " " + future.result().status_message)else:node.get_logger().info('Service call failed %r' % (future.exception(),))node.destroy_node()rclpy.shutdown()
if __name__ == '__main__':main()

启动文件还可以在启动期间转换 Xacro 文件,如diff_bot示例中所示。例如,要加载 Gazebo 配置,您需要执行以下命令:

import xacro
def generate_launch_description():pkg_radu_simulation = get_package_share_directory(package_name)robot_description_path =  os.path.join(pkg_radu_simulation,"urdf","gazebo.xacro",)robot_description = {"robot_description": xacro.process_file(robot_description_path).toxml()}

四、启动机器人

首先,我们构建当前工作区。

$> colcon build --symlink-install --cmake-clean-first --event-handlers console_direct+ --packages-up-to radu_bot

然后我们推出凉亭。

$> ros2 launch radu_bot gazebo.launch.py 
[INFO] [launch]: All log files can be found below /home/devcon/.ros/log/2021-05-30-09-07-30-541933-giga-36879
[INFO] [launch]: Default logging verbosity is set to INFO
[INFO] [gzserver-1]: process started with pid [36886]
[INFO] [gzclient   -2]: process started with pid [36889]

然后生成机器人。

$> ros2 run radu_bot spawn_radu
[INFO] [1622358479.722919377] [minimal_client]: Result True SpawnEntity: Successfully spawned entity [radu_bot]

最后,渲染机器人:

五、结论

        本文向您展示了如何从头开始在 ROS2 中创建与 Gazebo 兼容的模拟。事实证明,这是一个漫长的 过程,您需要 (1) 创建一个包,(2) 创建坐标定位文件,(3) 创建启动文件,(4) 将 Gazebo 特定标签添加到我们的机器人模型中,(5) 参数化您的机器人模型以与 Gazebo 和 RVIZ 兼容,以及 (6) 在模拟中生成机器人实体。形成所有这些步骤。添加 Gazebo 物理是学习和应用的时间密集型,我希望您也能获得宝贵的见解。最后,我们可以使用自定义启动脚本文件在 Gazebo 和 RViz 中生成 RADU。从这里,我们可以在模拟中移动机器人。

相关文章:

机器人操作系统:ROS2 仿真入门

塞巴斯蒂安 一、说明 在机器人项目中&#xff0c;仿真是一个具有多种用途的重要方面。首先&#xff0c;您可以测试希望机器人执行的行为代码。其次&#xff0c;您可以使用仿真来测试不同类型的硬件&#xff0c;例如距离传感器、相机或 3D 点云传感器&#xff0c;看看哪种效果最…...

面试题:线程池的底层工作原理

线程池的几个重要的参数&#xff1a; 1、corePoolSize&#xff1a;线程池的核心线程数&#xff08;也是默认线程数&#xff09; 2、maximumPoolSize&#xff1a;最大线程数 3、keepAliveTime&#xff1a;允许的线程最大空闲时间&#xff08;单位/秒&#xff09; 线程池内部是…...

Excel/PowerPoint条形图改变顺序

条形图是从下往上排的&#xff0c;很多时候不是我们想要的效果 解决方案 选择坐标轴&#xff0c;双击&#xff0c;按下图顺序点击 效果...

【操作系统】虚拟内存相关分段分页页面置换算法

虚拟内存是什么&#xff1f; 【进程地址空间虚拟地址空间C/C程序地址空间就是那个4G的空间】 虚拟内存是操作系统内核为了对进程地址空间进行管理&#xff0c;而设计的一个逻辑意义上的内存空间概念。在程序运行过程中&#xff0c;虚拟内存中需要被访问的部分会被映射到物理内…...

Unrecognized Hadoop major version number: 3.0.0-cdh6.3.2

一.环境描述 spark提交job到yarn报错&#xff0c;业务代码比较简单&#xff0c;通过接口调用获取数据&#xff0c;将数据通过sparksql将数据写入hive中&#xff0c;尝试各种替换hadoop版本&#xff0c;最后拿下 1.hadoop环境 2.项目 pom.xml spark-submit \ --name GridCorr…...

机器学习分类,损失函数中为什么要用Log,机器学习的应用

目录 损失函数中为什么要用Log 为什么对数可以将乘法转化为加法&#xff1f; 机器学习&#xff08;Machine Learning&#xff09; 机器学习的分类 监督学习 无监督学习 强化学习 机器学习的应用 应用举例&#xff1a;猫狗分类 1. 现实问题抽象为数学问题 2. 数据准备…...

PySpark安装及WordCount实现(基于Ubuntu)

先盘点一下要安装哪些东西&#xff1a; VMwareubuntu 14.04&#xff08;64位&#xff09;Java环境&#xff08;JDK 1.8&#xff09;Hadoop 2.7.1Spark 2.4.0&#xff08;Local模式&#xff09;Pycharm &#xff08;一&#xff09;Ubuntu VMware 和 ubuntu 14.04&#xff08;…...

SpringBoot 模板模式实现优惠券逻辑

一、计算逻辑的类结构图 在这张图里&#xff0c;顶层接口 RuleTemplate 定义了 calculate 方法&#xff0c;抽象模板类 AbstractRuleTemplate 将通用的模板计算逻辑在 calculate 方法中实现&#xff0c;同时它还定义了一个抽象方法 calculateNewPrice 作为子类的扩展点。各个具…...

并查集 rank 的优化(Java 实例代码)

目录 并查集 rank 的优化 Java 实例代码 UnionFind3.java 文件代码&#xff1a; 并查集 rank 的优化 上一小节介绍了并查集基于 size 的优化&#xff0c;但是某些场景下&#xff0c;也会存在某些问题&#xff0c;如下图所示&#xff0c;操作 union(4,2)。 根据上一小节&…...

TDA4超级玩家浮出水面,行泊一体功能、成本刷到极致

2023年以来&#xff0c;智能驾驶市场进入L2普及、高阶ADAS功能&#xff08;NOA&#xff09;大规模量产的新周期&#xff0c;降本增效&#xff0c;打造极致性价比、提升用户体验等&#xff0c;成为了竞争的焦点。 其中&#xff0c;替换更具性价比的硬件平台、传感器复用、系统优…...

3分钟了解Android中稳定性测试

一、什么是Monkey Monkey在英文里的含义是猴子&#xff0c;在测试行业的学名叫“猴子测试”&#xff0c;指的是没有测试经验的人甚至是根本不懂计算机的人&#xff08;就像一只猴子&#xff09;&#xff0c;不需要知道程序的任何用户交互方面的知识&#xff0c;给他一个程序&a…...

LVS-DR+keepalived实现高可用负载群集

VRRP 通信原理&#xff1a; VRRP就是虚拟路由冗余协议&#xff0c;它的出现就是为了解决静态路由的单点故障。 VRRP是通过一种竞选的一种协议机制&#xff0c;来将路由交给某台VRRP路由。 VRRP用IP多播的方式&#xff08;多播地址224.0.0.18&#xff09;来实现高可用的通信&…...

阿里云国际版注册教程

什么是阿里云国际版&#xff1f; 阿里云国际版是阿里云专为海外客户供给的服务器及核算资源&#xff0c;涵盖了云主机、弹性裸金属服务器、容器服务、数据库及安全和监控等一系列云核算解决方案。 与其他云核算服务供给商不同&#xff0c;阿里云国际版在安全性、稳定性、性能方…...

基于百度文心大模型创作的实践与谈论

文心概念 百度文心大模型源于产业、服务于产业&#xff0c;是产业级知识增强大模型。百度通过大模型与国产深度学习框架融合发展&#xff0c;打造了自主创新的AI底座&#xff0c;大幅降低了AI开发和应用的门槛&#xff0c;满足真实场景中的应用需求&#xff0c;真正发挥大模型…...

Java基础知识题(五)

系列文章目录 Java基础知识题(一) Java基础知识题(二) Java基础知识题(三) Java基础知识题(四) Java基础知识题(五) 文章目录 系列文章目录 前言 一 Java的数据连接——JDBC 1. 简述什么是JDBC&#xff1f;重点 2. JDBC PreparedStatement比Statement有什么优势&…...

攻防世界-fileinclude

原题 解题思路 题目已经告诉了&#xff0c;flag在flag.php中&#xff0c;先查看网页源代码&#xff08;快捷键CTRLU&#xff09;。 通过抓包修改&#xff0c;可以把lan变量赋值flag。在cookie处修改。新打开的网页没有cookie&#xff0c;直接添加“Cookie: languagephp://filte…...

流媒体服务器SRS的搭建及QT下RTMP推流客户端的编写

一、前言 目前市面上有很多开源的流媒体服务器解决方案&#xff0c;常见的有SRS、EasyDarwin、ZLMediaKit和Monibuca。这几种的对比如下&#xff1a; &#xff08;本图来源&#xff1a;https://www.ngui.cc/zz/1781086.html?actiononClick&#xff09; 二、SRS的介绍 SRS&am…...

Effective C++条款11——在operator=中处理“自我赋值”(构造/析构/赋值运算)

“自我赋值”发生在对象被赋值给自己时: class Widget {}; Widget w; // ... w w; // 赋值给自己 这看起来有点愚蠢&#xff0c;但它合法&#xff0c;所以不要认定客户绝不会那么做。此外赋值动作并不总是那么可被一眼辨识出来&#xff0c;例如: a[i] a[j]; …...

可视化绘图技巧100篇基础篇(八)-气泡图(一)

目录 前言 适用场景 图例 绘图工具及代码实现 EXCEL 1、单轴气泡图...

Elasticsearch查询之Disjunction Max Query

前言 Disjunction Max Query 又称最佳 best_fields 匹配策略&#xff0c;用来优化当查询关键词出现在多个字段中&#xff0c;以单个字段的最大评分作为文档的最终评分&#xff0c;从而使得匹配结果更加合理 写入数据 如下的两条例子数据&#xff1a; docId: 1 title: java …...

React Native 导航系统实战(React Navigation)

导航系统实战&#xff08;React Navigation&#xff09; React Navigation 是 React Native 应用中最常用的导航库之一&#xff0c;它提供了多种导航模式&#xff0c;如堆栈导航&#xff08;Stack Navigator&#xff09;、标签导航&#xff08;Tab Navigator&#xff09;和抽屉…...

【入坑系列】TiDB 强制索引在不同库下不生效问题

文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...

深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法

深入浅出&#xff1a;JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中&#xff0c;随机数的生成看似简单&#xff0c;却隐藏着许多玄机。无论是生成密码、加密密钥&#xff0c;还是创建安全令牌&#xff0c;随机数的质量直接关系到系统的安全性。Jav…...

【大模型RAG】Docker 一键部署 Milvus 完整攻略

本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装&#xff1b;只需暴露 19530&#xff08;gRPC&#xff09;与 9091&#xff08;HTTP/WebUI&#xff09;两个端口&#xff0c;即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...

Psychopy音频的使用

Psychopy音频的使用 本文主要解决以下问题&#xff1a; 指定音频引擎与设备&#xff1b;播放音频文件 本文所使用的环境&#xff1a; Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...

反射获取方法和属性

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

什么是EULA和DPA

文章目录 EULA&#xff08;End User License Agreement&#xff09;DPA&#xff08;Data Protection Agreement&#xff09;一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA&#xff08;End User License Agreement&#xff09; 定义&#xff1a; EULA即…...

【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)

要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况&#xff0c;可以通过以下几种方式模拟或触发&#xff1a; 1. 增加CPU负载 运行大量计算密集型任务&#xff0c;例如&#xff1a; 使用多线程循环执行复杂计算&#xff08;如数学运算、加密解密等&#xff09;。运行图…...

【HTML-16】深入理解HTML中的块元素与行内元素

HTML元素根据其显示特性可以分为两大类&#xff1a;块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...

Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理

引言 Bitmap&#xff08;位图&#xff09;是Android应用内存占用的“头号杀手”。一张1080P&#xff08;1920x1080&#xff09;的图片以ARGB_8888格式加载时&#xff0c;内存占用高达8MB&#xff08;192010804字节&#xff09;。据统计&#xff0c;超过60%的应用OOM崩溃与Bitm…...