CoppeliaSim(V-Rep)与ROS1、ROS2接口变迁-2024-

Webots:Webots与ROS1、ROS2接口变迁

Gazebo:Gazebo与ROS1、ROS2接口变迁



ROS1

2016:ROS_Kinetic_18 使用V-Rep3.3.1和Matlab2015b(vrep_ros_bridge)续

 

vrep_ros_bridge 插件

一、项目背景与目标

vrep_ros_bridge 是由位于法国雷恩的 Inria Lagadic 团队为 V-Rep(现更名为 CoppeliaSim)开发的一款插件。该插件旨在创建一个模拟环境,以便在模拟机器人上测试和调试算法。团队选择 V-Rep 作为 3D 模拟器,并利用 ROS(Robot Operating System)进行通信和利用其丰富的工具集。

二、主要功能

vrep_ros_bridge 的核心功能是提供一个通信接口,使得 ROS 能够控制 V-Rep 中的模拟环境。通过 ROS 消息和服务,用户可以外部控制 V-Rep 的仿真,包括发送控制指令、接收仿真数据等。

三、V-Rep 简介

V-Rep(CoppeliaSim)是由 Coppelia Robotics 开发的一款开源且先进的 3D 物理仿真引擎。它因其灵活性(支持多种机器人平台的模拟)、强大的动力学引擎(支持 ODE、Bullet 和 Vortex)以及高度的可定制性(允许用户包含自己的代码或与外部世界接口)而在机器人社区中越来越受欢迎。

四、插件架构与工作原理
  • 插件架构vrep_ros_bridge 是一个共享库,由 V-Rep 的主客户端程序在启动时自动加载。插件会查找场景中的已知对象并进行管理。
  • 数据交互:插件创建 ROS 发布者来发送仿真数据(如场景中物体的位置和速度),并接收 ROS 订阅者的消息,动态地将控制命令应用到对象上。
  • 模块化设计vrep_ros_bridge 是一个元包,而 vrep_ros_plugin 是实际的主包。它使用 pluginlib 来加载和卸载插件,这使得插件具有高度的灵活性和可扩展性。
五、支持的对象与处理器
  • 支持的对象
    • 机器人:包括机械臂和移动机器人(通过 manipulator_handler 处理),以及四旋翼飞行器(通过 quadrotor_handler 处理)。
    • 传感器:包括视觉传感器(通过 camera_handler 处理)和 IMU 传感器(通过 imu_handler 处理)。
  • 处理器
    • 刚体处理器rigid_body_handler):提供设置和获取物体的位置和速度(Twist)的功能。
六、如何链接插件与 V-REP 中的对象

要在 V-REP 中使用 vrep_ros_bridge 插件,你需要将插件与场景中的对象进行链接。这通常涉及以下几个步骤:

  1. 确保插件已加载:在 V-REP 启动时,插件应自动加载。
  2. 配置对象:在 V-REP 场景中,为需要控制的每个对象(如机器人、传感器)配置相应的属性,以便插件能够识别和管理它们。
  3. 设置 ROS 节点:在 ROS 端,启动相应的节点以订阅或发布与 V-REP 交互所需的话题和服务。
  4. 运行仿真:在 V-REP 中运行仿真,并通过 ROS 发送控制命令或接收仿真数据。
七、总结

vrep_ros_bridge 插件为 V-Rep 和 ROS 之间的通信提供了一个强大的接口,使得在模拟环境中测试和控制机器人变得更加容易和高效。通过支持多种机器人和传感器,以及灵活的模块化设计,该插件为机器人研究和开发提供了强大的支持。

 


ROS2

2019:CoppeliaSim(V-Rep)和ROS2的使用说明

2024:CoppeliaSim_Edu_V4_7_0_rev4_Ubuntu24_04 和 ROS2 Jazzy

 

 


ROS2 Interface Plugin for CoppeliaSim 中文详细总结

支持的ROS2版本
  • Humble Hawksbill:这是ROS2的一个主要版本,确保你的ROS2环境与此版本兼容。
编译准备
  1. 目录命名

    • 确保包含所有文件(如package.xml等)的目录命名为sim_ros2_interface,否则编译将失败。
  2. 安装simStubsGen所需包

    • 需要根据simStubsGen的README文档安装必要的包。simStubsGen是一个用于生成CoppeliaSim(之前称为V-REP)模拟环境中ROS接口代码的工具。
  3. 克隆并切换版本

    • 使用Git克隆simROS2仓库到本地,并命名为sim_ros2_interface
    • 切换到与你的CoppeliaSim版本相对应的分支。例如,如果你使用的是CoppeliaSim v4.5.0,则应该切换到coppeliasim-v4.5.0-rev0分支。注意替换为实际使用的CoppeliaSim版本。
     

    bash

    $ git clone https://github.com/CoppeliaRobotics/simROS2.git sim_ros2_interface
    $ cd sim_ros2_interface
    $ git checkout coppeliasim-v4.5.0-rev0
  4. 编辑meta/interfaces.txt

    • 如果需要包含更多的ROS接口,请编辑此文件。确保使用完全限定的接口名称,如geometry_msgs/msg/Twist而不是Twist。如果接口使用了非基本类型(即其他接口),则也需要将这些接口添加到文件中。
编译过程
  • 使用colcon进行编译。colcon是ROS2推荐的构建系统。

     

    bash

    $ colcon build --symlink-install
  • 调试编译错误

    • 如果遇到编译错误,可以使用以下命令来构建,这将提供更详细的输出信息:

       

      bash

      VERBOSE=1 MAKEFLAGS=-j1 colcon build --symlink-install --event-handlers console_direct+ --parallel-workers 1
    • 如果遇到运行时错误(如崩溃、意外行为等),可以在构建时添加--cmake-args -DCMAKE_BUILD_TYPE=Debug来启用调试模式。

  • 使用Clang编译器

    • 如果GCC编译器在编译大量接口时失败,可以尝试使用Clang编译器。首先安装Clang,然后设置环境变量CXXclang++,再进行编译。

       

      bash

      sudo apt install clang
      export CXX=clang++
      colcon build ...
注意事项
  • 确保ROS2环境已正确设置,并且colcon和所有必要的依赖都已安装。
  • 如果你的CoppeliaSim版本与simROS2仓库中的分支不完全匹配,可能需要手动调整代码或查找是否有更新的分支/仓库。
  • 编译过程中可能会遇到与特定ROS2版本或CoppeliaSim版本相关的兼容性问题。在这种情况下,请检查官方文档或社区论坛以获取帮助。

通过以上步骤,你应该能够成功编译并设置ROS2 Interface Plugin for CoppeliaSim,以便在模拟环境中使用ROS2接口。


ROS2 与 CoppeliaSim 集成教程

本教程旨在以简单易懂的方式解释如何使CoppeliaSim(之前称为V-REP)支持ROS 2。首先,请确保您已经完成了ROS 2的官方教程,至少包括入门部分。我们假设您已经安装了最新版本的Ubuntu,ROS 2也已安装,并且工作空间文件夹已设置。请参考ROS 2安装的官方文档。

ROS2 Interface 插件

CoppeliaSim中的ROS 2功能主要通过ROS2 Interface(libsimROS2.so)支持。这个Linux发行版可能已经包含了在CoppeliaSim/compiledROSPlugins目录下编译好的文件,但首先需要将其复制到CoppeliaSim/目录下,否则不会被加载。不过,根据您的系统特性,您可能会遇到插件加载问题:请确保始终检查CoppeliaSim的终端窗口以获取有关插件加载操作的详细信息。加载ROS2插件的Lua代码如下:

 

lua复制代码

simROS2 = require('simROS2')

在运行CoppeliaSim之前,请确保已经导入了ROS 2环境。

插件编译

如果插件无法加载,您可能需要自己重新编译它。因为它是开源的,所以可以根据需要进行修改以支持特定功能或扩展其功能。如果需要支持特定的消息/服务等,请在重新编译之前编辑simROS2/meta/下的文件。

存在两个包:

  1. simROS2:这个包是ROS 2接口,将被编译成".so"文件并由CoppeliaSim使用。
  2. ros2_bubble_rob:这是一个非常简单的机器人控制器包,它通过ROS 2接口与CoppeliaSim连接。此节点将负责控制demo场景controlTypeExamples/controlledViaRos.ttt中的红色机器人。

这两个包应该被复制到您的ros2_ws/src文件夹中。

构建包

为了构建这些包,请导航到ros2_ws文件夹并输入以下命令:

 

bash复制代码

$ export COPPELIASIM_ROOT_DIR=~/path/to/coppeliaSim/folder
$ ulimit -s unlimited # 否则编译可能会冻结/崩溃
$ colcon build --symlink-install --cmake-args -DCMAKE_BUILD_TYPE=Release

完成以上步骤后,包应该已经被生成并编译成库文件,该库文件将自动复制到CoppeliaSim的安装文件夹中。现在,插件已准备好使用。

加载和使用ROS2 Interface

打开一个新的终端,移动到CoppeliaSim的安装文件夹,启动CoppeliaSim,并使用上述Lua代码加载ROS2插件。成功加载ROS 2接口后,可以通过以下命令检查可用的节点:

 

bash复制代码

$ ros2 node list
/sim_ros2_interface

在CoppeliaSim的一个空场景中,选择一个对象,然后为其附加一个非线程仿真脚本(通过[添加 > 脚本 > 仿真脚本 > 非线程 > Lua/Python])。打开该脚本的编辑器,并用以下代码替换其内容(根据您的需求编写具体的Lua代码来控制仿真):

 

lua复制代码

-- 在这里编写控制CoppeliaSim中对象的Lua代码

这样,您就可以开始通过ROS 2与CoppeliaSim进行交互了。

#pythondef subscriber_callback(msg):# This is the subscriber callback functionlog_message = f'subscriber receiver following Float32: {msg["data"]}'sim.addLog(sim.verbosity_scriptinfos, log_message)def getTransformStamped(objHandle, name, relTo, relToName):# This function retrieves the stamped transform for a specific objectt = simROS2.getSystemTime()p = sim.getObjectPosition(objHandle, relTo)o = sim.getObjectQuaternion(objHandle, relTo)return {'header': {'stamp': t,'frame_id': relToName},'child_frame_id': name,'transform': {'translation': {'x': p[0], 'y': p[1], 'z': p[2]},'rotation': {'x': o[0], 'y': o[1], 'z': o[2], 'w': o[3]}}}def sysCall_init():sim = require('sim')simROS2 = require('simROS2')# The simulation script initializationself.objectHandle = sim.getObject('..')self.objectAlias = sim.getObjectAlias(self.objectHandle, 3)# Prepare the float32 publisher and subscriber (we subscribe to the topic we publish):self.publisher = simROS2.createPublisher('/simulationTime', 'std_msgs/msg/Float32')self.subscriber = simROS2.createSubscription('/simulationTime', 'std_msgs/msg/Float32', subscriber_callback)def sysCall_actuation():# Send an updated simulation time message, and send the transform of the object attached to this script:simROS2.publish(self.publisher, {'data': sim.getSimulationTime()})simROS2.sendTransform(getTransformStamped(self.objectHandle, self.objectAlias, -1, 'world'))# To send several transforms at once, use simROS2.sendTransforms insteaddef sysCall_cleanup():# Following not really needed in a simulation script (i.e. automatically shut down at simulation end):simROS2.shutdownPublisher(self.publisher)simROS2.shutdownSubscription(self.subscriber)
--luafunction subscriber_callback(msg)-- This is the subscriber callback functionsim.addLog(sim.verbosity_scriptinfos, 'subscriber receiver following Float32: '..msg.data)
endfunction getTransformStamped(objHandle, name, relTo, relToName)-- This function retrieves the stamped transform for a specific objectlocal t = simROS2.getSystemTime()local p = sim.getObjectPosition(objHandle,relTo)local o = sim.getObjectQuaternion(objHandle,relTo)return {header = {stamp = t,frame_id = relToName},child_frame_id = name,transform = {translation = {x = p[1], y = p[2], z = p[3]},rotation = {x = o[1], y = o[2], z = o[3], w = o[4]}}}
endfunction sysCall_init()sim = require('sim')simROS2 = require('simROS2')-- The simulation script initializationobjectHandle = sim.getObject('..')objectAlias = sim.getObjectAlias(objectHandle, 3)-- Prepare the float32 publisher and subscriber (we subscribe to the topic we publish):publisher = simROS2.createPublisher('/simulationTime', 'std_msgs/msg/Float32')subscriber = simROS2.createSubscription('/simulationTime', 'std_msgs/msg/Float32', 'subscriber_callback')
endfunction sysCall_actuation()-- Send an updated simulation time message, and send the transform of the object this script is attached to:simROS2.publish(publisher, {data = sim.getSimulationTime()})simROS2.sendTransform(getTransformStamped(objectHandle, objectAlias, -1, 'world'))-- To send several transforms at once, use simROS2.sendTransforms instead
endfunction sysCall_cleanup()-- Following not really needed in a simulation script (i.e. automatically shut down at simulation end):simROS.shutdownPublisher(publisher)simROS.shutdownSubscriber(subscriber)
end

上述脚本将同时发布仿真时间并订阅它,此外还会发布附加该脚本的对象的变换信息。你可以通过以下命令查看仿真时间的话题列表:

 

bash复制代码

$ ros2 topic list

为了查看消息内容,你可以输入:

 

bash复制代码

$ ros2 topic echo /simulationTime

接下来,加载演示场景 messaging/ros2InterfaceTopicPublisherAndSubscriber.ttt 并运行仿真。在这个场景中,附加到Vision_sensor的视觉传感器仿真脚本包含的代码将启用一个发布者来流式传输视觉传感器的图像数据,并启用一个订阅者来监听同一个数据流。这里的订阅者将读取到的数据应用到被动视觉传感器上,该被动视觉传感器仅用作数据容器。

以下是具体发生的情况的详细总结:

  1. 发布与订阅仿真时间
    • 脚本的一部分功能是在ROS 2网络中发布当前的仿真时间,并同时订阅该时间话题。这可以用于同步或记录仿真过程中的时间信息。
  2. 发布对象变换
    • 脚本还会发布附加该脚本的对象的变换信息(如位置、姿态等)。这对于需要知道对象在仿真环境中位置的应用来说非常有用。
  3. 视觉传感器数据的发布与订阅
    • messaging/ros2InterfaceTopicPublisherAndSubscriber.ttt场景中,视觉传感器通过ROS 2接口发布其捕获的图像数据。这允许其他ROS 2节点接收并处理这些数据。
    • 同时,该场景中还设置了一个订阅者,它订阅了由视觉传感器发布的相同数据流。订阅者接收到数据后,将其应用到被动视觉传感器上。这里,被动视觉传感器实际上并不进行任何实际的视觉处理,而是作为数据容器存在,用于演示数据如何在ROS 2网络中流动。
  4. 数据流的双向性
    • 这个例子展示了CoppeliaSim如何同时作为数据的生产者和消费者。它不仅能够发布数据供其他系统使用,还能够订阅并处理来自其他节点的数据。这种双向数据流的能力使得CoppeliaSim能够与其他ROS 2节点无缝集成,实现复杂的仿真和控制系统。
  5. 演示目的
    • 通过这个演示,用户可以直观地看到ROS 2接口如何在CoppeliaSim中工作,以及如何利用ROS 2的强大功能来扩展仿真应用的能力。这包括数据的实时传输、处理以及仿真与真实世界之间的交互等。

 

在这个实验中,你可以尝试对代码进行一些修改和实验。CoppeliaSim 能够通过 ROS 2 接口流式传输图像数据,你可以使用以下命令来可视化这些图像:

 

bash复制代码

$ ros2 run image_tools showimage --ros-args --remap image:=/image

这个命令会启动 image_tools 包中的 showimage 工具,并通过 --remap 参数将 /image 话题映射为工具所需的输入。这样,你就可以在运行时窗口中看到从 CoppeliaSim 传输过来的图像了。

如果你传输的是更简单的数据类型(比如数字、字符串等),你也可以使用 ros2 topic echo 命令来查看这些数据:

 

bash复制代码

$ ros2 topic echo /image

但请注意,对于图像数据,ros2 topic echo 并不适用,因为它无法直接以人类可读的形式显示图像内容。

现在,停止当前的仿真,并加载 controlTypeExamples/controlledViaRos2.ttt 演示场景,然后运行仿真。在这个场景中,有一个简化的机器人模型,其行为也被设计为尽可能简单,以便于理解。这个机器人通过 ROS 2 接口进行控制。

通过这个演示,你可以学习到如何使用 ROS 2 来控制 CoppeliaSim 中的机器人。你可以通过发送特定的 ROS 2 消息来控制机器人的运动,比如移动关节、设置末端执行器的位置或姿态等。这个过程涉及到 ROS 2 节点之间的通信,以及如何将 ROS 2 消息映射到 CoppeliaSim 的仿真环境中。

在CoppeliaSim中,附加到机器人的仿真脚本以非线程方式运行,主要负责以下任务:

  1. 确定对象句柄:例如电机关节句柄和接近传感器句柄。
  2. 启动电机速度订阅者:监听并响应来自ROS 2的电机速度控制命令。
  3. 启动传感器发布者和仿真时间发布者:将传感器的数据和当前的仿真时间发布到ROS 2话题上。
  4. 启动客户端应用程序:调用名为ros2BubbleRob的客户端应用程序,并传递一些话题名称作为参数,以便它知道需要监听和订阅哪些话题。之后,ros2BubbleRob客户端应用程序将通过ROS 2接管对机器人的控制。

在仿真运行时,你可以复制并粘贴机器人模型多次。注意,每次复制的机器人都是直接可操作且独立的。这是CoppeliaSim众多强大功能之一,允许用户轻松创建复杂的仿真场景。

现在,停止当前仿真并打开一个新场景,然后将Models/tools/ros2Interface helper tool.ttm模型拖入其中。这个模型包含一个自定义脚本,提供了以下话题的发布者和订阅者:

  • startSimulation:通过向此话题发布std_msgs/msg/Bool消息来启动仿真。
  • pauseSimulation:通过向此话题发布std_msgs/msg/Bool消息来暂停仿真。
  • stopSimulation:通过向此话题发布std_msgs/msg/Bool消息来停止仿真。
  • enableSyncMode:通过向此话题发布std_msgs/msg/Bool消息来启用或禁用步进模式。
  • triggerNextStep:在步进模式下,通过向此话题发布std_msgs/msg/Bool消息来触发下一个仿真步骤。
  • simulationStepDone:在每个仿真周期结束时,发布类型为std_msgs/msg/Bool的消息。
  • simulationState:定期发布类型为std_msgs/msg/Int32的消息,其中0表示仿真已停止,1表示正在运行,2表示已暂停。
  • simulationTime:定期发布类型为std_msgs/msg/Float32的消息,指示当前的仿真时间。

你可以查看并完全自定义这个自定义脚本,以满足不同的需求。此外,尝试从命令行生成话题消息,例如使用ROS 2命令行工具来发布消息到这些话题,以测试和控制仿真过程。这提供了一种灵活的方式来与CoppeliaSim中的ROS 2接口进行交互。

$ ros2 topic pub /startSimulation std_msgs/msg/Bool '{data: true}' --once
$ ros2 topic pub /pauseSimulation std_msgs/msg/Bool '{data: true}' --once
$ ros2 topic pub /stopSimulation std_msgs/msg/Bool '{data: true}' --once
$ ros2 topic pub /enableSyncMode std_msgs/msg/Bool '{data: true}' --once
$ ros2 topic pub /startSimulation std_msgs/msg/Bool '{data: true}' --once
$ ros2 topic pub /triggerNextStep std_msgs/msg/Bool '{data: true}' --once
$ ros2 topic pub /triggerNextStep std_msgs/msg/Bool '{data: true}' --once
$ ros2 topic pub /triggerNextStep std_msgs/msg/Bool '{data: true}' --once
$ ros2 topic pub /stopSimulation std_msgs/msg/Bool '{data: true}' --once

 


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

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

相关文章

Linux系统之jobs命令的基本使用

Linux系统之jobs命令的基本使用 一、jobs命令介绍二、jobs命令的使用帮助2.1 jobs命令的help帮助信息2.2 jobs命令的语法解释 三、jobs命令的基本使用3.1 运行一个后台任务3.2 列出后台所有的作业3.3 列出进程ID3.4 只列出进程ID3.5 终止后台任务3.6 只显示运行任务3.7 只显示停…

设备状态图表-甘特图

1.背景&#xff1a;设备状态监控图表&#xff0c;监控不同状态的时间段&#xff0c;可以使用甘特图来展示效果 鼠标经过时的数据提示框 2、代码实现 <template><divref"ganttChartRefs":style"{ height: 6.2rem, width: 100% }"class"bg…

视频项目开发,EasyCVR视频融合平台为何成为关键驱动力

智慧类视频项目是基于多个系统融合&#xff0c;旨在实现更广泛联动功能&#xff0c;以满足智能化应用需求为基石的信息化项目。当前&#xff0c;智慧社区、智慧园区、智慧工厂乃至智慧城市等应用场景的需求日益增长。这些智慧项目的整合进程中&#xff0c;视频融合能力扮演着不…

burpsuite xssValidator插件(xss插件)

安装 1. 商城安装插件 2. 安装环境 Download PhantomJShttps://phantomjs.org/download.htmlGitHub - NetSPI/xssValidator: This is a burp intruder extender that is designed for automation and validation of XSS

房价下跌的大环境下,我的佣金为何能逆市增长?

声明&#xff1a;此篇为 ai123.cn 原创文章&#xff0c;转载请标明出处链接&#xff1a;https://ai123.cn/2199.html &#x1f3e0;&#x1f4b0;最近房地产市场可不太景气&#xff0c;房价跌跌不休&#xff0c;咱们中介们的佣金收入也受到了影响。你知道那种心情吗&#xff1f…

【IoTDB 线上小课 06】列式写入=时序数据写入性能“利器”?

【IoTDB 视频小课】更新来啦&#xff01;今天已经是第六期了~ 关于 IoTDB&#xff0c;关于物联网&#xff0c;关于时序数据库&#xff0c;关于开源... 一个问题重点&#xff0c;3-5 分钟&#xff0c;我们讲给你听&#xff1a; 列式写入到底是&#xff1f; 上一期我们详细了解了…

汽车冷却液温度传感器的作用与检测方法

汽车冷却系统中的关键部件之一是冷却液温度传感器&#xff0c;它的位置通常在发动机的缸体或水泵附近&#xff0c;与冷却液直接接触。该传感器的作用是监测发动机冷却液的温度&#xff0c;它采用负温度系数热敏电阻&#xff0c;这种电阻随温度升高而降低。当冷却液温度达到预定…

AcWing 850. Dijkstra求最短路 II

迪杰斯特拉的优化算法采用堆优化&#xff0c;优化之前是花费 O ( n ) O(n) O(n)时间来查找未最优点里面距离点1最小的点。现在使用堆优化&#xff0c;直接花费 O ( 1 ) O(1) O(1)时间就完事儿了。 堆里面存储 p a i r < i n t , i n t > pair<int,int> pair<int…

Java毕业论文 【二手书电子商城网站】源码见github (原创项目,从0-1自己实现)

文章目录 项目背景主要功能模块分布模块分布具体部分功能 系统架构功能演示买家部分界面&#xff1a;卖家部分界面【8002模块】&#xff1a;管理员部分界面&#xff1a; 项目github地址 项目背景 主要面向高校学生&#xff0c;将高年级同学的书回收到低年级学生的手上&#xf…

CANoe.DiVa的应用——Diva进行诊断自动化测试执行过程详解(三)

🙋‍♂️【Vector CANdelastudio配置CDD】文章合集💁‍♂️点击跳转 ——————————————————————————————————–—— 从0开始学习CANoe使用 从0开始学习车载测试 相信时间的力量 星光不负赶路者,时光不负有心人。 目录 1.工程导入2.查看用…

什么是BOM,有哪些分类?

一、什么是BOM&#xff1f; BOM是物料清单的缩写&#xff0c;也称为产品结构表或产品结构树。 BOM的作用主要是通过计算机辅助企业生产管理&#xff0c;使计算机能够识别企业所制造的产品构成和所有要涉及的物料。 在制造业中&#xff0c;BOM是一份详细记录制造某个产品时所…

【算法基础实验】图论-最小生成树Kruskal实现

预备知识 【算法基础实验】图论-UnionFind连通性检测之quick-union_union find 判断是否成环-CSDN博客 【算法基础实验】排序-最小优先队列MinPQ_最小优先队列实现-CSDN博客 理论知识 Kruskal算法是一种用于查找加权无向图的最小生成树的贪心算法。最小生成树是一个连通的子…

uniapp使用live-pusher进行人脸识别打卡(安卓跟ios)

效果图 代码 使用live-pusher <live-pusher idlivePusher class"livePusher" mode"FHD" beauty"0" whiteness"0" aspect"9:16"min-bitrate"1000" audio-quality"16KHz" device-position"fron…

Apple pencil有替代品吗?2024开学季推荐五款实惠又好用的电容笔

如果只是用于学习和办工的话&#xff0c;Apple pencil是有替代品的&#xff0c;虽然Apple Pencil的性能不错&#xff0c;但它的高昂价格让很多用户不得不开始寻求性价比更高的平替电容笔。那么&#xff0c;在众多选择中&#xff0c;如何挑选一款合适的电容笔呢&#xff1f;以下…

【iOS】Block底层分析

目录 前言Block底层结构Block捕获变量原理捕获局部变量&#xff08;auto、static&#xff09;全局变量捕获实例self Block类型Block的copyBlock作为返回值将Block赋值给__strong指针Block作为Cocoa API中方法名含有usingBlock的方法参数Block作为GCD API的方法参数Block属性的写…

光性能 -- 边模抑制比眼图

最小边模抑制比 在最坏的发射条件下&#xff0c;主模的平均光功率与最显著边模的光功率之比即最小边模抑制比。 什么是边模 理想情况下&#xff0c;光模块发射的信号应当只是有特定波长的光信号。但实际情况下不仅有一个特定波长的主信号&#xff0c;还有一些其他波长的存在&…

Java学习笔记(02)接口的使用

1、接口关键字&#xff1a;interface 2、接口内部结构的说明&#xff1a; 可以声明抽象方法&#xff0c;属性由public static final修饰&#xff0c;但都会默认。 不可以声明&#xff1a;构造器&#xff0c;代码块等。 3、格式&#xff1a;class A extends SuperA implements…

开放式耳机别人能听到吗?现在开放式耳机用防漏音效果越来越好!

回答&#xff1a; 开放式耳机的通透的设计允许一部分声音泄露出来&#xff0c;因此站在您旁边的人确实有可能听到您耳机中的声音&#xff0c;尤其是当音量设置得比较高时。开放式耳机通常提供更为自然和宽敞的听感&#xff0c;但牺牲了一定的隔音效果和隐私性。如果您需要在公…

探索提示工程 Prompt Engineering的奥妙

一、探索提示工程 1. 介绍通用人工智能和专用人工智能 人工智能&#xff08;AI&#xff09;可以分为通用人工智能&#xff08;AGI&#xff09;和专用人工智能&#xff08;Narrow AI&#xff09;。AGI是一种能够理解、学习和执行任何人类可以完成的任务的智能。与此相对&#x…

《深入浅出多模态》(八)多模态经典模型:MiniGPT4

&#x1f389;AI学习星球推荐&#xff1a; GoAI的学习社区 知识星球是一个致力于提供《机器学习 | 深度学习 | CV | NLP | 大模型 | 多模态 | AIGC 》各个最新AI方向综述、论文等成体系的学习资料&#xff0c;配有全面而有深度的专栏内容&#xff0c;包括不限于 前沿论文解读、…