ROS2 Humble学习笔记

本文发表与个人的github pages。部分内容未同步到这里。
想查看完整内容,请移步到ROS2 Humble学习笔记

一、前言

2013年的时候已经接触ROS了,当时断断续续学习了一些ROS的基础知识。16年搬到深圳之后,也有幸参加过星火的一次关于ROS的一些活动。当时活动的主讲之一是CSDN上ROS知识传播界的大牛的古月和港中文的林天麟先生。然而,因为自己一直涉猎的是嵌入式领域,一直没有在ROS上有所深耕。十年过去了,我相信我的知识已经足够从头到尾做一台机器人小车(无论是嵌入式软硬件合适结构)。所以我决定开始重新学习ROS。当年ROS2还没有完成,现在ROS2的LTS版本已经是humble了(ROS的版本大体是按照字母顺序起名的,所以你可以看到进展)。

这次学习,我的目标是达到中级水平,能够按照自己的需求开发机器人系统所需要的功能包。另一方面,在工程上我希望基于手边的Jetson Nano自己制作一台机器人。在这些够完成之后,开始个人的机器人项目:Artemis。

除了ROS2的学习,我还希望同时了解和学习Nvidia的ISAAC ROS开发方法。好在我的笔记本基本满足ISAAC的最低要求。知识内存需要从16G升级到32G。目前暂且使用笔记本来开发ISAAC,后续如果实在需要服务器或者PC机,可能这将是一笔较大的投入。不过暂时先将此时放在一边。
好了,现在开始学习吧。愿计划可以达成。

二、安装

为了安装humble,我的计算机目前安装的Ubuntu22.04,这也是一个LTS版本。安装过程并不复杂,我按照官方的教程在笔记本(AMD64)和Raspberry Pi 4(ARM64)。

但是在我的Jetson Nano上遇到了问题。这是因为Nvidia对于Jetson Nano的支持并不积极,目前Nvidia的JetPack5(基于ubuntu20.04)支持的是orin系列和AVG系列。似乎JetPack 6(基于ubuntu22.04)也已经预发布了。似乎还继续支持orin和AVG系列。但按照我们对于Nvidia的了解,对于orin的支持也仅到JetPack6. Ubuntu 24.04将会是2024年另一个LTS版本,厂家的程序可能会延后半年到一年。所以nvidia未来的JetPack7可能会在2024年底或者2025年发布。相应的新Jetson硬件也应该会在2024年发布。所以如果需要购买Jetson,我们可以再等一等。暂时还是设法让Jetson Nano对humble进行支持。下面这几张图是Nvidia的产品和软件Roadmap,我觉得很讽刺的是支持的最后年限并不意味着软件和系统也跟着做相应的支持。
1

图1:Jetson模块消费版路线图

2

图2:Jetson模块工业版路线图

3

图3:JetPack软件路线图

在搜索了一通之后,发现目前的道路有三条。一条是容易的道路,使用别人已经编译好的容器。另一条更难的道路是自行编译ROS2使其支持ubuntu18.04.第三条是让Jetson Nano支持ubuntu22.04.因为现在属于初期阶段,不想在起步阶段就卡住。所以我暂时使用容器的方法。当然这条道路坑也很多。

2.1 Jetson Nano容器方法运行ROS2 Humble

在开始正文之前,我简单说一下为什么会选择Humble,因为这是目前的最新的LTS版本,支持时间也相对比较长。感兴趣的朋友可以去ROS网站查看一下每个版本的支持时间。

2.1.1 基础安装和尝试

Jetson Nano容器安装也是Nvidia官方支持的一部分。我们可以在他们的[链接](Jetson Containers)找到相应的说明。这个链接中包含多个ROS版本的Base、Core、Desktop镜像。
具体的安装方法可以看上面的链接中的说明。这里简单枚举一下命令:

#下载镜像到本地
sudo docker pull dustynv/ros:humble-ros-base-l4t-r32.7.1

# 通过镜像方式运行,这是一种比较节省空间的方式
sudo docker run --runtime nvidia -it --rm --network=host dustynv/ros:humble-ros-base-l4t-r36.2.0

#另一种更powerful的方式是直接clone整个仓库,然后在本都build和运行
#但是这种方式应该会占用更多空间,上手会有一定的难度。
#可以在稍微熟悉之后再尝试
2.1.2 docker运行界面程序遇到的问题和解决办法

在docker界面运行ros2后如果要运行turtlesim_node,rqt等依赖gui的程序时要怎么解决问题。

2.1.3 docker运行界面程序的IP问题
2.1.X 更多问题

2.2 与ROS相关的vscode的插件

古月的ROS2入门21讲里面里面很好的总结了ROS2开发相干的插件,这里转述如下:

  • ROS开发语言相关的python和C/C++插件。还有智能提示插件IntelliCode。这三个都是microsoft出的。还有CMAKE插件,古月推荐的是twxs提供的CMake插件,而不是由微软提供的CMake Tools。
  • 美化相关的除了各种主题之外还有语言插件和叫做vscode-icons的插件。(也是microsoft出品)
  • 与ROS直接相关的插件有:microsoft出的ROS(对ROS1和ROS2提供开发支持);msg格式支持的Msg Language Support(作者是ajshort);由smilerobotics制作的URDF插件对URDF文件提供支持;

三、ROS2基础学习

3.1 怎么查看turtlesim某个包的可执行文件

在官方的示例中,我们看到ros2 run的基本格式如下:ros2 run <package_name> <executable_name>,但是当我们拿到一个package的时候怎么它的executable对象呐。其实和我们查看我们的环境中的的packages是类似的。

# 查看pack命令
ros2 pkg list

# 查看是否包含某个名称的pack,例如寻找和urdf相关的包
ros2 pkg list | grep urdf

# 查看某个包的可执行程序,比如我们查看turtlesim包含的可执行程序
ros2 pkg executables turtlesim
#你将会收到如下response
# turtlesim draw_square
# turtlesim mimic
# turtlesim turtle_teleop_key
# turtlesim turtlesim_node

3.2 深刻理解spawn操作

在官方入门教程Using turtlesim, ros2, and rqt那一章中指导我们利用rqt产生一个turtle,但是在看ros2入门21讲的时候我注意到它是利用命令行产生的另一个turtle。命令如下:

ros2 service call /spawn turtlesim/srv/Spawn "{x: 2, y: 2, theta: 0.2, name: ''}"
3.2.1 追根溯源,弄懂怎么控制小乌龟

但是这条命令的格式为什么是这样,如果我要自己编辑一个命令靠死记硬背肯定不行呀。其实这也不是很复杂,我跟着ros2的命令提示操作起来。

# 1. 我们先看一下ros2都支持啥命令. 
# 为了便于描述,我在自己输入的命令前加上了‘$ ’
$ ros2 -h
  action     Various action related sub-commands
  bag        Various rosbag related sub-commands
  component  Various component related sub-commands
  daemon     Various daemon related sub-commands
  doctor     Check ROS setup and other potential issues
  interface  Show information about ROS interfaces
  launch     Run a launch file
  lifecycle  Various lifecycle related sub-commands
  multicast  Various multicast related sub-commands
  node       Various node related sub-commands
  param      Various param related sub-commands
  pkg        Various package related sub-commands
  run        Run a package specific executable
  security   Various security related sub-commands
  service    Various service related sub-commands
  topic      Various topic related sub-commands
  wtf        Use `wtf` as alias to `doctor`
# 共有17个参数,缩写和单词都是单数。不要误写成复数形式。
# 我们可以看到doctor和daemon分别是负责issue检查和守护程序的相关功能, wtf和docter一样
# lifecycle用来运行和生命周期相关的功能;multicast和组播相关;security应该是和加密相关的功能
# run用来运行包的可执行程序文件;launch运行启动文件;bag是用来记录、播放、查询rosbag的功能集
# pkg是ros功能包相关的功能集;interface和pkg的接口相关的功能集,下面会重点用到它
# components看提示适合container(容器)以及component(组件/元件)相关的。但目前还不知道用法
# param和node(节点)相关的参数操作相关的功能集
# node/service/action/topic是ROS2中一些基础概念,后面会提到

# 2. 起初我并不知道spawn到底是属于service,topic,action或是param
#    但是没关系,我们用list分别看看各自包含什么
$ ros2 node list
/turtlesim
$ ros2 action list
/turtle1/rotate_absolute
$ ros2 param list
/turtlesim:
  background_b
  background_g
  background_r
  qos_overrides./parameter_events.publisher.depth
  qos_overrides./parameter_events.publisher.durability
  qos_overrides./parameter_events.publisher.history
  qos_overrides./parameter_events.publisher.reliability
  use_sim_time
$ ros2 topic list
/parameter_events
/rosout
/turtle1/cmd_vel
/turtle1/color_sensor
/turtle1/pose
$ ros2 service list
/clear
/kill
/reset
/spawn
/turtle1/set_pen
/turtle1/teleport_absolute
/turtle1/teleport_relative
/turtlesim/describe_parameters
/turtlesim/get_parameter_types
/turtlesim/get_parameters
/turtlesim/list_parameters
/turtlesim/set_parameters
/turtlesim/set_parameters_atomically
# 上面是当我之前只开启了一个turtlesim_node之后的情况
# 可以看到spwan属于服务,当随着之后的学习我相信应该可以更准确的预测某个功能是service还是topic
# 好了我们现在锁定了我们想要的spwan功能属于一个service,具体是’/spawn‘

# 3.那么我们不妨先看一下service到底有啥操作
$ ros2 service -h
usage: ros2 service [-h] [--include-hidden-services] Call `ros2 service <command> -h` for more detailed usage. ...

Various service related sub-commands

options:
  -h, --help            show this help message and exit
  --include-hidden-services
                        Consider hidden services as well

Commands:
  call  Call a service
  find  Output a list of available services of a given type
  list  Output a list of available services
  type  Output a service's type             '
  Call `ros2 service <command> -h` for more detailed usage.

$ ros2 service call -h
ros2 service call -h
usage: ros2 service call [-h] [-r N] service_name service_type [values]

Call a service

positional arguments:
  service_name    Name of the ROS service to call to (e.g. '/add_two_ints')
  service_type    Type of the ROS service (e.g. 'std_srvs/srv/Empty')
  values          Values to fill the service request with in YAML format (e.g. '{a: 1, b: 2}'), otherwise the service request will be published with default values

options:
  -h, --help      show this help message and exit
  -r N, --rate N  Repeat the call at a specific rate in Hz

# 很显然ros2 service call是我们最终要使用的可执行程序它需要三个参数
# 第一个参数是service_name,这里是我们用`ros2 service list`的时候查询到的`/spwan`
# 第二个参数是service_type,按照上面的输出我们应该可以通过调用type查询到
# 第三个参数是values,需要参数是YAML形式的。这个是问题的核心。这个参数可选,忽略后用默认值。

# 4. 我们先来找到第二个参数
$ ros2 service type /spawn
turtlesim/srv/Spawn
# 在反复品味这个指令之后,我的理解是type是这个service需要的数据结构/数据类型
# 在尝试了param之后想到interface应该包含这个数据结构的信息,一测试还真可以

# 5. 我们用interface查看一下第三个参数有什么
$ ros2 interface -h
usage: ros2 interface [-h] Call `ros2 interface <command> -h` for more detailed usage. ...

Show information about ROS interfaces

options:
  -h, --help            show this help message and exit

Commands:
  list      List all interface types available
  package   Output a list of available interface types within one package
  packages  Output a list of packages that provide interfaces
  proto     Output an interface prototype
  show      Output the interface definition

  Call `ros2 interface <command> -h` for more detailed usage.
$ ros2 interface package turtlesim
turtlesim/srv/Spawn
turtlesim/srv/SetPen
turtlesim/srv/TeleportRelative
turtlesim/msg/Pose
turtlesim/msg/Color
turtlesim/action/RotateAbsolute
turtlesim/srv/Kill
turtlesim/srv/TeleportAbsolute
# 我们可以看到'turtlesim/srv/Spawn'正是turtlesim包的可用接口类型
# service type也是一种interface type。可以看到有srv,msg和action三种接口
# msg应该是topic用的,srv就是我们这里的service用的,action就是action用的
$ ros2 interface proto turtlesim/srv/Spawn
"x: 0.0
y: 0.0
theta: 0.0
name: ''
"
# 查看了类型的原型(prototype)
$ ros2 interface show turtlesim/srv/Spawn
float32 x
float32 y
float32 theta
string name # Optional.  A unique name will be created and returned if this is empty
---
string name
# 显示更详细的信息

到这里我们就基本了解了怎么使用spawn去产生另一个乌龟。这里还有一个问题是YAML是什么数据格式。我这里提供一个菜鸟教程的链接.YAML的语法还是有一些比较严格的规格的,可以使用vscode中的redhat的YAML插件来检查数据内容是否符合规格。一般在shell中使用YAML的flow style形式。和json类似,但key不使用引号包裹。
根据上面的提示物品们就可以自己制作一个的命令,注意YAML语句需要用单引号或者双引号包裹:

ros2 service call /spawn turtlesim/srv/Spawn "{ x: 6, y: 6, theta: 0.0, name: 'wu_gui' }"
3.2.2 举一反三,我们试着使用“/reset”服务

按照上面类似的方法我们可以看一下/reset的用法:

# 查询第二个参数
$ ros2 service type /reset
std_srvs/srv/Empty

# 使用interface的show或者proto功能去查看这个类型的信息
$ ros2 interface proto std_srvs/srv/Empty
"{}
"

# 至此我们基本确定了value是空,这个参数可以省略
# 现在开始尝试一下
$ ros2 service call /reset std_srvs/srv/Empty

# 这时候你会发现之前界面上的两只乌龟都消失了,出来了另一只不同颜色的乌龟
3.2.3 扩展技能,使用action操作乌龟

在3.2.1的最后我们使用service创造了另一只乌龟,不过在3.2.2中我们又将它清除了。现在我们再次重复3.2.1的操作创建另一只名字叫"wu_gui"的turtle。

## 1. 查询目前支持的action
$ ros2 action -h
usage: ros2 action [-h] Call `ros2 action <command> -h` for more detailed usage. ...

Various action related sub-commands

options:
  -h, --help            show this help message and exit

Commands:
  info       Print information about an action
  list       Output a list of action names
  send_goal  Send an action goal

  Call `ros2 action <command> -h` for more detailed usage.

## 2.查询一下send_goal需要什么参数 
$ ros2 action send_goal -h
usage: ros2 action send_goal [-h] [-f] action_name action_type goal

Send an action goal

positional arguments:
  action_name     Name of the ROS action (e.g. '/fibonacci')
  action_type     Type of the ROS action (e.g. 'example_interfaces/action/Fibonacci')
  goal            Goal request values in YAML format (e.g. '{order: 10}')

options:
  -h, --help      show this help message and exit
  -f, --feedback  Echo feedback messages for the goal

## 3. 现在看一下都有那些action,可以看到我们的wu_gui节点有一个action
$ ros2 action list
/turtle1/rotate_absolute
/wu_gui/rotate_absolute

## 4. 查询/wu_gui/rotate_absolute这个action的信息
$ ros2 action info -h
usage: ros2 action info [-h] [-t] [-c] action_name

Print information about an action

positional arguments:
  action_name       Name of the ROS action to get info (e.g. '/fibonacci')

options:
  -h, --help        show this help message and exit
  -t, --show-types  Additionally show the action type
  -c, --count       Only display the number of action clients and action servers
$ ros2 action info -t /wu_gui/rotate_absolute
Action: /wu_gui/rotate_absolute
Action clients: 0
Action servers: 1
    /turtlesim [turtlesim/action/RotateAbsolute]

## 此时我们得到send_goal的action_name和action_type,还需要一个goal
## 5. 类似与之前的方法我们用interface指令去查询turtlesim/action/RotateAbsolute
$ ros2 interface proto turtlesim/action/RotateAbsolute
"theta: 0.0
"

# 至此我们基本确定了所有的参数
# 6. 现在开始尝试发送指令
ros2 action send_goal /wu_gui/rotate_absolute  turtlesim/action/RotateAbsolute "{ theta: 1.732}"
Waiting for an action server to become available...
Sending goal:
     theta: 1.732

Goal accepted with ID: 8733fdd9a69a4bfebda19fae76b0912d

Result:
    delta: -0.9440000057220459

Goal finished with status: SUCCEEDED

现在你会发现乌龟已经朝向了顶部。

3.2.4 继续折腾,使用topic和乌龟对话

topic是ros2很重要的概念,turtlesim下面有很多topic。稍后我会展示cmd_vel这个Topic。

# 1. 我们先看一下topic的功能
$ ros2 topic -h
usage: ros2 topic [-h] [--include-hidden-topics] Call `ros2 topic <command> -h` for more detailed usage. ...

Various topic related sub-commands

options:
  -h, --help            show this help message and exit
  --include-hidden-topics
                        Consider hidden topics as well

Commands:
  bw     Display bandwidth used by topic
  delay  Display delay of topic from timestamp in header
  echo   Output messages from a topic
  find   Output a list of available topics of a given type
  hz     Print the average publishing rate to screen
  info   Print information about a topic
  list   Output a list of available topics
  pub    Publish a message to a topic
  type   Print a topic's type                          '   

# 可以看到topic的功能还是很复杂的,后面我只展示几个主要步骤
# 2. 我们看一下当前有什么topic
$ ros2 topic list
/parameter_events
/rosout
/turtle1/cmd_vel
/turtle1/color_sensor
/turtle1/pose
/wu_gui/cmd_vel
/wu_gui/color_sensor
/wu_gui/pose
# 3. pub按照解释应该是发布(publish)主题的我们简单看一下它的用法 
ros2 topic pub -h
usage: ros2 topic pub [-h] [-r N] [-p N] [-1 | -t TIMES] [-w WAIT_MATCHING_SUBSCRIPTIONS] [--keep-alive N] [-n NODE_NAME]
                      [--qos-profile {unknown,system_default,sensor_data,services_default,parameters,parameter_events,action_status_default}] [--qos-depth N]
                      [--qos-history {system_default,keep_last,keep_all,unknown}] [--qos-reliability {system_default,reliable,best_effort,unknown}]
                      [--qos-durability {system_default,transient_local,volatile,unknown}] [--spin-time SPIN_TIME] [-s]
                      topic_name message_type [values]

Publish a message to a topic

positional arguments:
  topic_name            Name of the ROS topic to publish to (e.g. '/chatter')
  message_type          Type of the ROS message (e.g. 'std_msgs/String')
  values                Values to fill the message with in YAML format (e.g. 'data: Hello World'), otherwise the message will be published with default values

options:
  -h, --help            show this help message and exit
  -r N, --rate N        Publishing rate in Hz (default: 1)
  -p N, --print N       Only print every N-th published message (default: 1)
  -1, --once            Publish one message and exit
  -t TIMES, --times TIMES
                        Publish this number of times and then exit
  -w WAIT_MATCHING_SUBSCRIPTIONS, --wait-matching-subscriptions WAIT_MATCHING_SUBSCRIPTIONS
                        Wait until finding the specified number of matching subscriptions. Defaults to 1 when using "-1"/"--once"/"--times", otherwise defaults to 0.
  --keep-alive N        Keep publishing node alive for N seconds after the last msg (default: 0.1)
  -n NODE_NAME, --node-name NODE_NAME
                        Name of the created publishing node
  --qos-profile {unknown,system_default,sensor_data,services_default,parameters,parameter_events,action_status_default}
                        Quality of service preset profile to publish)
  --qos-depth N         Queue size setting to publish with (overrides depth value of --qos-profile option)
  --qos-history {system_default,keep_last,keep_all,unknown}
                        History of samples setting to publish with (overrides history value of --qos-profile option, default: keep_last)
  --qos-reliability {system_default,reliable,best_effort,unknown}
                        Quality of service reliability setting to publish with (overrides reliability value of --qos-profile option, default: reliable)
  --qos-durability {system_default,transient_local,volatile,unknown}
                        Quality of service durability setting to publish with (overrides durability value of --qos-profile option, default: transient_local)
  --spin-time SPIN_TIME
                        Spin time in seconds to wait for discovery (only applies when not using an already running daemon)
  -s, --use-sim-time    Enable ROS simulation time
# 尽管pub的命令很复杂,但是主要的参数还是3个:name,type,value
# 这和action,service并不区别。其中value有时是可选的
# 只是topic多了很多更多样的options,这些options后面慢慢研究

# 4. info和type都可以看到某个topic的类型,这里我们使用type看一下/wu_gui/cmd_vel的类型
$ ros2 topic type /wu_gui/cmd_vel
geometry_msgs/msg/Twist

# 这样我们就获得了第二个参数
# 现在根据第二个参数来了解第三个参数要怎么输入
$ ros2 interface show geometry_msgs/msg/Twist
# This expresses velocity in free space broken into its linear and angular parts.

Vector3  linear
	float64 x
	float64 y
	float64 z
Vector3  angular
	float64 x
	float64 y
	float64 z
$ ros2 interface proto geometry_msgs/msg/Twist
"linear:
  x: 0.0
  y: 0.0
  z: 0.0
angular:
  x: 0.0
  y: 0.0
  z: 0.0
"
# 上面的信息显示了线速度和角速度,每个都是三个参数组成的矢量,每个参数都是float64类型的。
# float64暂时不知道是不是double还是一种特殊定义的float类型。

# 5. 按照上面的信息我们来组合一个pub命令
$ ros2 topic pub /wu_gui/cmd_vel  geometry_msgs/msg/Twist  "{ linear: { x: 5.0, y: 0.0, z: 0.0 }, angular: { x: 0.0, y: 0.0, z: 1.732 }}"

现在你可以看到一个旋转的乌龟:

4

图4:旋转乌龟


<本文完/2024.01.09/watershade2010]>
<后续部分未转载>
想查看完整内容,请移步到ROS2 Humble学习笔记

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

S281 LoRa网关在智能电力监测系统中的应用

随着能源消耗的增加和环境保护的要求&#xff0c;智能电力监测系统在电力行业得到了广泛的应用。作为一家领先的科技公司&#xff0c;钡铼技术有限公司推出的S281 LoRa网关为智能电力监测系统提供了强大的支持和解决方案。本文将重点介绍S281 LoRa网关在智能电力监测系统中的应…

【Android Studio】APP练手小项目——切换图片APP

本项目效果&#xff1a; 前言&#xff1a;本项目最终实现生成一个安卓APP软件&#xff0c;点击按钮可实现按钮切换图片。项目包含页面布局、功能实现的逻辑代码以及设置APP图标LOGO和自定义APP名称。 关于Android Studio的下载与安装见我的博文&#xff1a;Android Studio 最新…

Native Crash回溯栈

获取调用栈四种方案&#xff1a;Android Native Crash 收集 1、使用系统的<unwind.h>库 可以获取到出错文件与函数名。只不过需要自己解析函数符号&#xff0c;同时经常会捕获到系统错误&#xff0c;需要手动过滤。 2、libcorkscrew 在4.1.1以上&#xff0c;5.0以下&…

C# 强制类型转换和as区别和不同使用场景

文章目录 1.强制类型转换2. as 运算符3.实例总结&#xff1a; 在C#中&#xff0c;as 和 强制类型转换&#xff08;例如 (T)value&#xff09;的主要区别在于它们处理类型转换不成功时的行为和适用场景&#xff1a; 1.强制类型转换 使用语法&#xff1a;Type variable (Type)…

设计模式之适配器模式【结构型模式】

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档> 学习的最大理由是想摆脱平庸&#xff0c;早一天就多一份人生的精彩&#xff1b;迟一天就多一天平庸的困扰。各位小伙伴&#xff0c;如果您&#xff1a; 想系统/深入学习某…

“高端”的位运算

王有志&#xff0c;一个分享硬核Java技术的互金摸鱼侠加入Java人的提桶跑路群&#xff1a;共同富裕的Java人 原计划迭代作为预备知识的收尾&#xff0c;不过在解2的幂和4的幂时&#xff0c;想到关于数字2的问题可以通过位运算去解决&#xff0c;因此补充了关于位运算的内容。 …

基于ssm的生鲜在线销售系统的设计与实现论文

摘 要 使用旧方法对生鲜在线销售系统的信息进行系统化管理已经不再让人们信赖了&#xff0c;把现在的网络信息技术运用在生鲜在线销售系统的管理上面可以解决许多信息管理上面的难题&#xff0c;比如处理数据时间很长&#xff0c;数据存在错误不能及时纠正等问题。这次开发的生…

Python(33):数据断言(查询数据库数据和插入数据对比)

Python(33):数据断言(查询数据库数据和插入数据对比) 前言&#xff1a; 需求&#xff1a;需要针对查询数据库数据和插入的数据进行对比&#xff0c;用Python语言进行编写 数据库查询的结果可参考&#xff1a;https://blog.csdn.net/fen_fen/article/details/135462484 1、查…

共享文件访问权限被拒绝

winr 打开命令行输入gpedit.msc打开组编辑窗口 这样操作之后就远程电脑一般就可以访问共享文件夹了

STM32CubeMX配置STM32G031多通道UART+DMA收发数据(HAL库开发)

时钟配置HSI主频配置64M 配置好串口&#xff0c;选择异步模式 配置DMA TX,RX,选择循环模式。 NVIC中勾选使能中断 勾选生成独立的.c和h文件 配置好需要的开发环境并获取代码 串口重定向勾选Use Micro LIB main.c文件修改 增加头文件和串口重定向 #include <string.h&g…

纯血鸿蒙「扩圈」100天,酝酿已久的突围

坦白讲&#xff0c;去年参加华为开发者大会看到HarmonyOS NEXT&#xff08;仅运行鸿蒙原生应用&#xff0c;所以也称作「纯血鸿蒙」&#xff09;的时候&#xff0c;小雷也没料想到鸿蒙原生应用生态的发展速度会如此之快。 9月25日&#xff0c;华为正式对外宣布启动HarmonyOS NE…

LabVIEW在微生物检测中的应用

随着对食品安全关注的增加&#xff0c;食品检测的准确性变得越来越重要。其中&#xff0c;微生物计数作为食品合格的关键指标&#xff0c;对其检测技术的准确性和实时性要求极高。传统的微生物检测面临着菌落识别困难、设备实时性差和自动化程度不高等问题&#xff0c;尤其在疫…

深入了解鸿鹄电子招投标系统:Java版企业电子招标采购系统的核心功能

随着市场竞争的加剧和企业规模的扩大&#xff0c;招采管理逐渐成为企业核心竞争力的重要组成部分。为了提高招采工作的效率和质量&#xff0c;我们提出了一种基于电子化平台的解决方案。该方案旨在通过电子化招投标&#xff0c;使得招标采购的质量更高、速度更快&#xff0c;同…

【HarmonyOS4.0】第三篇-类web开发模式

【HarmonyOS4.0】第三篇-类web开发模式 一、鸿蒙介绍 课程核心 为什么我们需要学习鸿蒙&#xff1f; 哪些人适合直接转鸿蒙&#xff1f; 鸿蒙系统优势是什么&#xff1f; 课程内容 (1)为什么要学习鸿蒙 从行情出发&#xff1a; 美国商务部长访问中国&#xff0c;2023年…

uniapp实现清除缓存

一、页面加载时计算缓存大小&#xff08;H5不支持&#xff09; data() {return {// 缓存大小展示到页面上fileSizeString: 0KB} }// 获取缓存大小formatSize() {let that this;// #ifndef H5plus.cache.calculate(function(size) {let sizeCache parseInt(size);if (sizeCac…

linux 使用log4cpp记录项目日志

为什么要用log4cpp记录项目日志 在通常情况下&#xff0c;Linux/UNIX 每个程序在开始运行的时刻&#xff0c;都会打开 3 个已经打开的 stream. 分别用来输入&#xff0c;输出&#xff0c;打印错误信息。通常他们会被连接到用户终端。这 3 个句柄的类型为指向 FILE 的指针。可以…

Spring循环引用和三级缓存

前言 Spring 解决 Bean 之间的循环引用关系用到了三级缓存&#xff0c;那么问题来了。三级缓存是怎么用的&#xff1f;每一层的作用是什么&#xff1f;非得用三级吗&#xff1f;两级缓存行不行&#xff1f; 理解循环引用 所谓的“循环引用”是指 Bean 之间的依赖关系形成了一…

【算法刷题】Day28

文章目录 1. 买卖股票的最佳时机 III题干&#xff1a;算法原理&#xff1a;1. 状态表示&#xff1a;2. 状态转移方程3. 初始化4. 填表顺序5. 返回值 代码&#xff1a; 2. Z 字形变换题干&#xff1a;算法原理&#xff1a;1. 模拟2. 找规律 代码&#xff1a; 1. 买卖股票的最佳时…

PostGIS学习教程二十:3-D

PostGIS学习教程二十&#xff1a;3-D 注意&#xff1a;本文介绍许多PostGIS2.0及更高版本才支持的功能。 文章目录 PostGIS学习教程二十&#xff1a;3-D一、3-D几何图形二、3-D函数三、N-D索引 一、3-D几何图形 到目前为止&#xff0c;我们一直在处理2-D几何图形&#xff08;…

firewalld防火墙命令行工具

firewall-cmd命令 &#xff08;1&#xff09;启动、停止、查看firewalld服务 在安装CentOS 7系统时&#xff0c;会自动安装firewalld 和图形化工具firewall-config.执行以下命令可 以启动 firewalld 并设置为开机自启动状态。 [rootllcgc ~]# systemctl start firewalld.serv…