【ROS2】高级:使用 Fast DDS 发现服务器作为发现协议 [社区贡献]

news2024/12/28 21:17:51

目标:本教程将展示如何使用 Fast DDS Discovery Server 发现协议启动 ROS 2 节点。

 教程级别:高级

 时间:20 分钟

 目录

  •  背景

  •  快速 DDS 发现服务器 v2

  •  先决条件

  •  运行此教程

    •  设置发现服务器

    •  启动监听节点

    •  启动对话节点

    • 展示发现服务器执行

    •  可视化工具 rqt_graph

  •  高级用例

    •  服务器冗余

    •  备份服务器

    •  发现分区

  •  ROS 2 内省

    •  守护进程的相关工具

    •  没有虚拟光驱工具

  • 比较 Fast DDS 发现服务器与简单发现协议

 背景

从 ROS 2 Eloquent Elusor 开始,Fast DDS Discovery Server 协议是一项提供集中动态发现机制的功能而不是 DDS 默认使用的分布式机制。本教程解释了如何使用 Fast DDS Discovery Server 功能作为发现通信来运行一些 ROS 2 示例。

为了获取有关可用发现配置的更多信息,请查看以下文档 https://fast-dds.docs.eprosima.com/en/v2.1.0/fastdds/discovery/discovery.html 或阅读 Fast DDS 发现服务器特定文档。https://fast-dds.docs.eprosima.com/en/v2.1.0/fastdds/discovery/discovery_server.html#discovery-server

简单发现协议 https://fast-dds.docs.eprosima.com/en/v2.1.0/fastdds/discovery/simple.html 是 DDS 标准 https://www.omg.org/omg-dds-portal/ 中定义的标准协议。然而,它在某些场景中存在已知的缺点。

  • 它不能有效扩展,因为随着新节点的添加,交换的数据包数量显著增加。

  • 它需要多播功能,但在某些情况下可能无法可靠地工作,例如 WiFi

Fast DDS 发现服务器提供了一种客户端-服务器架构,允许节点使用中间服务器相互连接。每个节点都充当发现客户端,与一个或多个发现服务器共享其信息,并从中接收发现信息。这减少了与发现相关的网络流量,并且不需要多播功能。

1573d92953cd912f4a47ba63069d22d1.png

这些发现服务器可以是独立的、重复的或相互连接的,以便在网络上创建冗余并避免单点故障。

快速 DDS 发现服务器 v2

最新的 ROS 2 Foxy Fitzroy 版本(2020 年 12 月)包含了一个新版本,即 Fast DDS 发现服务器的第 2 版。该版本包括一个新的过滤功能,可以进一步减少发送的发现消息数量。该版本使用不同节点的主题来决定两个节点是否希望通信,或者它们是否可以不匹配(即不相互发现)。下图显示了发现消息的减少情况:

2350a2289f9e367dff9021621241e42e.png

这种架构大大减少了服务器和客户端之间发送的消息数量。在下图中,显示了在 RMF 诊所演示 https://github.com/open-rmf/rmf_demos#Clinic-World 的发现阶段网络流量的减少情况:

46339b0b10585cdc371c189b7524f3a9.png

要使用此功能,可以使用参与者的 XML 配置 https://fast-dds.docs.eprosima.com/en/v2.1.0/fastdds/discovery/discovery_server.html#discovery-server 来配置发现服务器。也可以使用 fastdds 工具 https://fast-dds.docs.eprosima.com/en/v2.1.0/fastddscli/cli/cli.html#discovery 和环境变量 https://fast-dds.docs.eprosima.com/en/v2.1.0/fastdds/env_vars/env_vars.html 来配置发现服务器,这是本教程中使用的方法。有关发现服务器配置的更详细说明,请访问 Fast DDS 发现服务器文档。

 先决条件

本教程假设您安装 https://docs.ros.org/en/jazzy/Installation.html 了 ROS 2 Foxy(或更新版本)。如果您的安装使用的是低于 Foxy 的 ROS 2 版本,则无法使用 fastdds 工具。因此,为了使用发现服务器,您可以更新您的存储库以使用不同的 Fast DDS 版本,或者使用 Fast DDS XML QoS 配置 https://fast-dds.docs.eprosima.com/en/v2.1.0/fastdds/discovery/discovery_server.html#discovery-server 来配置发现服务器。

运行本教程

talker-listener ROS 2 演示创建一个 talker 节点,该节点每秒发布一次“hello world”消息,并创建一个 listener 节点,该节点监听这些消息。

通过获取 ROS 2 https://docs.ros.org/en/jazzy/Tutorials/Beginner-CLI-Tools/Configuring-ROS2-Environment.html ,您将可以访问 CLI 工具 fastdds 。该工具可以访问发现工具 https://fast-dds.docs.eprosima.com/en/v2.14.3/fastddscli/cli/cli.html ,可用于启动发现服务器。此服务器将管理连接到它的节点的发现过程

 重要

请勿忘记在每个新打开的终端中源 ROS 2。

设置发现服务器

首先启动一个 ID 为 0 的发现服务器,端口为 11811(默认端口),并监听所有可用接口。

打开一个新的终端并运行:

cxy@ubuntu2404-cxy:~$ fastdds discovery --server-id 0
### Server is running ###
  Participant Type:   SERVER
  Security:           NO
  Server ID:          0
  Server GUID prefix: 44.53.00.5f.45.50.52.4f.53.49.4d.41
  Server Addresses:   UDPv4:[0.0.0.0]:11811

启动监听器节点

执行监听器演示,以监听 /chatter 主题。

在一个新的终端中,将环境变量 ROS_DISCOVERY_SERVER 设置为发现服务器的位置。(不要忘记在每个新终端中 source ROS 2)

export ROS_DISCOVERY_SERVER=127.0.0.1:11811

启动监听节点。使用参数 --remap __node:=listener_discovery_server 更改此教程的节点名称。

ros2 run demo_nodes_cpp listener --ros-args --remap __node:=listener_discovery_server

这将创建一个 ROS 2 节点,该节点将自动为发现服务器创建一个客户端,并连接到先前创建的服务器以执行发现,而不是使用多播。

启动 talker 节点

打开一个新的终端,并像之前一样设置 ROS_DISCOVERY_SERVER 环境变量,以便节点启动发现客户端。

export ROS_DISCOVERY_SERVER=127.0.0.1:11811
ros2 run demo_nodes_cpp talker --ros-args --remap __node:=talker_discovery_server

您现在应该看到讲话者发布“hello world”消息,并且听众正在接收这些消息。

演示发现服务器执行

到目前为止,没有证据表明这个例子和标准的说话者-听者例子运行得不同。为了清楚地证明这一点,请运行另一个未连接到发现服务器的节点。在一个新的终端中运行一个新的监听器(默认情况下监听 /chatter 主题),并检查它是否未连接到已经运行的说话者。

ros2 run demo_nodes_cpp listener --ros-args --remap __node:=simple_listener

新的监听节点不应该接收“hello world”消息。

要最终验证一切是否正常运行,可以使用简单发现协议(默认的 DDS 分布式发现机制)创建一个新的 talker 进行发现。

ros2 run demo_nodes_cpp talker --ros-args --remap __node:=simple_talker

现在你应该看到 simple_listener 节点接收到来自 simple_talker 的“hello world”消息,但没有接收到来自 talker_discovery_server 的其他消息

可视化工具 rqt_graph 

rqt_graph 工具可用于验证此示例的节点和结构。请记住,为了使用 rqt_graph 与发现服务器协议(即查看 listener_discovery_server 和 talker_discovery_server 节点),必须在启动前设置 ROS_DISCOVERY_SERVER 环境变量。

53cdce59ab79c9811b1a60c8cb4373d4.png

cxy@ubuntu2404-cxy:~$ export ROS_DISCOVERY_SERVER=127.0.0.1:11811
cxy@ubuntu2404-cxy:~$ rqt_graph  # 未隐藏

d8cccf09b30a32b8a5cd5a9dab1c21e6.png

cxy@ubuntu2404-cxy:~$ rqt_graph  # 隐藏debug

高级用例

以下部分显示了发现服务器的不同功能,这些功能使您能够通过网络构建一个强大的发现服务器。

 服务器冗余

通过使用 fastdds 工具,可以创建多个发现服务器发现客户端(ROS 节点)可以根据需要连接到任意数量的服务器。这允许拥有一个冗余网络,即使某些服务器或节点意外关闭也能正常工作。下图显示了提供服务器冗余的简单架构。

0e6d21252b33b746d84e87299f4ee277.png

在多个终端中,运行以下代码以建立与冗余服务器的通信。

fastdds discovery --server-id 0 --ip-address 127.0.0.1 --port 11811
fastdds discovery --server-id 1 --ip-address 127.0.0.1 --port 11888

--server-id N 表示 ID 为 N 的服务器。在引用带有 ROS_DISCOVERY_SERVER 的服务器时,服务器 0 必须放在第一位,服务器 1 必须放在第二位。

export ROS_DISCOVERY_SERVER="127.0.0.1:11811;127.0.0.1:11888"
ros2 run demo_nodes_cpp talker --ros-args --remap __node:=talker
export ROS_DISCOVERY_SERVER="127.0.0.1:11811;127.0.0.1:11888"
ros2 run demo_nodes_cpp listener --ros-args --remap __node:=listener

现在,如果其中一台服务器发生故障,仍然会有发现功能可用,节点仍然会相互发现。

备份服务器

Fast DDS 发现服务器允许创建具有备份功能的服务器。这允许服务器在关闭的情况下恢复其保存的最后状态。

66e55978e875ccc659205fc2bce210d9.png

在不同的终端上运行以下代码,以与备份服务器建立通信。

fastdds discovery --server-id 0 --ip-address 127.0.0.1 --port 11811 --backup
export ROS_DISCOVERY_SERVER="127.0.0.1:11811"
ros2 run demo_nodes_cpp talker --ros-args --remap __node:=talker
export ROS_DISCOVERY_SERVER="127.0.0.1:11811"
ros2 run demo_nodes_cpp listener --ros-args --remap __node:=listener

在发现服务器的工作目录(启动时的目录)中创建了几个备份文件。两个 SQLite 文件和两个 json 文件包含启动新服务器和恢复失败服务器状态所需的信息,以防止再次发生发现过程,并且不会丢失信息。

发现分区

与发现服务器的通信可以分割,以在发现信息中创建虚拟分区。这意味着只有在两个端点之间存在共享的发现服务器或发现服务器网络时,它们才会彼此了解。我们将执行一个具有两个独立服务器的示例。下图显示了架构。

d003f7d36066283cd15aaf49b6d272bc.png

通过此架构, Listener 1 将连接到 Talker 1 和 Talker 2 ,因为它们共享 Server 1 。 Listener 2 将与 Talker 1 连接,因为它们共享 Server 2 。但是 Listener 2 将不会听到来自 Talker 2 的消息,因为它们不共享任何发现服务器或发现服务器,包括通过冗余发现服务器之间的连接间接共享。

在本地主机上运行第一个监听默认端口 11811 的服务器。

fastdds discovery --server-id 0 --ip-address 127.0.0.1 --port 11811

在另一个终端上运行第二个服务器,监听本地主机上的另一个端口,在本例中为端口 11888。

fastdds discovery --server-id 1 --ip-address 127.0.0.1 --port 11888

现在,在不同的终端中运行每个节点。使用 ROS_DISCOVERY_SERVER 环境变量来决定它们连接到哪个服务器。请注意,ID 必须匹配。

export ROS_DISCOVERY_SERVER="127.0.0.1:11811;127.0.0.1:11888"
ros2 run demo_nodes_cpp talker --ros-args --remap __node:=talker_1
export ROS_DISCOVERY_SERVER="127.0.0.1:11811;127.0.0.1:11888"
ros2 run demo_nodes_cpp listener --ros-args --remap __node:=listener_1
export ROS_DISCOVERY_SERVER="127.0.0.1:11811"
ros2 run demo_nodes_cpp talker --ros-args --remap __node:=talker_2
export ROS_DISCOVERY_SERVER=";127.0.0.1:11888"
ros2 run demo_nodes_cpp listener --ros-args --remap __node:=listener_2

我们应该看看 Listener 1 如何从两个对话节点接收消息,而 Listener 2 与 Talker 2 在不同的分区中,因此不会接收来自它的消息。

 便条

一旦两个端点(ROS 节点)彼此发现,它们之间就不需要发现服务器网络来监听彼此的消息。

ROS 2 内省

ROS 2 命令行界面支持多种自省工具来分析 ROS 2 网络的行为。这些工具(即 ros2 bag record 、 ros2 topic list 等)对于理解 ROS 2 工作网络非常有帮助。

这些工具大多使用 DDS 简单发现来与每个现有参与者交换主题信息(使用简单发现,网络中的每个参与者都相互连接)。然而,新的 Discovery Server v2 实现了一种网络流量减少方案,限制了不共享主题的参与者之间的发现数据。这意味着节点只有在拥有该主题的写入者或读取者时才会接收该主题的发现数据。由于大多数 ROS 2 CLI 需要网络中的节点(其中一些依赖于正在运行的 ROS 2 守护进程,一些创建自己的节点),使用 Discovery Server v2 这些节点将不会拥有所有的网络信息,因此它们的功能将受到限制

Discovery Server v2 功能允许每个参与者作为超级客户端运行,这是一种连接到服务器的客户端,从服务器接收所有可用的发现信息(而不仅仅是它需要的信息)。从这个意义上说,ROS 2 内省工具可以配置为超级客户端,从而能够发现网络中使用 Discovery Server 协议的每个实体。

 便条

在本节中,我们使用术语参与者 Participant 作为 DDS 实体。每个 DDS 参与者对应一个 ROS 2 上下文,这是 DDS 上的 ROS 2 抽象。节点是依赖 DDS 通信接口的 ROS 2 实体: DataWriter 和 DataReader 。每个参与者可以容纳多个 ROS 2 节点。有关这些概念的更多详细信息,请访问节点到参与者映射设计文档https://design.ros2.org/articles/Node_to_Participant_mapping.html 。

守护进程的相关工具 Daemon’s related tools

ROS 2 守护进程用于多个 ROS 2 CLI 自省工具。它创建自己的参与者以将 ROS 2 节点添加到网络图中,以接收发送的所有数据。为了使 ROS 2 CLI 在使用发现服务器机制时工作,需要将 ROS 2 守护进程配置为超级客户端。因此,本节专门解释如何使用 ROS 2 CLI 和作为超级客户端运行的 ROS 2 守护进程。这将允许守护进程发现整个节点图,并接收所有主题和端点信息。为此,使用 Fast DDS XML 配置文件来配置 ROS 2 守护进程和 CLI 工具。

下面你可以找到一个 XML 配置文件,在本教程中应将其保存为工作目录中的 `super_client_configuration_file.xml` 文件。此文件将配置每个使用它的新参与者,作为超级客户端。

<?xml version="1.0" encoding="UTF-8" ?>  <!-- XML声明,版本1.0,编码格式UTF-8 -->
 <dds>  <!-- 开始定义dds -->
     <profiles xmlns="http://www.eprosima.com/XMLSchemas/fastRTPS_Profiles">  <!-- 定义profiles,xmlns属性定义了元素和属性的命名空间 -->
         <participant profile_name="super_client_profile" is_default_profile="true">  <!-- 定义参与者,profile_name属性定义了参与者的名称,is_default_profile属性定义了该参与者是否为默认参与者 -->
             <rtps>  <!-- 开始定义rtps -->
                 <builtin>  <!-- 开始定义builtin -->
                     <discovery_config>  <!-- 开始定义discovery_config -->
                         <discoveryProtocol>SUPER_CLIENT</discoveryProtocol>  <!-- 定义发现协议,此处为SUPER_CLIENT -->
                         <discoveryServersList>  <!-- 开始定义discoveryServersList -->
                             <RemoteServer prefix="44.53.00.5f.45.50.52.4f.53.49.4d.41">  <!-- 定义远程服务器,prefix属性定义了服务器的前缀 -->
                                 <metatrafficUnicastLocatorList>  <!-- 开始定义metatrafficUnicastLocatorList -->
                                     <locator>  <!-- 开始定义locator -->
                                         <udpv4>  <!-- 开始定义udpv4 -->
                                             <address>127.0.0.1</address>  <!-- 定义地址,此处为127.0.0.1 -->
                                             <port>11811</port>  <!-- 定义端口,此处为11811 -->
                                         </udpv4>  <!-- 结束定义udpv4 -->
                                     </locator>  <!-- 结束定义locator -->
                                 </metatrafficUnicastLocatorList>  <!-- 结束定义metatrafficUnicastLocatorList -->
                             </RemoteServer>  <!-- 结束定义RemoteServer -->
                         </discoveryServersList>  <!-- 结束定义discoveryServersList -->
                     </discovery_config>  <!-- 结束定义discovery_config -->
                 </builtin>  <!-- 结束定义builtin -->
             </rtps>  <!-- 结束定义rtps -->
         </participant>  <!-- 结束定义participant -->
     </profiles>  <!-- 结束定义profiles -->
 </dds>  <!-- 结束定义dds -->

 便条

在 RemoteServer 标签下,前缀属性值应根据 CLI 上传递的服务器 ID 进行更新(参见 Fast DDS CLI)。所示 XML 片段中指定的值对应于值为 0 的 ID。

首先,使用 Fast DDS CLI 实例化一个 ID 值为 0 的发现服务器。

fastdds discovery -i 0 -l 127.0.0.1 -p 11811

运行一个对话器和一个监听器,它们将通过服务器相互发现(注意 ROS_DISCOVERY_SERVER 配置与 super_client_configuration_file.xml 中的配置相同)。

export ROS_DISCOVERY_SERVER="127.0.0.1:11811"
ros2 run demo_nodes_cpp listener --ros-args --remap __node:=listener
export ROS_DISCOVERY_SERVER="127.0.0.1:11811"
ros2 run demo_nodes_cpp talker --ros-args --remap __node:=talker

然后,使用超级客户端配置实例化一个 ROS 2 守护进程(记住在每个新终端中都要 source ROS 2 安装)。

export FASTRTPS_DEFAULT_PROFILES_FILE=super_client_configuration_file.xml
ros2 daemon stop
ros2 daemon start
ros2 topic list
ros2 node info /talker
ros2 topic info /chatter
ros2 topic echo /chatter
cxy@ubuntu2404-cxy:~$ export FASTRTPS_DEFAULT_PROFILES_FILE=super_client_configuration_file.xml
cxy@ubuntu2404-cxy:~$ ros2 daemon stop
The daemon is not running
cxy@ubuntu2404-cxy:~$ ros2 daemon start
The daemon has been started
cxy@ubuntu2404-cxy:~$ ros2 topic list
/chatter
/parameter_events
/rosout
cxy@ubuntu2404-cxy:~$ ros2 node info /talker
/talker
  Subscribers:
    /parameter_events: rcl_interfaces/msg/ParameterEvent
  Publishers:
    /chatter: std_msgs/msg/String
    /parameter_events: rcl_interfaces/msg/ParameterEvent
    /rosout: rcl_interfaces/msg/Log
  Service Servers:
    /talker/describe_parameters: rcl_interfaces/srv/DescribeParameters
    /talker/get_parameter_types: rcl_interfaces/srv/GetParameterTypes
    /talker/get_parameters: rcl_interfaces/srv/GetParameters
    /talker/get_type_description: type_description_interfaces/srv/GetTypeDescription
    /talker/list_parameters: rcl_interfaces/srv/ListParameters
    /talker/set_parameters: rcl_interfaces/srv/SetParameters
    /talker/set_parameters_atomically: rcl_interfaces/srv/SetParametersAtomically
  Service Clients:


  Action Servers:


  Action Clients:


cxy@ubuntu2404-cxy:~$ ros2 topic info /chatter
Type: std_msgs/msg/String
Publisher count: 1
Subscription count: 1
cxy@ubuntu2404-cxy:~$ ros2 topic echo /chatter
data: 'Hello World: 59'
---
data: 'Hello World: 60'
---
data: 'Hello World: 61'
---
data: 'Hello World: 62'
---
data: 'Hello World: 63'

我们还可以使用 ROS 2 工具 rqt_graph 查看节点图,如下所示(您可能需要按刷新按钮):

export FASTRTPS_DEFAULT_PROFILES_FILE=super_client_configuration_file.xml
rqt_graph

b6ec2aac2a4818730e1dd82baa61549f.png

11d0c7243f29b5ff95fc7a2dd3cf1e5e.png

没有守护进程工具 No Daemon tools

有些 ROS 2 CLI 工具不使用 ROS 2 Daemon为了使这些工具能够连接到发现服务器并接收所有主题信息,它们需要被实例化为连接到服务器的超级客户端。

根据之前的配置,构建一个包含说话者和听者的简单系统。首先,运行一个服务器:

fastdds discovery -i 0 -l 127.0.0.1 -p 11811

然后,在不同的终端中运行 talker 和 listener:

export ROS_DISCOVERY_SERVER="127.0.0.1:11811"
ros2 run demo_nodes_cpp listener --ros-args --remap __node:=listener
export ROS_DISCOVERY_SERVER="127.0.0.1:11811"
ros2 run demo_nodes_cpp talker --ros-args --remap __node:=talker

继续使用带有 --no-daemon 选项的新配置的 ROS 2 CLI。新节点将连接到现有服务器,并将知道每个主题。不需要导出 ROS_DISCOVERY_SERVER ,因为 ROS 2 工具将通过 FASTRTPS_DEFAULT_PROFILES_FILE 进行配置。

export FASTRTPS_DEFAULT_PROFILES_FILE=super_client_configuration_file.xml
ros2 topic list --no-daemon
ros2 node info /talker --no-daemon --spin-time 2

比较 Fast DDS 发现服务器与简单发现协议

为了比较使用简单发现协议(默认的 DDS 机制用于分布式发现)或发现服务器执行节点,提供了两个脚本来执行一个讲述者和多个监听器,并在此期间分析网络流量。对于这个实验,您的系统上需要安装 tshark 。配置文件是必需的,以避免使用进程内模式。

 便条

这些脚本仅支持 Linux,并且需要一个发现服务器关闭功能,该功能仅在比 ROS 2 Foxy 版本更新的版本中可用。为了使用此功能,请使用 Fast DDS v2.1.0 或更高版本编译 ROS 2。

这些脚本的功能是供高级用途参考的,学习由用户自行完成。

  • bash network traffic generator

  • python3 graph generator

  • XML configuration

https://docs.ros.org/en/jazzy/_downloads/4091f7105a6c8d10b26927288ede29fc/generate_discovery_packages.bash

https://docs.ros.org/en/jazzy/_downloads/617a6849c029c43a931e24db314cb224/discovery_packets.py

https://docs.ros.org/en/jazzy/_downloads/358434c24ca02455545e1739688b839b/no_intraprocess_configuration.xml

运行 bash 脚本,并将 setup.bash 文件的路径作为参数传递给 ROS 2。这将生成简单发现的流量跟踪。使用第二个参数 SERVER 执行相同的脚本。它将生成使用发现服务器的跟踪。

 便条

根据您对 tcpdump 的配置,此脚本可能需要 sudo 权限才能读取网络设备上的流量。

在两个执行都完成后,运行 Python 脚本生成一个类似于下面的图表。

$ export FASTRTPS_DEFAULT_PROFILES_FILE="no_intraprocess_configuration.xml"
$ sudo bash generate_discovery_packages.bash ~/ros2/install/local_setup.bash
$ sudo bash generate_discovery_packages.bash ~/ros2/install/local_setup.bash SERVER
$ python3 discovery_packets.py

999e41d05a648719db9dc8a8caa5b6c3.png

此图是实验特定运行的结果。读者可以执行脚本并生成自己的结果进行比较。可以很容易地看出,使用发现服务时网络流量减少

流量的减少是由于避免每个节点宣布自己并等待网络上每个其他节点的响应。这在大型架构中会产生大量流量。随着节点数量的增加,这种方法的减少量增加,使得这种架构比简单发现协议方法更具可扩展性

新的 Fast DDS Discovery Server v2 自 Fast DDS v2.0.2 起可用,取代了旧的发现服务器。在这个新版本中,那些不共享主题的节点将自动不发现彼此,从而节省了连接它们及其端点所需的整个发现数据。上面的实验没有显示这种情况,但即便如此,由于 ROS 2 节点的隐藏基础设施主题,流量的大幅减少仍然可以被欣赏。

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

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

相关文章

【15】Android基础知识之Window(一)

概述 这篇文章纠结了很久&#xff0c;在想需要怎么写&#xff1f;因为window有关的篇幅&#xff0c;如果需要讲起来那可太多了。从层级&#xff0c;或是从关联&#xff0c;总之不是很好开口。这次也下定决心&#xff0c;决定从浅入深的讲讲window这个东西。 Window Window是…

django报错(三):No crontab program或got an unexpected keyword argument ‘user’

Crontab是linux系统上的定时管理模块&#xff0c;简单配置&#xff0c;灵活使用。但是要在windows使用必须借助Cygwin等虚拟工具&#xff0c;否则会报错“No crontab program”。如下图&#xff1a; python-crontab是其提供了python模块对crontab的访问&#xff0c;即可以通过p…

【简历】惠州某二本学院:前端简历指导,秋招面试通过率为0

注&#xff1a;为保证用户信息安全&#xff0c;姓名和学校等信息已经进行同层次变更&#xff0c;内容部分细节也进行了部分隐藏 简历说明 这是一份25届二本同学&#xff0c;投递前端职位的简历&#xff0c;那么在校招环节二本同学主要针对的还是小公司&#xff0c;这个学校因为…

怎么关闭Windows安全中心?

Windows安全中心是Windows操作系统中的一项重要功能&#xff0c;系统提供这个功能的目的是保护电脑免受各种安全威胁。尽管如此&#xff0c;有时候我们可能出于某些原因需要关闭它。本文将详细介绍如何关闭Windows安全中心&#xff0c;以及需要注意的事项。 重要提醒&#xff1…

minIO集成springboot

问题 minIO与spring集成。 步骤 创建桶 创建key 找到创建账号页面&#xff0c;如下图&#xff1a; 点击创建&#xff0c;如下图&#xff1a; 设置如下权限&#xff1a; {"Version": "2012-10-17","Statement": [{"Effect": &q…

生成式AI、3D模型交易、模型轻量化、模型格式转换、3D可视化、数字孪生引擎等

老子云3D可视化快速开发平台&#xff0c;集云压缩、云烘焙、云存储云展示于一体&#xff0c;使3D模型资源自动输出至移动端PC端、Web端&#xff0c;能在多设备、全平台进行展示和交互&#xff0c;是全球领先、自主可控的自动化3D云引擎。 平台架构 平台特性 1、基于 HTML5 和 …

django报错(一):python manage.py makemigrations,显示“No changes detected”

执行python manage.py makemigrations命令无任何文件生成&#xff0c;结果显示“No changes detected”。 解决方案一&#xff1a; 1、执行命令&#xff1a;python manage.py makemigrations –empty appname 2、删除其中的0001_initial.py文件&#xff08;因为这个文件内容是…

《昇思25天学习打卡营第25天|第10天》

今天是打卡的第十天&#xff0c;今天开始学应用实践中的LLM原理和实践&#xff0c;今天学的是基于MindSpore实现BERT对话情绪识别。最先了解的是BERT模型的简介&#xff08;来自变换器的双向编码器表征量&#xff08;Bidirectional Encoder Representations from Transformers&…

【Java】:浅克隆和深克隆

克隆 克隆和赋值 克隆的结果是有多个相同的实体&#xff0c;各个对象指向不同的实体而多个不同对象指向一个相同的实体不是克隆&#xff0c;而是赋值 克隆的过程 首先实例化一个 student1 对象 在堆里开辟了一块内存用来存储 age 10 这个数据 调用 clone 方法 在堆中又开辟了一…

Python数据结构:实现自定义栈与队列

更多Python学习内容&#xff1a;ipengtao.com 在计算机科学中&#xff0c;栈&#xff08;Stack&#xff09;和队列&#xff08;Queue&#xff09;是两种常见的数据结构。它们在算法和数据处理方面有着广泛的应用。本文将详细介绍如何在Python中实现自定义的栈与队列&#xff0c…

stm32精密控制步进电机(升级篇)

这一篇文章里会深入的对步进电机控制方法进行论述 如何避免步进电机丢转的问题 1.机械结构&#xff1a;排查一下传动的问题&#xff0c;举个例子&#xff0c;我的毕设里大臂机械臂的步进电机有时会有丢转问题&#xff0c;造成无法运动到指定位置&#xff0c;后面发现是因为皮带…

【单元测试】SpringBoot

【单元测试】SpringBoot 1. 为什么单元测试很重要&#xff1f;‼️ 从前&#xff0c;有一个名叫小明的程序员&#xff0c;他非常聪明&#xff0c;但有一个致命的缺点&#xff1a;懒惰。小明的代码写得又快又好&#xff0c;但他总觉得单元测试是一件麻烦事&#xff0c;觉得代码…

2.RabbitMQ相关概念

介绍 RabbitMQ是一个消息中间件&#xff0c;接受并转发消息。它接收、存储和转发消息数据。 四大核心概念&#xff1a; 1.生产者 产生数据发送消息的程序是生产者。 2.消费者 3.队列 每一个队列对应一个消费者。 如果两个消费者对应同一个队列&#xff0c;那么队列中的…

云监控(华为) | 实训学习day1(10)

云监控&#xff1a;确保服务器高效运行 在当今的数字化时代&#xff0c;服务器的稳定运行对于任何企业都至关重要。为了确保服务器的 CPU、内存和硬盘等资源的合理运行&#xff0c;云监控成为了一项不可或缺的技术。本文将详细介绍云监控的基本概念、所需软件、配置方法以及如何…

分布式 I/O 系统 BL200 Modbus TCP 耦合器

BL200 耦合器是一个数据采集和控制系统&#xff0c;基于强大的 32 位微处理器设计&#xff0c;采用 Linux 操作系统&#xff0c;支持 Modbus 协议&#xff0c;可以快速接入现场 PLC、SCADA 以及 ERP 系统&#xff0c; 内置逻辑控制、边缘计算应用&#xff0c;适用于 IIoT 和工业…

redis登录缓存

1.pom.xml中引入redis依赖 <!-- Redis依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency> 2.将登录成功的token存储到redis中 if(Md5…

捷配PCB打样采用机械盲埋孔制造,有何优势?

在电子制造领域&#xff0c;盲孔&#xff08;Blind Vias&#xff09;与埋孔&#xff08;Buried Vias&#xff09;是两种关键的PCB&#xff08;印刷电路板&#xff09;过孔技术。盲孔特指那些连接内层走线至外层走线的过孔&#xff0c;但并不贯穿整个板体。相对地&#xff0c;埋…

【数学建模】技术革新——Lingo的使用超详解

目录 基础知识 1. 变量声明 示例 2. 常量声明 语法格式 示例 3. 目标函数 语法格式 示例 4. 约束条件 语法格式 示例 5. 完整的Lingo模型示例 示例 解释 6. 整数变量声明 语法格式 示例 7. 非线性规划 示例 8. 多目标优化 语法格式 示例 9. 数据输入与…

持续集成02--Linux环境更新/安装Java新版本

前言 在持续集成/持续部署&#xff08;CI/CD&#xff09;的旅程中&#xff0c;确保开发环境的一致性至关重要。本篇“持续集成02--Linux环境更新/安装Java新版本”将聚焦于如何在Linux环境下高效地更新或安装Java新版本。Java作为广泛应用的编程语言&#xff0c;其版本的更新对…

ModuleNotFoundError: No module named ‘_cffi_backend‘的二中情况解决方案

1、问题概述? 创作时间:2024年7月 在pycharm中执行python脚本出现如下问题: No module named _cffi_backend 主要说明二中情况: 第一种原因:最常见的原因就是没有安装cffi模块,我们通过命令安装就可以了。 第二种原因:不常见的原因,如果你在pycharm中运行了别人的…