网站点击率代码/最好的优化公司
系列文章目录
ROS2 重要概念
ament_cmake_python 用户文档
ROS2 ament_cmake 用户文档
使用 rosdep 管理 ROS 2 依赖项
文章目录
- 系列文章目录
- 前言
- 一、Launch 文件示例
- 1.1 Python 版本
- 1.2 XML 版本
- 1.3 YAML 版本
- 二、从命令行使用 Launch 文件
- 1. Launching
- 2. 设置参数
- 3. 控制海龟
- 三、Python、XML 或 YAML: 我应该使用哪种语言?
- 四、为什么要使用 ROS 2 Launch
- `如果觉得内容不错,请点赞、收藏、关注`
前言
ROS 2 launch 文件可以用 Python、XML 和 YAML 编写。本指南介绍了如何使用这些不同的格式来完成相同的任务,并对何时使用每种格式进行了讨论。
一、Launch 文件示例
下面是一个用 Python、XML 和 YAML 实现的 Launch 文件。每个 Launch 文件都执行以下操作:
-
使用默认值设置命令行参数
-
包含另一个 launch 文件
-
在另一个命名空间中包含另一个启动文件
-
启动节点并设置其名称空间
-
启动一个节点,设置其名称空间,并在该节点中设置参数(使用参数)
-
创建一个节点,将消息从一个话题重新映射到另一个话题
1.1 Python 版本
首先介绍涉及到的几个 类
和 方法
ament_index_python.get_package_share_path(package_name, print_warning=True)
以 pathlib.Path 的形式返回给定软件包的共享目录。
例如,如果您将软件包 "foo "安装到"/home/user/ros2_ws/install",并以 "foo"作为参数调用此函数,那么它将返回一个代表"/home/user/ros2_ws/install/share/foo"的路径,然后您就可以用它来构建共享文件的路径,即 get_package_share_path('foo') /'urdf/robot.urdf'
launch.LaunchDescription
基础: LaunchDescriptionEntity
可启动系统的描述。
该描述由一系列实体组成,这些实体代表了系统设计师的意图。
该描述还可能有参数,参数由该启动描述中的 launch.actions.DeclareLaunchArgument 操作声明。
该描述的参数可通过 get_launch_arguments() 方法访问。参数是通过搜索此启动描述中的实体和每个实体的描述(可能包括由这些实体产生的实体)收集的。
launch.actions.declare_launch_argument.DeclareLaunchArgument(Action)
基础: Action
声明新启动参数的 Action。
启动参数存储在同名的 "启动配置 "中。请参阅 launch.actions.SetLaunchConfiguration 和 launch.substitutions.LaunchConfiguration。
在 launch.LaunchDescription 中声明的任何启动参数都会在包含该启动描述时作为参数显示出来,例如,在 launch.actions.IncludeLaunchDescription 动作中作为附加参数,或在使用 ros2 launch .... 启动时作为命令行参数。
除了名称(也是参数结果的存储位置)外,启动参数还可能有一个默认值、一个有效值选择列表和一个描述。如果给出了默认值,那么该参数就变成了可选参数,默认值将被放置在启动配置中。如果没有给出默认值,并且在包含启动说明时也没有给出值,则会发生错误。如果给出了一个选择列表,而给定值不在其中,则会发生错误。
默认值可以使用 Substitutions,但名称和描述只能是 Text,因为它们在启动前需要一个有意义的值,例如在列出命令行参数时。
需要注意的是,声明启动参数必须在启动描述的某个部分,而这个部分在不启动的情况下是可以描述的。例如,如果你在条件组中或作为事件处理程序的回调声明了一个启动参数,那么像 ros2 launch 这样的工具可能无法在启动描述之前知道该参数。在这种情况下,该参数在命令行上将不可见,但如果该参数在访问后未满足要求(且没有默认值),则可能引发异常。
换句话说,访问该操作的后置条件要么是同名的启动配置设置了值,要么是由于没有设置任何值且没有默认值而引发异常。但是,前置条件并不能保证在条件或情况夹杂后面的参数是可见的。
例如;
ld = LaunchDescription([DeclareLaunchArgument('simple_argument'),DeclareLaunchArgument('with_default_value', default_value='default'),DeclareLaunchArgument('with_default_and_description',default_value='some_default',description='this argument is used to configure ...'),DeclareLaunchArgument('mode',default_value='A',description='Choose between mode A and mode B',choices=['A', 'B']),# other actions here, ...
])
launch.actions.GroupAction
基础: Action
可产生其他操作的 Action。
此操作用于嵌套其他操作,而无需包含单独的启动说明,同时还可选择具有一个条件(与所有其他操作一样)、扩展和转发启动配置和环境变量,以及/或仅为组及其产生的操作声明启动配置。
Scoped=True 时,对启动配置和环境变量的更改仅限于组操作中的操作范围。
当 scopeed=True 和 forwarding=True 时,所有现有的启动配置和环境变量都可在作用域上下文中使用。
当 scope=True 和 forwarding=False 时,所有现有的启动配置和环境变量都会从作用域上下文中移除。
launch_configurations 字典中定义的任何启动配置都将在当前上下文中设置。当 scopeed=False 时,即使 GroupAction 已完成,这些配置也将持续存在。当 scoped=True 时,这些配置将仅对 GroupAction 中的动作可用。当 scope=True 和 forwarding=False 时,launch_configurations 字典将在清除前进行评估,然后在清除的 scope 上下文中重新设置。
launch.actions.IncludeLaunchDescription
基础: Action
包含启动描述源并在访问时生成其实体的动作。
可以向启动描述传递参数,这些参数是通过 launch.actions.DeclareLaunchArgument 动作声明的。
如果给定的参数与已声明的启动参数名称不匹配,则仍会使用 launch.actions.SetLaunchConfiguration 动作将其设置为启动配置。这样做的原因是,在给定的启动描述中,并非总能检测到所有已声明启动参数类的实例。
另一方面,如果给定的启动描述声明了启动参数,但未向此操作提供其值,有时会引发错误。不过,只有当声明的启动参数是无条件的(有时声明启动参数的操作只有在特定情况下才会被访问),并且没有默认值可供选择时,才会产生这种错误。
有条件包含的启动参数如果没有默认值,在尽力进行参数检查后仍无法提前发现未满足的参数时,最终将引发错误。
launch.launch_description_sources.PythonLaunchDescriptionSource(LaunchDescriptionSource)
基础: LaunchDescriptionSource
Python 启动文件的封装,可在启动过程中加载。
launch.substitutions.LaunchConfiguration(Substitution)
可访问启动配置变量的替代变量。
launch.substitutions.TextSubstitution(Substitution)
可对单个字符串文本进行替换。
PushROSNamespace(Action)
推送 ros 命名空间的动作。
在有作用域的 `GroupAction` 中使用时,它会自动弹出。没有其他方法可以弹出它。
XMLLaunchDescriptionSource(FrontendLaunchDescriptionSource)
封装 XML 启动文件,可在启动过程中加载。
YAMLLaunchDescriptionSource(FrontendLaunchDescriptionSource)
封装 YAML 启动文件,可在启动过程中加载。
Node(ExecuteProcess)
执行一个 ROS 节点的操作。
Python 代码如下
# example_launch.pyimport osfrom ament_index_python import get_package_share_directoryfrom launch import LaunchDescription
from launch.actions import DeclareLaunchArgument
from launch.actions import GroupAction
from launch.actions import IncludeLaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSource
from launch.substitutions import LaunchConfiguration
from launch.substitutions import TextSubstitution
from launch_ros.actions import Node
from launch_ros.actions import PushRosNamespace
from launch_xml.launch_description_sources import XMLLaunchDescriptionSource
from launch_yaml.launch_description_sources import YAMLLaunchDescriptionSourcedef generate_launch_description():# args that can be set from the command line or a default will be usedbackground_r_launch_arg = DeclareLaunchArgument("background_r", default_value=TextSubstitution(text="0"))background_g_launch_arg = DeclareLaunchArgument("background_g", default_value=TextSubstitution(text="255"))background_b_launch_arg = DeclareLaunchArgument("background_b", default_value=TextSubstitution(text="0"))chatter_py_ns_launch_arg = DeclareLaunchArgument("chatter_py_ns", default_value=TextSubstitution(text="chatter/py/ns"))chatter_xml_ns_launch_arg = DeclareLaunchArgument("chatter_xml_ns", default_value=TextSubstitution(text="chatter/xml/ns"))chatter_yaml_ns_launch_arg = DeclareLaunchArgument("chatter_yaml_ns", default_value=TextSubstitution(text="chatter/yaml/ns"))# include another launch filelaunch_include = IncludeLaunchDescription(PythonLaunchDescriptionSource(os.path.join(get_package_share_directory('demo_nodes_cpp'),'launch/topics/talker_listener_launch.py')))# include a Python launch file in the chatter_py_ns namespacelaunch_py_include_with_namespace = GroupAction(actions=[# push_ros_namespace to set namespace of included nodesPushRosNamespace('chatter_py_ns'),IncludeLaunchDescription(PythonLaunchDescriptionSource(os.path.join(get_package_share_directory('demo_nodes_cpp'),'launch/topics/talker_listener_launch.py'))),])# include a xml launch file in the chatter_xml_ns namespacelaunch_xml_include_with_namespace = GroupAction(actions=[# push_ros_namespace to set namespace of included nodesPushRosNamespace('chatter_xml_ns'),IncludeLaunchDescription(XMLLaunchDescriptionSource(os.path.join(get_package_share_directory('demo_nodes_cpp'),'launch/topics/talker_listener_launch.xml'))),])# include a yaml launch file in the chatter_yaml_ns namespacelaunch_yaml_include_with_namespace = GroupAction(actions=[# push_ros_namespace to set namespace of included nodesPushRosNamespace('chatter_yaml_ns'),IncludeLaunchDescription(YAMLLaunchDescriptionSource(os.path.join(get_package_share_directory('demo_nodes_cpp'),'launch/topics/talker_listener_launch.yaml'))),])# start a turtlesim_node in the turtlesim1 namespaceturtlesim_node = Node(package='turtlesim',namespace='turtlesim1',executable='turtlesim_node',name='sim')# start another turtlesim_node in the turtlesim2 namespace# and use args to set parametersturtlesim_node_with_parameters = Node(package='turtlesim',namespace='turtlesim2',executable='turtlesim_node',name='sim',parameters=[{"background_r": LaunchConfiguration('background_r'),"background_g": LaunchConfiguration('background_g'),"background_b": LaunchConfiguration('background_b'),}])# perform remap so both turtles listen to the same command topicforward_turtlesim_commands_to_second_turtlesim_node = Node(package='turtlesim',executable='mimic',name='mimic',remappings=[('/input/pose', '/turtlesim1/turtle1/pose'),('/output/cmd_vel', '/turtlesim2/turtle1/cmd_vel'),])return LaunchDescription([background_r_launch_arg,background_g_launch_arg,background_b_launch_arg,chatter_py_ns_launch_arg,chatter_xml_ns_launch_arg,chatter_yaml_ns_launch_arg,launch_include,launch_py_include_with_namespace,launch_xml_include_with_namespace,launch_yaml_include_with_namespace,turtlesim_node,turtlesim_node_with_parameters,forward_turtlesim_commands_to_second_turtlesim_node,])
1.2 XML 版本
<!-- example_launch.xml --><launch><!-- args that can be set from the command line or a default will be used --><arg name="background_r" default="0" /><arg name="background_g" default="255" /><arg name="background_b" default="0" /><arg name="chatter_py_ns" default="chatter/py/ns" /><arg name="chatter_xml_ns" default="chatter/xml/ns" /><arg name="chatter_yaml_ns" default="chatter/yaml/ns" /><!-- include another launch file --><include file="$(find-pkg-share demo_nodes_cpp)/launch/topics/talker_listener_launch.py" /><!-- include a Python launch file in the chatter_py_ns namespace--><group><!-- push_ros_namespace to set namespace of included nodes --><push_ros_namespace namespace="$(var chatter_py_ns)" /><include file="$(find-pkg-share demo_nodes_cpp)/launch/topics/talker_listener_launch.py" /></group><!-- include a xml launch file in the chatter_xml_ns namespace--><group><!-- push_ros_namespace to set namespace of included nodes --><push_ros_namespace namespace="$(var chatter_xml_ns)" /><include file="$(find-pkg-share demo_nodes_cpp)/launch/topics/talker_listener_launch.xml" /></group><!-- include a yaml launch file in the chatter_yaml_ns namespace--><group><!-- push_ros_namespace to set namespace of included nodes --><push_ros_namespace namespace="$(var chatter_yaml_ns)" /><include file="$(find-pkg-share demo_nodes_cpp)/launch/topics/talker_listener_launch.yaml" /></group><!-- start a turtlesim_node in the turtlesim1 namespace --><node pkg="turtlesim" exec="turtlesim_node" name="sim" namespace="turtlesim1" /><!-- start another turtlesim_node in the turtlesim2 namespaceand use args to set parameters --><node pkg="turtlesim" exec="turtlesim_node" name="sim" namespace="turtlesim2"><param name="background_r" value="$(var background_r)" /><param name="background_g" value="$(var background_g)" /><param name="background_b" value="$(var background_b)" /></node><!-- perform remap so both turtles listen to the same command topic --><node pkg="turtlesim" exec="mimic" name="mimic"><remap from="/input/pose" to="/turtlesim1/turtle1/pose" /><remap from="/output/cmd_vel" to="/turtlesim2/turtle1/cmd_vel" /></node>
</launch>
1.3 YAML 版本
# example_launch.yamllaunch:# args that can be set from the command line or a default will be used
- arg:name: "background_r"default: "0"
- arg:name: "background_g"default: "255"
- arg:name: "background_b"default: "0"
- arg:name: "chatter_py_ns"default: "chatter/py/ns"
- arg:name: "chatter_xml_ns"default: "chatter/xml/ns"
- arg:name: "chatter_yaml_ns"default: "chatter/yaml/ns"# include another launch file
- include:file: "$(find-pkg-share demo_nodes_cpp)/launch/topics/talker_listener_launch.py"# include a Python launch file in the chatter_py_ns namespace
- group:- push_ros_namespace:namespace: "$(var chatter_py_ns)"- include:file: "$(find-pkg-share demo_nodes_cpp)/launch/topics/talker_listener_launch.py"# include a xml launch file in the chatter_xml_ns namespace
- group:- push_ros_namespace:namespace: "$(var chatter_xml_ns)"- include:file: "$(find-pkg-share demo_nodes_cpp)/launch/topics/talker_listener_launch.xml"# include a yaml launch file in the chatter_yaml_ns namespace
- group:- push_ros_namespace:namespace: "$(var chatter_yaml_ns)"- include:file: "$(find-pkg-share demo_nodes_cpp)/launch/topics/talker_listener_launch.yaml"# start a turtlesim_node in the turtlesim1 namespace
- node:pkg: "turtlesim"exec: "turtlesim_node"name: "sim"namespace: "turtlesim1"# start another turtlesim_node in the turtlesim2 namespace and use args to set parameters
- node:pkg: "turtlesim"exec: "turtlesim_node"name: "sim"namespace: "turtlesim2"param:-name: "background_r"value: "$(var background_r)"-name: "background_g"value: "$(var background_g)"-name: "background_b"value: "$(var background_b)"# perform remap so both turtles listen to the same command topic
- node:pkg: "turtlesim"exec: "mimic"name: "mimic"remap:-from: "/input/pose"to: "/turtlesim1/turtle1/pose"-from: "/output/cmd_vel"to: "/turtlesim2/turtle1/cmd_vel"
二、从命令行使用 Launch 文件
1. Launching
上述任何启动文件都可以通过 ros2 launch 运行。要在本地试用它们,可以创建一个新软件包,然后使用
ros2 launch <package_name> <launch_file_name>
或通过指定 launch 文件的路径直接运行该文件
ros2 launch <path_to_launch_file>
2. 设置参数
要设置传递给启动文件的参数,应使用 key:=value 语法。例如,可以用以下方式设置 background_r 的值:
ros2 launch <package_name> <launch_file_name> background_r:=255
ros2 launch <path_to_launch_file> background_r:=255
3. 控制海龟
要测试重映射是否有效,可以在另一个终端运行以下命令来控制海龟:
ros2 run turtlesim turtle_teleop_key --ros-args --remap __ns:=/turtlesim1
三、Python、XML 或 YAML: 我应该使用哪种语言?
ROS 1 中的启动文件是用 XML 编写的,因此对于来自 ROS 1 的用户来说,XML 可能是最熟悉的。
对于大多数应用程序来说,选择哪种 ROS 2 启动格式取决于开发人员的偏好。不过,如果你的启动文件需要有 XML 或 YAML 无法实现的灵活性,你可以使用 Python 来编写启动文件。由于以下两个原因,使用 Python 编写 ROS 2 启动文件更为灵活:
-
Python 是一种脚本语言,因此您可以在启动文件中使用该语言及其库。
-
ros2/launch(一般启动功能)和 ros2/launch_ros(ROS 2 特定启动功能)都是用 Python 编写的,因此你可以访问 XML 和 YAML 可能无法提供的较低级别的启动功能。
尽管如此,用 Python 编写的启动文件可能比 XML 或 YAML 编写的文件更复杂、更冗长。
四、为什么要使用 ROS 2 Launch
ROS 2 系统通常由运行在多个不同进程(甚至不同机器)上的多个节点组成。虽然每个节点都可以单独运行,但很快就会变得非常麻烦。
ROS 2 中的启动系统旨在通过一条命令自动运行多个节点。它可以帮助用户描述系统配置,然后按描述执行。系统配置包括运行哪些程序、在哪里运行、传递哪些参数,以及 ROS 特有的约定,通过为每个组件提供不同的配置,可以方便地在整个系统中重复使用组件。它还负责监控已启动进程的状态,并对这些进程的状态变化做出报告和/或反应。
上述所有内容都在一个启动文件中指定,该文件可以用 Python、XML 或 YAML 编写。使用 ros2 launch 命令运行该启动文件后,所有指定的节点都将运行。
设计文档详细介绍了 ROS 2 启动系统的设计目标(目前尚未提供所有功能)。
如果觉得内容不错,请点赞、收藏、关注
相关文章:

使用 Python、XML 和 YAML 编写 ROS 2 Launch 文件
系列文章目录 ROS2 重要概念 ament_cmake_python 用户文档 ROS2 ament_cmake 用户文档 使用 rosdep 管理 ROS 2 依赖项 文章目录 系列文章目录前言一、Launch 文件示例1.1 Python 版本1.2 XML 版本1.3 YAML 版本 二、从命令行使用 Launch 文件1. Launching2. 设置参数3. 控制海…...

SpringCloud 微服务全栈体系(十)
第十章 RabbitMQ 一、初识 MQ 1. 同步和异步通讯 微服务间通讯有同步和异步两种方式: 同步通讯:就像打电话,需要实时响应。 异步通讯:就像发邮件,不需要马上回复。 两种方式各有优劣,打电话可以立即得…...

[原创]Cadence17.4,win64系统,构建CIS库
目录 1、背景介绍 2、具体操作流程 3、遇到问题、分析鉴别问题、解决问题 4、借鉴链接并评论 1、背景介绍 CIS库,绘制原理图很方便,但是需要在Cadence软件与数据库之间建立联系,但是一直不成功,花费半天时间才搞明白如何建立关系并…...

Python 海龟绘图基础教学教案(一)
Python 海龟绘图——第 1 题 题目:绘制下面的图形 解析: 考察 turtle 基本命令,绘制直线,使用 forward,可缩写为 fd。 答案: import turtle as t t.fd(100) # 或者使用 t.forward(100) t.done() Python 海…...

JUC并发编程系列(一):Java线程
前言 JUC并发编程是Java程序猿必备的知识技能,只有深入理解并发过程中的一些原则、概念以及相应源码原理才能更好的理解软件开发的流程。在这篇文章中荔枝会梳理并发编程的基础,整理有关Java线程以及线程死锁的知识,希望能够帮助到有需要的小…...

双向链表相关代码
DLinkList.h // // DLinkList.hpp // FirstP // // Created by 赫赫 on 2023/10/31. // 双向链表相关代码:双向链表、循环双向链表#ifndef DLinkList_hpp #define DLinkList_hpp #include <stdio.h> #include <stdlib.h> #include <iostream>…...

[每周一更]-(第70期):常用的GIT操作命令
1、增删文件 # 添加当前目录的所有文件到暂存区 $ git add .# 添加指定文件到暂存区 $ git add <file1> <file2> ...# 添加指定目录到暂存区,包括其子目录 $ git add <dir># 删除工作区文件,并且将这次删除放入暂存区 $ git rm [file…...

Leetcode-283 移动零
count记录0的个数,不为0的数取代0位置,最后把剩余位置置零 class Solution {public void moveZeroes(int[] nums) {int count 0;for(int i0;i<nums.length;i){if(nums[i]0){count;}else{nums[i-count]nums[i];}}for(int inums.length-count;i<nu…...

爱上C语言:函数递归,青蛙跳台阶图文详解
🚀 作者:阿辉不一般 🚀 你说呢:生活本来沉闷,但跑起来就有风 🚀 专栏:爱上C语言 🚀作图工具:draw.io(免费开源的作图网站) 如果觉得文章对你有帮助的话,还请…...

Pycharm 对容器中的 Python 程序断点远程调试
pycharm如何连接远程服务器的docker容器有两种方法: 第一种:pycharm通过ssh连接已在运行中的docker容器 第二种:pycharm连接docker镜像,pycharm运行代码再自动创建容器 本文是第一种方法的教程,第二种请点击以上的链接…...

自动驾驶行业观察之2023上海车展-----车企发展趋势(3)
合资\外资发展 宝马:i7、iX1新车亮相,未来将持续发力电动化、数字化(座舱) 宝马在本次车展重点展示了电动化产品,新发车型为i7 M70L、iX1、及i vision Dee概念车等车型。 • 展示重点:电动化数字化&#…...

day55【动态规划子序列】392.判断子序列 115.不同的子序列
文章目录 392.判断子序列115.不同的子序列 392.判断子序列 题目链接:力扣链接 讲解链接:代码随想录讲解链接 题意:给定字符串 s 和 t ,判断 s 是否为 t 的子序列。 字符串的一个子序列是原始字符串删除一些(也可以不…...

c语言中磁盘文件的分类
#include <stdio.h> /*磁盘文件的分类: * 一个文件通常是磁盘上一段命名的存储区计算机的存储在物理上是二进制的, * 所以物理上所有的磁盘文件本质上都是一样的:以字节为单位进行顺序存储 * 从用户或者操作系统使用的角度(…...

Unity适配微信
使用的是微信开发的插件 GitHub - wechat-miniprogram/minigame-unity-webgl-transform 路径相关: Unity:Application.streamingAssetsPath --> 配置的cdn路径StreamingAssets...

虚拟机本地磁盘在线扩容
背景 虚拟机本地盘对于host物理机来说就是一个LVM卷,虚拟化(libvirt+kvm_qemu)已经支持虚拟机磁盘在线调整,配合物理机lvm管理工具可实现云场景下虚拟机磁盘在线扩容功能。环境检查 (1)虚拟机本地盘信息 <disk type=block device=disk><driver...

ACTIVE_MQ学习
ActiveMq学习①___入门概述https://blog.csdn.net/qq_45905724/article/details/131796502 ActiveMq学习②__安装与控制台https://blog.csdn.net/qq_45905724/article/details/133893214 ActiveMq学习③___Java编码实现ActiveMQ通讯https://blog.csdn.net/qq_45905724/articl…...

【C++初阶】类和对象(上)
【C初阶】类和对象(上) 1.面向对象与面向过程的初步认识2.类的引入3. 类的定义4.类的访问限定符及封装4.1访问限定符4.2封装 5.类的作用域6.类的实例化6.类的对象的大小计算7.类的this指针7.1this指针的引入7.2this指针的一些特性 📃博客主页…...

新版onenet平台安全鉴权的确定与使用
根据onenet官方更新的文档:平台提供开放的API接口,用户可以通过HTTP/HTTPS调用,进行设备管理,数据查询,设备命令交互等操作,在API的基础上,根据自己的个性化需求搭建上层应用。 为提高API访问安…...

容器核心技术-Namespace
一、容器 基于Linux 内核的 Cgroup, Namespace,以及Union FS等技术,对进程进行封装隔离,属于操作系统层面的虚拟化技术,由于隔离的进程独立于宿主和其它的隔离的进程,因此也称其为容器。 1.1 容器主要特性…...

linux写文件如何保证落盘?
3.1.1. sync sync函数只是将所有修改过的块缓冲区排入写队列,然后就返回,它并不等待实际写磁盘操作结束。通常称为 update的系统守护进程会周期性地(一般每隔30秒)调用sync函数。这就保证了定期冲洗内核的块缓冲区。命令 sync也…...

2023 electron最新最简版打包、自动升级详解
这里我将讲解一下从0搭建一个electron最简版架子,以及如何实现打包自动化更新 之前我有写过两篇文章关于electron框架概述以及 常用api的使用,感兴趣的同学可以看看 Electron桌面应用开发 Electron桌面应用开发2 搭建electron 官方文档:ht…...

ConcurrentHashMap是如何实现线程安全的
目录 原理: 初始化数据结构时的线程安全 put 操作时的线程安全 原理: 多段锁cassynchronize 初始化数据结构时的线程安全 在 JDK 1.8 中,初始化 ConcurrentHashMap 的时候这个 Node[] 数组是还未初始化的,会等到第一次 put() 方…...

MYSQL:索引与锁表范围简述
一、聚簇索引原则 当有主键索引时,选择主键索引;如果没有主键索引,选择第一个的unique索引;如果都没有就选择隐藏生成的ROW_ID。 二、加锁原则 来自知乎MySQL探秘(七):InnoDB行锁算法 - 知乎 (zhihu.com) 在不通过索引条件查询时…...

15 款 PDF 编辑器帮助轻松编辑、合并PDF文档
PDF 编辑器在当今的数字环境中至关重要,因为 PDF 已成为共享和存储信息的首选格式。只需几分钟,可靠的 PDF 编辑器即可让用户能够根据其特定需求修改、定制和定制文档。在本文中,我们全面汇编了 15 款最佳免费 PDF 编辑器,让您可以…...

PS Raw中文增效工具Camera Raw 16
Camera Raw 16 for mac(PS Raw增效工具)的功能特色包括强大的图像调整工具。例如,它提供白平衡、曝光、对比度、饱和度等调整选项,帮助用户优化图像的色彩和细节。此外,Camera Raw 16的界面简洁易用,用户可…...

Flink源码解析二之执行计划⽣成
JobManager Leader 选举 首先flink会依据配置获取RecoveryMode,RecoveryMode一共两两种:STANDALONE和ZOOKEEPER。 如果用户配置的是STANDALONE,会直接去配置中获取JobManager的地址如果用户配置的是ZOOKEEPER,flink会首先尝试连接zookeeper,利用zookeeper的leadder选举服务发现…...

MySQL遍历所有表所有字段查找字符数据
MySQL遍历所有表所有字段查找字符数据 工作中有一些数据查找,但是在那个库那个表那个字段中并不明确,特别是敏感字符查找,如果数据量并不大,我们可以采用遍历整个库、表中字符来查找相关数据来解决该问题。 我们可以写一个存储过…...

Java中的异常处理机制是怎样的?
Java中的异常处理机制主要包括以下几个部分: 异常类(Exception Class):Java中的异常类继承自java.lang.Throwable,主要分为两大类:Error和Exception。Error表示程序无法处理的严重问题,如系统崩…...

高教社杯数模竞赛特辑论文篇-2023年A题:定日镜场的优化设计(附获奖论文及MATLAB代码实现)
目录 摘 要 一、 问题重述 1.1 问题背景 1.2 问题重述 二、 模型假设 三、 符号说明...

c语言实现http下载功能,显示进度条和下载速率
#include <stdio.h>//printf #include <string.h>//字符串处理 #include <sys/socket.h>//套接字 #include <arpa/inet.h>//ip地址处理 #include <fcntl.h>//open系统调用 #include <unistd.h>//write系统调用 #include <netdb.h>//…...