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

news2024/9/29 13:28:29

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进行交互了。

#python

def subscriber_callback(msg):
    # This is the subscriber callback function
    log_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 object
    t = 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 initialization
    self.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 instead

def 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)
--lua

function subscriber_callback(msg)
    -- This is the subscriber callback function
    sim.addLog(sim.verbosity_scriptinfos, 'subscriber receiver following Float32: '..msg.data)
end

function getTransformStamped(objHandle, name, relTo, relToName)
    -- This function retrieves the stamped transform for a specific object
    local 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]}
        }
    }
end

function sysCall_init()
    sim = require('sim')
    simROS2 = require('simROS2')

    -- The simulation script initialization
    objectHandle = 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')
end

function 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
end

function 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.coloradmin.cn/o/2066594.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[数据集][目标检测]光伏发电板红外图像鸟粪检测数据集VOC+YOLO格式173张1类别

数据集格式:Pascal VOC格式YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):173 标注数量(xml文件个数):173 标注数量(txt文件个数):173 标注类别…

Windows—RAW编程

客服端骨架&#xff1a; #include <iostream> #include <WinSock2.h> #pragma comment(lib,"ws2_32.lib")int main() {WORD wVersionRequested MAKEWORD(2, 2);WSADATA lpWSAData;WSAStartup(wVersionRequested, &lpWSAData);SOCKADDR_IN saddr{ …

如何在没有密码的情况下解锁iPhone?

如果您的 iPhone 被锁定&#xff0c;知道如何在没有密码的情况下解锁它会派上用场。有几种方法可以帮助您重新使用无价的小工具&#xff0c;无论您是忘记了密码&#xff0c;还是现在只想使用手机。这篇博客文章将讨论在 iPhone 上设置密码的价值、忘记密码的典型原因以及在没有…

什么是DDOS攻击?DDOS攻击一小时多少钱?DDOS攻击如何防御?

什么是DDOS攻击? 拒绝服务攻击&#xff08;DDOS&#xff09;亦称洪水攻击&#xff0c;是一种网络攻击手法&#xff0c;其目的在于使目标计算机的网络或系统资源耗尽&#xff0c;使服务暂时中断或停止&#xff0c;导致其正常用户无法访问。当黑客使用网络上两个或以上被攻陷的计…

AWK的高级用法、三剑客总结

1、定义引用变量 -v:声明变量 案例一: 将系统的变量a,在awk里赋值为变量b,然后调用变量b -v 选项将其传递给 awk直接调用的话需要先用双引号再用单引号awk直接定义变量并引用调用函数getline,读取一行数据的时候并不是得到当前行而是当前行的下一行打印整个行面下面含有ro…

mp4怎么转换成mp3?看了就会的8种mp4转mp3方法!

mp4怎么转换成mp3&#xff1f;MP4作为广泛应用的视频格式&#xff0c;在日常娱乐与工作中扮演着重要角色&#xff0c;但它在特定情境下也带来了一些不便&#xff0c;你是否曾遇到过这样的困扰&#xff0c;当视频内容中的画面并非焦点&#xff0c;而你只对其中的音频感兴趣时&am…

鸿蒙Harmony编程开发:服务端证书锁定防范中间人攻击示例

1. TLS通讯中间人攻击及防范简介 TLS安全通讯的基础是基于对操作系统或者浏览器根证书的信任&#xff0c;如果CA证书签发机构被入侵&#xff0c;或者设备内置证书被篡改&#xff0c;都会导致TLS握手环节面临中间人攻击的风险。其实&#xff0c;这种风险被善意利用的情况还是很…

EasyCVR视频汇聚技术赋能智慧煤矿:车载设备接入方案助力实时监控与远程监管

在煤矿行业&#xff0c;智慧化转型已成为提升生产效率、保障安全的重要途径。随着物联网、大数据、云计算等技术的快速发展&#xff0c;智慧煤矿建设逐步深入&#xff0c;车载设备作为煤矿生产的重要一环&#xff0c;其接入智慧管理系统显得尤为重要。本文将详细介绍智慧煤矿车…

软件开发整体介绍

软件开发流程 需求分析&#xff1a;需求规格说明书&#xff08;一般以word文档的形式&#xff09;、产品原型&#xff08;静态页面展示出来&#xff09;设计&#xff1a;UI设计、数据库设计、接口设计编码&#xff1a;项目代码、单元测试测试&#xff1a;测试用例、测试报告上…

滚雪球学Java(89):Java GUI入门与进阶:AWT核心概念深度解析,有两下子!

咦咦咦&#xff0c;各位小可爱&#xff0c;我是你们的好伙伴——bug菌&#xff0c;今天又来给大家普及Java SE啦&#xff0c;别躲起来啊&#xff0c;听我讲干货还不快点赞&#xff0c;赞多了我就有动力讲得更嗨啦&#xff01;所以呀&#xff0c;养成先点赞后阅读的好习惯&#…

html文件运行后界面反馈xxx拒绝连接

概述&#xff1a;我的html代码中包含了外站界面&#xff0c;运行后界面反馈到xxx拒绝连接&#xff0c;我尝试了网上的诸多方法&#xff0c;例如换一个浏览器运行&#xff0c;修改主机网络设置&#xff0c;更改浏览器DNS都没有作用。 <!DOCTYPE html> <html> <h…

html+css+js网页设计 电商 翡翠钻石电商网站10个页面

htmlcssjs网页设计 电商 翡翠钻石电商网站10个页面 网页作品代码简单&#xff0c;可使用任意HTML编辑软件&#xff08;如&#xff1a;Dreamweaver、HBuilder、Vscode 、Sublime 、Webstorm、Text 、Notepad 等任意html编辑软件进行运行及修改编辑等操作&#xff09;。 获取源…

华为录音删除怎么恢复?教你几招轻松找回重要录音

在日常生活中&#xff0c;我们经常会使用华为手机进行通话录音或录制一些重要的会议内容。然而&#xff0c;有时不小心删除了这些录音文件&#xff0c;可能会带来不小的麻烦。那么&#xff0c;华为录音删除后该如何恢复呢&#xff1f;本文将为你详细介绍几种实用的恢复方法&…

红黑树的插入

目录 一、红黑树 二、红黑树节点的定义 三、红黑树的插入 3.1按照二叉搜索的树规则插入新节点 3.2检测新节点插入后红黑树的情况 3.3红黑树插入代码总体实现 四、红黑树的验证 五、红黑树和AVL树的比较 一、红黑树 红黑树&#xff0c;是一种二叉搜索树&#xff0c;但在…

如何申请开通商家转账到零钱【成功经验分享】

商家转账到零钱功能是微信支付为商户提供的一项便捷服务&#xff0c;允许商户直接将资金转入用户的微信钱包。鉴于很多商户在申请商家转账到零钱时被过时的、错误的经验文章所误导&#xff0c;以我们上万次成功开通商家转账到零钱功能的经验整理这篇文章&#xff0c;希望能对新…

整套厨帽检测算法样本、模型、源码和厨帽算法识别应用方案介绍

厨帽检测算法的应用方案主要涉及技术选型、硬件配置、软件集成、部署与监控以及应对实际挑战等多个方面。以下是一个详细的应用方案概述&#xff1a; 一、技术选型 深度学习技术&#xff1a;厨帽检测算法主要基于深度学习技术&#xff0c;特别是卷积神经网络&#xff08;CNN&…

OpenCV几何图像变换(10)透视变换函数warpPerspective()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 warpPerspective 函数使用指定的矩阵对源图像进行透视变换&#xff1a; dst ( x , y ) src ( M 11 x M 12 y M 13 M 31 x M 32 y M 33 , M…

信息流产品场景及数据指标体系

一、信息流产品的场景 我们分别从用户、内容生产者和平台的角度&#xff0c;描述他们在信息流产品里的消费场景&#xff0c;便于理解阐述的指标体系。 1、用户在信息流产品里的消费的场景 小明同学&#xff0c;每天打开 5 次 App&#xff0c;刷新内容 20 次&#xff0c;浏览了…

高性能、可扩展、支持二次开发的java版本企业电子招标采购系统源码

在数字化时代&#xff0c;企业需要借助先进的数字化技术来提高工程管理效率和质量。招投标管理系统作为企业内部业务项目管理的重要应用平台&#xff0c;涵盖了门户管理、立项管理、采购项目管理、采购公告管理、考核管理、报表管理、评审管理、企业管理、采购管理和系统管理等…

苹果手机如何恢复微信好友?更新6个方法,快来收藏!

场景一&#xff1a;想查看某个好友的朋友圈&#xff0c;却不小心点击了删除好友。 场景二&#xff1a;与好友吵架了&#xff0c;一气之下删了好友&#xff0c;却不知如何重新恢复好友。 …… …… 除了上述的两种场景之外&#xff0c;我们可能还会因为其他的原因与好友失去微…