ros2 launch 用法以及一些基础功能函数的示例

文章目录

  • launch
    • 启动一个节点的launch示例
    • launch文件中添加节点的namespace
    • launch文件中的话题名称映射
    • launch文件中向节点内传入命令行参数
    • launch文件中向节点内传入rosparam
    • 使用方法
    • 多节点启动
    • 命令行参数配置
    • 资源重映射
    • ROS参数设置
    • 加载参数文件
    • 在launch文件中使用条件变量
    • action的分组
    • action的启动延时控制
    • Launch文件包含,在launch文件中调用另一个launch文件
    • 在launch文件中运行脚本
    • 在launch文件中设置环境变量或读取环境变量
    • launch 用法以及一些基础功能函数的示例
    • 参数文件编译配置

launch

##前言

ros2 launch文件中最主要的概念是action,ros2 launch把每一个要执行的节点,文件,脚本,功能等全部抽象成action,用统一的接口来控制其启动,最主要的结构是:

def generate_launch_description():return LaunchDescription([action_1,action_2,...action_n])

要启动的节点或其他launch文件全部都传入LaunchDescription()函数中,该函数中接受一个或多launch.actionslaunch_ros.actions类型的对象,以下列举一下常用的action:

launch_ros.actions.Node· 此函数功能是启动一个ros2节点;
launch_ros.actions.PushRosNamespace· 此函数功能是给一个节点或组设置命名空间;
launch.actions.IncludeLaunchDescription· 此函数功能是直接引用另一个launch文件;
launch.actions.SetLaunchConfiguration· 此函数功能是在launch文件内声明一个参数,并给定参数值;
launch.actions.SetEnvironmentVariable· 此函数功能是声明一个环境变量并给定环境变量的值;
launch.actions.AppendEnvironmentVariable· 此函数将对一个环境变量追加一个值,如果不存在则创建;
launch.actions.DeclareLaunchArgument· 此函数功能是声明一个启动描述参数,该参数具有名称、默认值和文档;
launch.actions.TimerAction· 此函数功能是在一段时间后执行一个或多个action;
launch.actions.GroupAction· 此函数功能是将action分组,同组内的action可以统一设定参数方便集中管理;
launch.actions.ExecuteProcess· 此函数功能是根据输入执行一个进程或脚本;
launch.actions.EmitEvent· 此函数功能是发出一个事件,触发以注册的事件函数被调用;
launch.actions.RegisterEventHandler· 此函数功能是注册一个事件;
launch.actions.UnregisterEventHandler· 此函数功能是删除一个注册过的事件;

启动一个节点的launch示例

from launch import LaunchDescription
from launch_ros.actions import Nodedef generate_launch_description():return LaunchDescription([Node(package='ros2_test',executable='ros2_test_publisher_node',name='ros2_test_publisher_node',output='screen')])

或者:

from launch import LaunchDescription
from launch_ros.actions import Nodedef generate_launch_description():action_1 = Node(package='ros2_test',executable='ros2_test_publisher_node',name='ros2_test_publisher_node',output='screen')return LaunchDescription([action_1])

launch文件名为test.launch.py,调用launch文件启动节点:

ros2 launch ros2_test test.launch.py

launch文件中添加节点的namespace

from launch import LaunchDescription
from launch_ros.actions import Nodedef generate_launch_description():return LaunchDescription([Node(package='ros2_test',executable='ros2_test_publisher_node',name='ros2_test_publisher_node',output='screen',namespace='my_ros2_test')])

设置了namespace后,此节点的话题前会加上namespace的前缀,例如原来的话题名称’/test’,设置后变为’/my_ros2_test/test’

注意,有以下情况namespace无效:

节点本来就已经有了namespace了,后续会介绍将节点分组,整组节点可以设置统一的namespace,此时如果有个节点已经设置过namespace,则在此设置不会生效;
定义发布节点的时候,topic名字的前面加上了符号/;

launch文件中的话题名称映射

话题映射的字段是remappings,语法示例如下:

remappings=[('src1', 'dest1'),('src2', 'dest2'),...
]

如果需要话题名称映射的话要将该字段加入到节点的函数内,假如节点内有个test1话题要映射到test2,示例如下:

from launch import LaunchDescription
from launch_ros.actions import Nodedef generate_launch_description():return LaunchDescription([Node(package='ros2_test',executable='ros2_test_publisher_node',name='ros2_test_publisher_node',output="screen",remappings=[("test1", "test2")])])

launch文件中向节点内传入命令行参数

参数字段是arguments,语法示例如下:

arguments=['arg1', 'arg2', ...]

如果需要向ros2_test_publisher_node节点中传入命令行参数,示例如下:

from launch import LaunchDescription
from launch_ros.actions import Nodedef generate_launch_description():return LaunchDescription([Node(package='ros2_test',executable='ros2_test_publisher_node',name='ros2_test_publisher_node',output="screen",arguments=['arg1', 'arg2'])])

传入的参数可以从节点启动时main函数中的argc参数获取到参数个数,argv参数获取到参数内容,详情参考c++的命令行参数获取;

launch文件中向节点内传入rosparam

字段是parameter,语法示例如下:

parameters=[{'port': '/dev/ttyUsb0'},...
]

如果需要在launch文件中发布某个节点空间下的parameter,示例如下:

from launch import LaunchDescription
from launch_ros.actions import Nodedef generate_launch_description():return LaunchDescription([Node(package='ros2_test',executable='ros2_test_publisher_node',name='ros2_test_publisher_node',output="screen",parameter=[{'port': '/dev/ttyUSB0'}])])

如果需要参数的值可以从外部调用launch文件时灵活更改,则可以使用变量的形式作为参数的值,在文件中给定默认值,若外部给定则以外部给定的值为准,若外部不给则以默认值为准:

port_var = LaunchConfiguration('port', default='/dev/ttyS1')

同时还可以使用DeclareLaunchArgument函数增加对参数的描述,增加描述后可以通过ros2 launch的命令行工具展示出每个launch文件中有哪些rosparam以及他的默认值和具体含义:

DeclareLaunchArgument('port',default_value=port_var,description='This is the port address value'
)

如果文件中加入了参数介绍则可以通过以下指令看到launch文件中有哪些可以自定义的参数以及参数含义:

ros2 launch ros2_test test.launch.py --show-args

所以如果launch文件中存在可配置参数,应该在LaunchDescription中添加DeclareLaunchArgument,让其他使用者明白变量名,以及他的含义是什么;

完整的launch文件如下:

from launch import LaunchDescription
from launch_ros.actions import Node
from launch.substitutions import LaunchConfigurationdef generate_launch_description():port_var = LaunchConfiguration('port', default='/dev/ttyS1')return LaunchDescription([DeclareLaunchArgument('port',default_value=port_var,description='This is the port address value'),Node(package='ros2_test',executable='ros2_test_publisher_node',name='ros2_test_publisher_node',output="screen",parameter=[{'port': port_var}])])

此时我们可以把参数通过调用launch的时候传入到节点中:

ros2 launch ros2_test test.launch.py port_var:=/dev/ttyUSB2

在ros2_test_publisher_node节点中如果要想获取该参数,需要先声明parameter,然后再进行get:

this->declare_parameter<std::string>("port");
string port_str;
this->get_parameter_or<std::string>("port", port_str, "null");
if (port_str != "null") RCLCPP_INFO(this->get_logger(), "get ros2param port value : %s", port_str.c_str());

使用方法

官方推荐用python编写launch,如果launch文件不在功能包中,随便建立以.launch.py结尾的文件后,在当前目录直接运行即可,如果在功能包中可采用下面方式运行。如下代码。

ros2 launch turtlesim_mimic_launch.py  # 在文件中直接启动launch
ros2 launch <package_name> <launch_file_name> # 在功能包中启动launch

文件内容实例如下:

from launch import LaunchDescription           # launch文件的描述类
from launch_ros.actions import Node            # 节点启动的描述类def generate_launch_description():             # 自动生成launch文件的函数return LaunchDescription([                 # 返回launch文件的描述信息Node(                                  # 配置一个节点的启动package='learning_topic',          # 节点所在的功能包executable='topic_helloworld_pub', # 节点的可执行文件),Node(                                  # 配置一个节点的启动package='learning_topic',          # 节点所在的功能包executable='topic_helloworld_sub', # 节点的可执行文件名),])

多节点启动

from launch import LaunchDescription           # launch文件的描述类
from launch_ros.actions import Node            # 节点启动的描述类def generate_launch_description():             # 自动生成launch文件的函数return LaunchDescription([                 # 返回launch文件的描述信息Node(                                  # 配置一个节点的启动package='learning_topic',          # 节点所在的功能包executable='topic_helloworld_pub', # 节点的可执行文件),Node(                                  # 配置一个节点的启动package='learning_topic',          # 节点所在的功能包executable='topic_helloworld_sub', # 节点的可执行文件名),])

命令行参数配置

import osfrom ament_index_python.packages import get_package_share_directory # 查询功能包路径的方法from launch import LaunchDescription    # launch文件的描述类
from launch_ros.actions import Node     # 节点启动的描述类def generate_launch_description():      # 自动生成launch文件的函数rviz_config = os.path.join(          # 找到配置文件的完整路径get_package_share_directory('learning_launch'),'rviz','turtle_rviz.rviz')return LaunchDescription([           # 返回launch文件的描述信息Node(                             # 配置一个节点的启动package='rviz2',               # 节点所在的功能包executable='rviz2',            # 节点的可执行文件名name='rviz2',                  # 对节点重新命名arguments=['-d', rviz_config]  # 加载命令行参数)])

资源重映射

from launch import LaunchDescription      # launch文件的描述类
from launch_ros.actions import Node       # 节点启动的描述类def generate_launch_description():        # 自动生成launch文件的函数return LaunchDescription([            # 返回launch文件的描述信息Node(                             # 配置一个节点的启动package='turtlesim',          # 节点所在的功能包namespace='turtlesim1',       # 节点所在的命名空间executable='turtlesim_node',  # 节点的可执行文件名name='sim'                    # 对节点重新命名),Node(                             # 配置一个节点的启动package='turtlesim',          # 节点所在的功能包namespace='turtlesim2',       # 节点所在的命名空间executable='turtlesim_node',  # 节点的可执行文件名name='sim'                    # 对节点重新命名),Node(                             # 配置一个节点的启动package='turtlesim',          # 节点所在的功能包executable='mimic',           # 节点的可执行文件名name='mimic',                 # 对节点重新命名remappings=[                  # 资源重映射列表('/input/pose', '/turtlesim1/turtle1/pose'),         # 将/input/pose话题名修改为/turtlesim1/turtle1/pose('/output/cmd_vel', '/turtlesim2/turtle1/cmd_vel'),  # 将/output/cmd_vel话题名修改为/turtlesim2/turtle1/cmd_vel])])

ROS参数设置

from launch import LaunchDescription                   # launch文件的描述类
from launch.actions import DeclareLaunchArgument       # 声明launch文件内使用的Argument类
from launch.substitutions import LaunchConfiguration, TextSubstitutionfrom launch_ros.actions import Node                    # 节点启动的描述类def generate_launch_description():                     # 自动生成launch文件的函数background_r_launch_arg = DeclareLaunchArgument('background_r', default_value=TextSubstitution(text='0')     # 创建一个Launch文件内参数(arg)background_r)background_g_launch_arg = DeclareLaunchArgument('background_g', default_value=TextSubstitution(text='84')    # 创建一个Launch文件内参数(arg)background_g)background_b_launch_arg = DeclareLaunchArgument('background_b', default_value=TextSubstitution(text='122')   # 创建一个Launch文件内参数(arg)background_b)return LaunchDescription([                                      # 返回launch文件的描述信息background_r_launch_arg,                                     # 调用以上创建的参数(arg)background_g_launch_arg,background_b_launch_arg,Node(                                                        # 配置一个节点的启动package='turtlesim',executable='turtlesim_node',                              # 节点所在的功能包name='sim',                                               # 对节点重新命名parameters=[{                                             # ROS参数列表'background_r': LaunchConfiguration('background_r'),   # 创建参数background_r'background_g': LaunchConfiguration('background_g'),   # 创建参数background_g'background_b': LaunchConfiguration('background_b'),   # 创建参数background_b}]),])

加载参数文件

import osfrom ament_index_python.packages import get_package_share_directory  # 查询功能包路径的方法from launch import LaunchDescription   # launch文件的描述类
from launch_ros.actions import Node    # 节点启动的描述类def generate_launch_description():     # 自动生成launch文件的函数config = os.path.join(              # 找到参数文件的完整路径get_package_share_directory('learning_launch'),'config','turtlesim.yaml')return LaunchDescription([          # 返回launch文件的描述信息Node(                            # 配置一个节点的启动package='turtlesim',          # 节点所在的功能包executable='turtlesim_node',  # 节点的可执行文件名namespace='turtlesim2',       # 节点所在的命名空间name='sim',                   # 对节点重新命名parameters=[config]           # 加载参数文件)])

在launch文件中使用条件变量

字段是condition,语法示例如下:

condition=IfCondition(variable)

IfCondition(variable)函数内只接受true, false, 0, 1参数,如果节点启动的描述中加入该字段并且参数值为false或0则节点不启动

完整的launch文件如下:

from launch import LaunchDescription
from launch_ros.actions import Node
from launch.substitutions import LaunchConfiguration
from launch.conditions import IfConditiondef generate_launch_description():variable = LaunchConfiguration('start_flag', default='true')return LaunchDescription([DeclareLaunchArgument('start_flag',default_value=variable,description='This is the ros2_test_publisher_node start flag'),Node(package='ros2_test',executable='ros2_test_publisher_node',name='ros2_test_publisher_node',output="screen",condition=IfCondition(variable))])

此时

运行:ros2 launch ros2_test test.launch.py 节点会正常启动

运行:ros2 launch ros2_test test.launch.py start_flag:=false 节点不会启动

进阶的IfCondition函数使用方式:

由于LaunchConfiguration()函数的返回是一个对象,所以我们不可以拿来直接做运算,但是可以使用PythonExpression()做参数的表达式运算,语法如下:

PythonExpression([variable, '== 1']) 或
PythonExpression([variable, '+ 1 == 2']) 或
PythonExpression([variable, "== 'test'"]) 等等

完整的launch文件如下:

from launch import LaunchDescription
from launch_ros.actions import Node
from launch.substitutions import LaunchConfiguration
from launch.conditions import IfConditiondef generate_launch_description():port_var = LaunchConfiguration('port', default='/dev/ttyS1')return LaunchDescription([DeclareLaunchArgument('port',default_value=port_var,description='This is the port address value'),Node(package='ros2_test',executable='ros2_test_publisher_node',name='ros2_test_publisher_node',output="screen",condition=IfCondition(PythonExpression([port_var, "== '/dev/ttyUSB0'"])))])

此时

运行:ros2 launch ros2_test test.launch.py 节点不会启动

运行:ros2 launch ros2_test test.launch.py port_var:=/dev/ttyUSB0 节点正常启动

action的分组

GroupAction():函数可以将一个或多个action加入到一个组中,组内可以共用参数,控制整组节点全部启动或全部不启动等,方便action的管理,需要接受的部分参数有:

  • actions:接受一个list, [action_1, action_2,…],列表中装要执行的action
  • condition:条件变量参数
  • launch_configuration:参数

PushRosNamespace()函数的作用是向test_group中设置组内的namespace,但是action_1中已经设置过了namespace,所以此时不会生效,该namespace只会在action_2中生效;

实例一:

from launch import LaunchDescription
from launch_ros.actions import Node
from launch.actions import GroupAction
from launch_ros.actions import PushRosNamespacedef generate_launch_description():action_1 = Node(package='ros2_test',executable='ros2_test_publisher_node',name='ros2_test_publisher_node',output='screen',namespace='my_ros2_test')action_2 = Node(package='ros2_test',executable='ros2_test_subscriber_node',name='ros2_test_subscriber_node',output='screen')test_group = GroupAction(actions=[PushRosNamespace("my_group_test"),action_1, action_2])return LaunchDescription([test_group])

action的启动延时控制

TimerAction():函数可以在指定的时间后执行一个action,需要接受参数有

  • period:接受一个float, 延迟的时间
  • actions:接受一个list, [action_1, action_2,…],列表中装要执行的action

实例一:

from launch import LaunchDescription
from launch_ros.actions import Node
from launch.actions import TimerActiondef generate_launch_description():action_1 = Node(package='ros2_test',executable='ros2_test_publisher_node',name='ros2_test_publisher_node',output='screen')return LaunchDescription([TimerAction(period=5.0, actions=[action_1])])

Launch文件包含,在launch文件中调用另一个launch文件

PythonLaunchDescriptionSource() :在launch文件中调用其他launch需要调用函数,参数是被调用launch的路径。

实例一:

import osfrom ament_index_python.packages import get_package_share_directory  # 查询功能包路径的方法from launch import LaunchDescription                 # launch文件的描述类
from launch.actions import IncludeLaunchDescription  # 节点启动的描述类
from launch.launch_description_sources import PythonLaunchDescriptionSource
from launch.actions import GroupAction               # launch文件中的执行动作
from launch_ros.actions import PushRosNamespace      # ROS命名空间配置def generate_launch_description():                   # 自动生成launch文件的函数parameter_yaml = IncludeLaunchDescription(        # 包含指定路径下的另外一个launch文件PythonLaunchDescriptionSource([os.path.join(get_package_share_directory('learning_launch'), 'launch'),'/parameters_nonamespace.launch.py']))parameter_yaml_with_namespace = GroupAction(      # 对指定launch文件中启动的功能加上命名空间actions=[PushRosNamespace('turtlesim2'),parameter_yaml])return LaunchDescription([                        # 返回launch文件的描述信息parameter_yaml_with_namespace])

实例二:

import os
from ament_index_python import get_package_share_directory
from launch import LaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSource
from launch_ros.actions import Nodedef generate_launch_description():return LaunchDescription([Node(package='ros2_test',executable='ros2_test_publisher_node',name='ros2_test_publisher_node',output='screen'),PythonLaunchDescriptionSource(os.path.join(get_package_share_directory('ros2_test'),'launch/test_subscriber.launch.py'))])

实例三:

from launch.launch_description_sources import PythonLaunchDescriptionSource
from launch.substitutions import ThisLaunchFileDir
from launch.conditions import IfCondition
from launch.substitutions import LaunchConfiguration
from launch.actions import IncludeLaunchDescriptiondef generate_launch_description():inlucde_other_file = LaunchConfiguration('inlucde_other_file', default='true')test_var = LaunchConfiguration('test_var', default='test_var_2')return launch.LaunchDescription([IncludeLaunchDescription(PythonLaunchDescriptionSource([ThisLaunchFileDir(), '/test_subscriber.launch.py']),condition=IfCondition(inlucde_other_file),launch_arguments={'test_var': test_var}.items())])

在launch文件中运行脚本

ExecuteProcess():运行脚本同样可实现启动某个节点,同时该函数还支持condition、additional_env等参数的设置。

实例一:

from launch import LaunchDescription
from launch.actions import ExecuteProcessdef generate_launch_description():return LaunchDescription([ExecuteProcess(cmd=['ros2', 'run', 'ros2_test', 'ros2_test_publisher_node'],output="screen")])

在launch文件中设置环境变量或读取环境变量

SetEnvironmentVariable(var_name, var_value):函数用于设置环境变量,接受两个参数分别是要设置的环境变量名称和环境变量的值;

EnvironmentVariable(var_name):函数用于获取环境变量的值,返回值类型是一个对象,输入参数是要获取的环境变量名称;

完整launch文件实例:

from launch import LaunchDescription
from launch.actions import SetEnvironmentVariable, ExecuteProcess
from launch.substitutions import EnvironmentVariabledef generate_launch_description():return LaunchDescription([SetEnvironmentVariable('PRODUCT_MODEL', 'spray_robot'),ExecuteProcess(cmd=['echo', EnvironmentVariable('PRODUCT_MODEL')],output='screen')])

运行看到以下输出

[INFO] [echo-1]: process started with pid [195168]
[echo-1] spray_robot
[INFO] [echo-1]: process has finished cleanly [pid 195168]

launch 用法以及一些基础功能函数的示例

ros2 launch文件中最主要的概念是action,ros2 launch把每一个要执行的节点,文件,脚本,功能等全部抽象成action,用统一的接口来控制其启动,最主要的结构是:

def generate_launch_description():return LaunchDescription([action_1,action_2,...action_n])

要启动的节点或其他launch文件全部都传入LaunchDescription()函数中,该函数中接受一个或多launch.actionslaunch_ros.actions类型的对象,以下列举一下常用的action:

launch_ros.actions.Node· 此函数功能是启动一个ros2节点;
launch_ros.actions.PushRosNamespace· 此函数功能是给一个节点或组设置命名空间;
launch.actions.IncludeLaunchDescription· 此函数功能是直接引用另一个launch文件;
launch.actions.SetLaunchConfiguration· 此函数功能是在launch文件内声明一个参数,并给定参数值;
launch.actions.SetEnvironmentVariable· 此函数功能是声明一个环境变量并给定环境变量的值;
launch.actions.AppendEnvironmentVariable· 此函数将对一个环境变量追加一个值,如果不存在则创建;
launch.actions.DeclareLaunchArgument· 此函数功能是声明一个启动描述参数,该参数具有名称、默认值和文档;
launch.actions.TimerAction· 此函数功能是在一段时间后执行一个或多个action;
launch.actions.GroupAction· 此函数功能是将action分组,同组内的action可以统一设定参数方便集中管理;
launch.actions.ExecuteProcess· 此函数功能是根据输入执行一个进程或脚本;
launch.actions.EmitEvent· 此函数功能是发出一个事件,触发以注册的事件函数被调用;
launch.actions.RegisterEventHandler· 此函数功能是注册一个事件;
launch.actions.UnregisterEventHandler· 此函数功能是删除一个注册过的事件;

参数文件编译配置

功能包里面的参数文件,需要在setup.py里面做以下配置,编译的时候才能拷贝到include里面去

from setuptools import setup
import os
from glob import globpackage_name = 'learning_launch'setup(name=package_name,version='0.0.0',packages=[package_name],data_files=[('share/ament_index/resource_index/packages',['resource/' + package_name]),('share/' + package_name, ['package.xml']),(os.path.join('share', package_name, 'launch'), glob(os.path.join('launch', '*.launch.py'))),(os.path.join('share', package_name, 'config'), glob(os.path.join('config', '*.*'))),(os.path.join('share', package_name, 'rviz'), glob(os.path.join('rviz', '*.*'))),],install_requires=['setuptools'],zip_safe=True,maintainer='hcx',maintainer_email='huchunxu@guyuehome.com',description='TODO: Package description',license='TODO: License declaration',tests_require=['pytest'],entry_points={'console_scripts': [],},
)

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

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

相关文章

【CC2530-操作外部flash】

zigbee cc2530操作flash&#xff0c;以cc2530读flash_id为例子&#xff1b; void InitIO() {CLKCONCMD & ~0x40; //设置系统时钟源为32MHZ晶振 while(CLKCONSTA & 0x40); //等待晶振稳定为32M CLKCONCMD & ~0x47; //设置系统主时钟频率为32MHZ…

Python知识点20---池

提前说一点&#xff1a;如果你是专注于Python开发&#xff0c;那么本系列知识点只是带你入个门再详细的开发点就要去看其他资料了&#xff0c;而如果你和作者一样只是操作其他技术的Python API那就足够了。 如果看了我发的线程和进程的知识点的朋友&#xff0c;如果发散思维能…

面试(五)

目录 1. 知道大顶堆小顶端吗&#xff0c;代码怎么区分大顶端小顶端 2. 计算机中栈地址与内存地址增长方向相反吗&#xff1f; 3. %p和%d输出指针地址 4. 为什么定义第二个变量时候&#xff0c;地址反而减了 5. 12&#xff0c;32&#xff0c;64位中数据的占字节&#xff1f;…

物质的量质量,它们可不是一个概念

物质的量&质量&#xff0c;它们可不是一个概念。 物质的量&质量 乍一听物质的量&#xff0c;还以为是和质量有什么关系&#xff0c;是不是&#xff1f;其实物质的量和质量没什么直接的联系。 物质的量是国际单位制中7个基本物理量之一&#xff0c;其符号为n&#xf…

Aras Innovator-Team(群组)的使用方法

当Aras Innovator在处理权限时&#xff0c;在不使用Team的情况下&#xff0c;系统的权限配置可以满足大部分业务场景&#xff0c;如&#xff1a;常见的按照组织架构&#xff0c;成员和角色分配权限&#xff0c;按照生命周期分配权限等。 如果遇到比较复杂的权限需求&#xff0c…

AltiumDesigner/AD添加数据库连接

1.首先确保本机电脑有无对应的数据库驱动&#xff0c;例如我这边要添加MySQL的数据&#xff0c;则需要首先下载MySQL数据驱动&#xff1a;MySQL :: Download MySQL Connector/ODBC (Archived Versions) 2.运行“odbcad32.exe”&#xff0c;如下图添加对应的数据库配置&#xf…

SpringMVC:向三大域对象存数据

1. 简介 Servlet中的三个域对象 请求域&#xff1a;request会话域&#xff1a;session应用域&#xff1a;application 主要是通过&#xff1a;setAttribute getAttribute方法来完成在域中数据的传递和共享。 点击跳转Servlet详细概念 // 向域中存储数据 void setAttribute(St…

智能sql LLM

DB-GPT&#xff1a;彻底改变数据库与私有LLM技术的交互 智能SQL生成&#xff1a;后端技术与LLM的完美结合 智能SQL生成&#xff1a;后端技术与LLM的完美结合_llm sql-CSDN博客 GitHub - eosphoros-ai/DB-GPT: AI Native Data App Development framework with AWEL(Agentic Wor…

【C/C++】C/C++车辆交通违章管理系统(源码+数据文件)【独一无二】

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;公众号&#x1f448;&#xff1a;测试开发自动化【获取源码商业合作】 &#x1f449;荣__誉&#x1f448;&#xff1a;阿里云博客专家博主、5…

golang字符串实用函数库go-str-utils 之字符串命名转换 大小驼峰, snake, kebab命名转换

在go语言的开发中&#xff0c;字符串的处理是最为频繁的&#xff0c; 今天给大家介绍的这个 go-str-utils 专门的字符串处理实用函数库中的 字符串命名转换 大小驼峰&#xff0c; snake, kebab命名转换。 各种命名转换规则和示例 CamelStr 大驼峰 单词全部首字母大写 如: User…

[补题记录]LeetCode 167.两数之和 II - 输入有序数组

StarryCoding 是面向计算机专业学生的综合学习与刷题平台&#xff0c;欢迎同学们的加入&#xff01; 传送门&#xff1a;两数之和 II - 输入有序数组 Thought/思路 答案只需要返回两个下标&#xff0c;表示和为 target 的两个数。 我们可以用一个 map<int, vector> 维…

面试题:useEffect的Clean Up 什么时候触发?

​ useEffect作为做常用的Hook&#xff0c;以下三个知识点你有必要了解下~ 防止写出奇怪的代码祸害队友&#xff0c;而我不幸就是这个受害者&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; useEffect的依赖项为空 useEffect的dependencyList作为一个可选参数…

Pytest框架中用例用例执行常用参数介绍

pytest 支持通过命令行参数来定制测试运行的方式。以下是一些常用的 pytest 执行参数介绍。 学习目录 -q 或 --quiet: 安静模式&#xff0c;只显示进度和摘要 -s : 选项允许在测试的输出中捕获 stdout 和 stderr。 -v : 选项会使 pytest 的输出更加详细。 -k &#xff1a;…

Git 恢复已删除的branch

六一节晚上改了点code, 做完之后commit, 然后误删了这个branch, 并且新建了branch. 那么怎样恢复已删除的branch呢&#xff1f; 网上查询一番&#xff0c;找到了答案&#xff1a; 1. git reflog 找到被删的branch中最后一笔commit, 记录它的SHA1。 怎么看SHA1是被删除的bra…

鸿蒙应用Stage模型【应用/组件级配置】

应用/组件级配置 在开发应用时&#xff0c;需要配置应用的一些标签&#xff0c;例如应用的包名、图标等标识特征的属性。本文描述了在开发应用需要配置的一些关键标签。 应用包名配置 应用需要在工程的AppScope目录下的[app.json5配置文件]中配置bundleName标签&#xff0c;…

Python PyInstaller打包方法介绍

为了将开发好的Python工具交付给其他人使用&#xff0c;除了在目标电脑部署Python编译环境以外&#xff0c;我们还可以将它打包成可执行文件&#xff0c;这样目标电脑不需要安装Python环境就可以运行。将Python程序打包成可执行文件的方法有多种&#xff0c;比如Nuitka、PyInst…

【TB作品】msp430f5529单片机,读取DHT11温湿度,读取adc,oled显示

功能 msp430f5529单片机&#xff0c;读取DHT11温湿度&#xff0c;读取adc&#xff0c;oled显示 硬件 //OLED引脚分配 绿色板子 //DO(SCLK)------P4.3 //D1(DATA)------P4.0 //RES-----------P3.7 //DC------------P8.2 //CS------------P8.1 //mq135 P6.5 //DHT11 P4.1 部…

如何使用Python获取图片中的文字信息

如下有三中方法&#xff1a; 方法1. 使用Tesseract OCR&#xff08;pytesseract&#xff09; 安装依赖 首先&#xff0c;确保你已经安装了Tesseract OCR引擎&#xff08;例如&#xff0c;通过你的操作系统的包管理器&#xff09;。然后&#xff0c;你可以通过pip安装pytesse…

微博增强-tampermonkey脚本实现网页管理悄悄关注

不是很明白微博为什么不出个x的列表功能&#xff0c;毕竟现在信息洪流&#xff0c;有些东西只是要看要了解&#xff0c;但不希望天天在首页轰炸眼睛&#xff0c;扰乱心智。 这个tampermonkey脚本适配了pc web和手机pwa版本&#xff08;weibo.com/m.weibo.cn&#xff09;,解决了…

golang map部分原理源码个人走读-附个人理解过程图解

近期再写map的demo时出现了下面一段报错&#xff0c;于是带着疑惑去看了一下源码 目的&#xff1a;主要想知道为啥map不让并发读写 fatal error: concurrent map read and map write 一.map的数据结构 先有个印象&#xff0c;后续会详细介绍 // A header for a Go map. ty…