【ROS】—— 机器人系统仿真 —URDF语法 (十三)

news2024/11/23 20:59:19

文章目录

  • 前言
  • 1. 概述
    • 1.1 概念
    • 1.2 作用
    • 1.3 相关组件
      • 1.3.1 URDF
      • 1.3.2 RViz
      • 1.3.3 gazebo
    • 1.4 准备
  • 2. URDF集成Rviz基本流程
    • 2.1 创建功能包,导入依赖
    • 2.2 编写 URDF 文件
    • 2.3 在 launch 文件中集成 URDF 与 Rviz
  • 3. URDF语法详解
    • 3.1 robot
    • 3.2 link
    • 3.3 joint
    • 3.4 URDF练习
    • 3.5 URDF工具
      • 3.5.1 check_urdf 语法检查
      • 3.5.2 urdf_to_graphiz 结构查看

前言

📢本系列将依托赵虚左老师的ROS课程,写下自己的一些心得与笔记。
📢课程链接:https://www.bilibili.com/video/BV1Ci4y1L7ZZ
📢讲义链接:http://www.autolabor.com.cn/book/ROSTutorials/index.html
📢 文章可能存在疏漏的地方,恳请大家指出。

1. 概述

1.1 概念

机器人系统仿真:是通过计算机对实体机器人系统进行模拟的技术,在 ROS 中,仿真实现涉及的内容主要有三:对机器人建模(URDF)创建仿真环境(Gazebo) 以及 感知环境(Rviz) 等系统性实现。

1.2 作用

仿真优势仿真缺陷
低成本:当前机器人成本居高不下,动辄几十万,仿真可以大大降低成本,减小风险仿真器所使用的物理引擎目前还不能够完全精确模拟真实世界的物理情况
高效:搭建的环境更为多样且灵活,可以提高测试效率以及测试覆盖率仿真器构建的是关节驱动器(电机&齿轮箱)、传感器与信号通信的绝对理想情况,目前不支持模拟实际硬件缺陷或者一些临界状态等情形
高安全性:仿真环境下,无需考虑耗损问题

1.3 相关组件

1.3.1 URDF

URDF是 Unified Robot Description Format 的首字母缩写,直译为统一(标准化)机器人描述格式,可以以一种 XML 的方式描述机器人的部分结构,比如底盘、摄像头、激光雷达、机械臂以及不同关节的自由度…,该文件可以被 C++ 内置的解释器转换成可视化的机器人模型,是 ROS 中实现机器人仿真的重要组件

1.3.2 RViz

RViz 是 ROS Visualization Tool 的首字母缩写,直译为ROS的三维可视化工具。它的主要目的是以三维方式显示ROS消息,可以将 数据进行可视化表达。例如:可以显示机器人模型,可以无需编程就能表达激光测距仪(LRF)传感器中的传感 器到障碍物的距离,RealSense、Kinect或Xtion等三维距离 传感器的点云数据(PCD, Point Cloud Data),从相机获取的图像值等

1.3.3 gazebo

Gazebo是一款3D动态模拟器,用于显示机器人模型并创建仿真环境,能够在复杂的室内和室外环境中准确有效地模拟机器人。与游戏引擎提供高保真度的视觉模拟类似,Gazebo提供高保真度的物理模拟,其提供一整套传感器模型,以及对用户和程序非常友好的交互方式。

1.4 准备

将素材下载至文件夹内

git clone https://github.com/zx595306686/sim_demo.git

包含3个文件
在这里插入图片描述

2. URDF集成Rviz基本流程

需求描述:
在 Rviz 中显示一个盒状机器人

实现流程:

  • 准备:新建功能包,导入依赖

  • 核心:编写 urdf 文件

  • 核心:在 launch 文件集成 URDF 与 Rviz

  • 在 Rviz 中显示机器人模型

2.1 创建功能包,导入依赖

创建一个新的功能包,名称自定义,导入依赖包:urdfxacro

在当前功能包下,再新建几个目录:

  • urdf: 存储 urdf 文件的目录
  • meshes:机器人模型渲染文件,机器人的皮肤(暂不使用)
  • config: 配置文件
  • launch: 存储 launch 启动文件

2.2 编写 URDF 文件

如图所示创建文件
在这里插入图片描述
demo01_helloworld.urdf

<robot name="mycar">
    <link name="base_link">
        <visual>
            <geometry>
                <box size="0.5 0.2 0.1" />
            </geometry>
        </visual>
    </link>
</robot>

2.3 在 launch 文件中集成 URDF 与 Rviz

demo01_helloworld.launch

<launch> 
    <!--在参数服务器载入URDF文件 -->
    <param name = "robot_description" textfile = "$(find urdf01_rviz)/urdf/urdf/demo01_helloworld.urdf"/> 
    <!--启动rviz -->
    <node pkg = "rviz" type = "rviz" name="rviz"/>
</launch>

robot_description是固定的
在这里插入图片描述
Fixed Frame具体设置参考URDF文件具体实现

重复启动launch文件时,Rviz 之前的组件配置信息不会自动保存,需要重复执行步骤4的操作,为了方便使用,可以使用如下方式优化:
1.首先,将当前配置保存进config目录
2.然后,launch文件中 Rviz 的启动配置添加参数:args,值设置为-d 配置文件路径
在这里插入图片描述

<launch> 
    <!--在参数服务器载入URDF文件 -->
    <param name = "robot_description" textfile = "$(find urdf01_rviz)/urdf/urdf/demo01_helloworld.urdf"/> 
    <!--启动rviz -->
    <node pkg = "rviz" type = "rviz" name="rviz" args="-d $(find urdf01_rviz)/config/demo01.rviz"/>
</launch>

3. URDF语法详解

URDF 文件是一个标准的 XML 文件,在 ROS 中预定义了一系列的标签用于描述机器人模型,机器人模型可能较为复杂,但是 ROS 的 URDF 中机器人的组成却是较为简单,可以主要简化为两部分:连杆(link标签)关节(joint标签),接下来我们就通过案例了解一下 URDF 中的不同标签:

  • robot 根标签,类似于 launch文件中的launch标签
  • link 连杆标签
  • joint 关节标签
  • gazebo 集成gazebo需要使用的标签

关于gazebo标签,后期在使用 gazebo 仿真时,才需要使用到,用于配置仿真环境所需参数,比如: 机器人材料属性、gazebo插件等,但是该标签不是机器人模型必须的,只有在仿真时才需设置

3.1 robot

urdf 中为了保证 xml 语法的完整性,使用了robot标签作为根标签,所有的 link 和 joint 以及其他标签都必须包含在 robot 标签内,在该标签内可以通过 name 属性设置机器人模型的名称

1.属性
name: 指定机器人模型的名称

2.子标签
其他标签都是子级标签

3.2 link

urdf 中的 link 标签用于描述机器人某个部件(也即刚体部分)的外观和物理属性,比如: 机器人底座、轮子、激光雷达、摄像头…每一个部件都对应一个 link, 在 link 标签内,可以设计该部件的形状、尺寸、颜色、惯性矩阵、碰撞参数等一系列属性

在这里插入图片描述
1.属性
name —> 为连杆命名

2.子标签

  • - visual —> 描述外观(对应的数据是可视的)
标签名称说明子标签属性
geometry 设置连杆的形状box(盒状)size=长(x) 宽(y) 高(z)
cylinder(圆柱)radius=半径 length=高度
sphere(球体)radius=半径
mesh(为连杆添加皮肤) filename=资源路径(格式:package:/// /文件)
origin 设置偏移量与倾斜弧度xyzx偏移 y便宜 z偏移
rpyx翻滚 y俯仰 z偏航 (单位是弧度)
metrial 设置材料属性(颜色)colorrgba=红绿蓝权重值与透明度 (每个权重值以及透明度取值[0,1])
  • collision —> 连杆的碰撞属性
  • Inertial —> 连杆的惯性矩阵

需求:分别生成长方体、圆柱与球体的机器人部件

demo02_link.urdf

<!-- 设置不同形状的机器人部件-->
<robot name  = "my_robot">
    <link name = "base_link">
        <!-- 可视化标签-->
        <visual>
            <!-- 形状-->
            <geometry>
                <!-- 1.立方体-->
                    <!-- <box size="0.3 0.4 0.5"/> -->
                <!-- 2.圆柱-->
                    <!-- <cylinder radius="0.5" length="1.0"/> -->
                <!-- 3.球体-->
                    <!-- <sphere radius="0.5"/> -->
                <!-- 皮肤-->
                    <mesh filename="package://urdf01_rviz/meshes/autolabor_mini.stl"/>
            </geometry>
            <!-- 偏移量与倾斜弧度-->
                <!--
                     xyz 设置偏移量
                     rpy设置倾斜弧度
                -->
                <origin xyz = "0 0 0" rpy="1.57 0 1.57"/>
            <!-- 颜色-->
                <material name="robot_color">
                    <color rgba="1 0 1 1"/>
                </material>
        </visual>
    </link>

</robot>

demo02_link.launch

<launch> 
    <!--在参数服务器载入URDF文件 -->
    <param name = "robot_description" textfile = "$(find urdf01_rviz)/urdf/urdf/demo02_link.urdf"/> 
    <!--启动rviz -->
    <node pkg = "rviz" type = "rviz" name="rviz" args="-d $(find urdf01_rviz)/config/demo01.rviz"/>
</launch>

长方体
在这里插入图片描述圆柱
在这里插入图片描述

球体
在这里插入图片描述

皮肤
在这里插入图片描述偏移
在这里插入图片描述旋转
在这里插入图片描述颜色
在这里插入图片描述

3.3 joint

urdf 中的 joint 标签用于描述机器人关节的运动学动力学属性还可以指定关节运动的安全极限,机器人的两个部件(分别称之为 parent link 与 child link)以"关节"的形式相连接,不同的关节有不同的运动形式: 旋转、滑动、固定、旋转速度、旋转角度限制…,比如:安装在底座上的轮子可以360度旋转,而摄像头则可能是完全固定在底座上。

joint标签对应的数据在模型中是不可见的

在这里插入图片描述
1.属性

  • name —> 为关节命名
  • type —> 关节运动形式
    • continuous: 旋转关节,可以绕单轴无限旋转
    • revolute: 旋转关节,类似于 continues,但是有旋转角度限制
    • prismatic: 滑动关节,沿某一轴线移动的关节,有位置极限
    • planer: 平面关节,允许在平面正交方向上平移或旋转
    • floating: 浮动关节,允许进行平移、旋转运动
    • fixed: 固定关节,不允许运动的特殊关节

2.子标签

  • parent(必需的)
    parent link的名字是一个强制的属性

    • link:父级连杆的名字,是这个link在机器人结构树中的名字。
  • child(必需的)
    child link的名字是一个强制的属性

    • link:子级连杆的名字,是这个link在机器人结构树中的名字。
  • origin

    • 属性: xyz=各轴线上的偏移量 rpy=各轴线上的偏移弧度。
  • axis

    • 属性: xyz用于设置围绕哪个关节轴运动。

需求:创建机器人模型,底盘为长方体,在长方体的前面添加一摄像头,摄像头可以沿着 Z 轴 360 度旋转。

demo03_joint.urdf

<!-- 设置机器人底盘 并添加摄像头-->
<robot name = "my_robot">
    <!-- 底盘link-->
    <link name = "base_link">
        <visual>
            <geometry>
                <box size="0.3 0.2 0.1"/>
            </geometry>
            <origin xyz = "0 0 0" rpy="0 0 0"/>
            <material name="camera_color">
                <color rgba="1 0 0 1"/>
            </material>
        </visual>
    </link> 
    <!--摄像头link-->
        <link name = "camera">
        <visual>
            <geometry>
                <box size="0.02 0.05 0.05"/>
            </geometry>
            <origin xyz = "0 0 0" rpy="0 0 0"/>
            <material name="robot_color">
                <color rgba="0 0 1 1"/>
            </material>
        </visual>
    </link> 
    <!-- 关节 -->
    <joint name="camera2baselink" type="continuous">
        <!-- 父级节点-->
        <parent link = "base_link"/>
        <!-- 子级节点-->
        <child link = "camera" />
        <!-- 需要计算两个 link 的物理中心之间的偏移量 -->
        <origin xyz="0.2 0 0.075" rpy="0 0 0" />
        <!-- 确定旋转的轴-->
        <axis xyz="0 0 1" />
    </joint>
</robot>

demo03_joint.launch

<launch> 
    <!--在参数服务器载入URDF文件 -->
    <param name = "robot_description" textfile = "$(find urdf01_rviz)/urdf/urdf/demo03_joint.urdf"/> 
    <!--启动rviz -->
    <node pkg = "rviz" type = "rviz" name="rviz" args="-d $(find urdf01_rviz)/config/demo01.rviz"/>
</launch>

运行出现了这样的问题,但改正之后未能复现,可能是urdf文件一些细节的地方出了问题.

[ERROR] [1673507658.550707801]: Failed to build tree: Joint [camera2baselink] is missing a parent and/or child link specification.

roslauch 运行后,出现以下问题No transform from [camera] to [base_link]
在这里插入图片描述
launch文件改为:

<launch> 
    <!--在参数服务器载入URDF文件 -->
    <param name = "robot_description" textfile = "$(find urdf01_rviz)/urdf/urdf/demo03_joint.urdf"/> 
    <!--启动rviz -->
    <node pkg = "rviz" type = "rviz" name="rviz" args="-d $(find urdf01_rviz)/config/demo01.rviz"/>
    <!-- 添加关节状态发布节点 -->
    <node pkg="joint_state_publisher" type="joint_state_publisher" name="joint_state_publisher" />
    <!-- 添加机器人状态发布节点 -->
    <node pkg="robot_state_publisher" type="robot_state_publisher" name="robot_state_publisher" />
</launch>

若还报错,去掉URDF文件里的中文注释

<robot name = "my_robot">
    <link name = "base_link">
        <visual>
            <geometry>
                <box size="0.3 0.2 0.1"/>
            </geometry>
            <origin xyz = "0 0 0" rpy="0 0 0"/>
            <material name="camera_color">
                <color rgba="1 0 0 1"/>
            </material>
        </visual>
    </link> 
        <link name = "camera">
        <visual>
            <geometry>
                <box size="0.02 0.05 0.05"/>
            </geometry>
            <origin xyz = "0 0 0" rpy="0 0 0"/>
            <material name="robot_color">
                <color rgba="0 0 1 1"/>
            </material>
        </visual>
    </link> 
    <joint name="camera2baselink" type="continuous">
        <parent link = "base_link"/>
        <child link = "camera" />
        <origin xyz="0.12 0 0.075" rpy="0 0 0" />
        <axis xyz="0 0 1" />
    </joint>
</robot>

在这里插入图片描述注意: joint的位置是以摄像头中心点为标准的.

接下来控制摄像头的旋转

sudo apt-get install ros-melodic-joint-state-publisher-gui 
<launch> 
    <!--在参数服务器载入URDF文件 -->
    <param name = "robot_description" textfile = "$(find urdf01_rviz)/urdf/urdf/demo03_joint.urdf"/> 
    <!--启动rviz -->
    <node pkg = "rviz" type = "rviz" name="rviz" args="-d $(find urdf01_rviz)/config/demo01.rviz"/>
    <!-- 添加关节状态发布节点 -->
    <node pkg="joint_state_publisher" type="joint_state_publisher" name="joint_state_publisher" />
    <!-- 添加机器人状态发布节点 -->
    <node pkg="robot_state_publisher" type="robot_state_publisher" name="robot_state_publisher" />
    <!-- 可选:用于控制关节运动的节点 -->
    <node pkg="joint_state_publisher_gui" type="joint_state_publisher_gui" name="joint_state_publisher_gui" />

</launch>

若产生抖动,注释掉joint_state_publisher
在这里插入图片描述base_footprint优化urdf
前面实现的机器人模型是半沉到地下的,因为默认情况下: 底盘的中心点位于地图原点上,所以会导致这种情况产生,可以使用的优化策略,将初始 link 设置为一个尺寸极小的 link(比如半径为 0.001m 的球体,或边长为 0.001m 的立方体),然后再在初始 link 上添加底盘等刚体,这样实现,虽然仍然存在初始link半沉的现象,但是基本可以忽略了。这个初始 link 一般称之为 base_footprint

<robot name = "my_robot">

    <link name = "base_footprint">
        <visual>
            <geometry>
                <box size="0.001 0.001 0.001"/>
            </geometry>
            <origin xyz = "0 0 0" rpy="0 0 0"/>
            <material name="color1">
                <color rgba="0 1 1 1"/>
            </material>
        </visual>
    </link> 

    <link name = "base_link">
        <visual>
            <geometry>
                <box size="0.3 0.2 0.1"/>
            </geometry>
            <origin xyz = "0 0 0" rpy="0 0 0"/>
            <material name="robot_color">
                <color rgba="1 0 0 1"/>
            </material>
        </visual>
    </link> 

        <link name = "camera">
        <visual>
            <geometry>
                <box size="0.02 0.05 0.05"/>
            </geometry>
            <origin xyz = "0 0 0" rpy="0 0 0"/>
            <material name="camera_color">
                <color rgba="0 0 1 1"/>
            </material>
        </visual>
    </link> 

    <joint name="baselink2basefootprint" type="fixed">
        <parent link = "base_footprint"/>
        <child link = "base_link" />
        <origin xyz="0 0 0.05" rpy="0 0 0" />
        <axis xyz="0 0 0" />
    </joint>

    <joint name="camera2baselink" type="continuous">
        <parent link = "base_link"/>
        <child link = "camera" />
        <origin xyz="0.12 0 0.075" rpy="0 0 0" />
        <axis xyz="0 0 1" />
    </joint>

</robot>

base_link 改为 base_footprint
在这里插入图片描述

3.4 URDF练习

需求描述:

创建一个四轮圆柱状机器人模型,机器人参数如下,底盘为圆柱状,半径 10cm,高 8cm,四轮由两个驱动轮和两个万向支撑轮组成,两个驱动轮半径为 3.25cm,轮胎宽度1.5cm,两个万向轮为球状,半径 0.75cm,底盘离地间距为 1.5cm(与万向轮直径一致)

PS:连杆之间的偏移最好在joint上进行.

demo05_test.urdf

<robot name = "my_robot">

    <link name = "base_footprint">
        <visual>
            <geometry>
                <box size="0.001 0.001 0.001"/>
            </geometry>
            <origin xyz = "0 0 0" rpy="0 0 0"/>
            <material name="color1">
                <color rgba="0 1 1 1"/>
            </material>
        </visual>
    </link> 

    <link name = "base_link">
        <visual>
            <geometry>
                <cylinder radius = "0.1" length="0.08"/>
            </geometry>
            <origin xyz = "0 0 0" rpy="0 0 0"/>
            <material name="robot_color">
                <color rgba="0.2 0.2 0.2 1"/>
            </material>
        </visual>
    </link> 

    <joint name="baselink2basefootprint" type="fixed">
        <parent link = "base_footprint"/>
        <child link = "base_link" />
        <origin xyz="0 0 0.055" rpy="0 0 0" />
        <axis xyz="0 0 0" />
    </joint>

    <link name = "left_wheel">
        <visual>
            <geometry>
                <cylinder radius = "0.0325" length="0.015"/>
            </geometry>
            <origin xyz = "0 0 0" rpy="1.5705 0 0"/>
            <material name="wheel_color">
                <color rgba="0 0 0 1"/>
            </material>
        </visual>
    </link> 

    <joint name="leftwheel2baselink" type="continuous">
        <parent link = "base_link"/>
        <child link = "left_wheel" />
        <origin xyz="0 0.1 -0.0225" />
        <axis xyz="0 1 0" />
    </joint>

    <link name = "right_wheel">
        <visual>
            <geometry>
                <cylinder radius = "0.0325" length="0.015"/>
            </geometry>
            <origin xyz = "0 0 0" rpy="1.5705 0 0"/>
            <material name="wheel_color">
                <color rgba="0 0 0 1"/>
            </material>
        </visual>
    </link> 

    <joint name="rightwheel2baselink" type="continuous">
        <parent link = "base_link"/>
        <child link = "right_wheel" />
        <origin xyz="0 -0.1 -0.0225" />
        <axis xyz="0 1 0" />
    </joint>

    <link name = "front_wheel">
        <visual>
            <geometry>
                <sphere radius="0.0075" />
            </geometry>
            <origin xyz = "0 0 0" rpy="0 0 0"/>
            <material name="wheel_color">
                <color rgba="0 0 0 1"/>
            </material>
        </visual>
    </link> 

    <joint name="frontwheel2baselink" type="continuous">
        <parent link = "base_link"/>
        <child link = "front_wheel" />
        <origin xyz="0.0925 0 -0.0475" />
        <axis xyz="1 1 1" />
    </joint>

    <link name = "back_wheel">
        <visual>
            <geometry>
                <sphere radius="0.0075" />
            </geometry>
            <origin xyz = "0 0 0" rpy="0 0 0"/>
            <material name="wheel_color">
                <color rgba="0 0 0 1"/>
            </material>
        </visual>
    </link> 

    <joint name="backwheel2baselink" type="continuous">
        <parent link = "base_link"/>
        <child link = "back_wheel" />
        <origin xyz="-0.0925 0 -0.0475" />
        <axis xyz="1 1 1" />
    </joint>
</robot>

demo05_test.launch

<launch> 
    <!--在参数服务器载入URDF文件 -->
    <param name = "robot_description" textfile = "$(find urdf01_rviz)/urdf/urdf/demo05_test.urdf"/> 
    <!--启动rviz -->
    <node pkg = "rviz" type = "rviz" name="rviz" args="-d $(find urdf01_rviz)/config/demo01.rviz"/>
    <!-- 添加关节状态发布节点 -->
    <node pkg="joint_state_publisher" type="joint_state_publisher" name="joint_state_publisher" />
    <!-- 添加机器人状态发布节点 -->
    <node pkg="robot_state_publisher" type="robot_state_publisher" name="robot_state_publisher" />
    <!-- 可选:用于控制关节运动的节点 -->
    <node pkg="joint_state_publisher_gui" type="joint_state_publisher_gui" name="joint_state_publisher_gui" />

</launch>

在这里插入图片描述在这里插入图片描述

3.5 URDF工具

在 ROS 中,提供了一些工具来方便 URDF 文件的编写,比如:

  • check_urdf命令可以检查复杂的 urdf 文件是否存在语法问题
  • urdf_to_graphiz命令可以查看 urdf 模型结构,显示不同 link 的层级关系

当然,要使用工具之前,首先需要安装,安装命令:sudo apt install liburdfdom-tools

3.5.1 check_urdf 语法检查

进入urdf文件所属目录,调用:check_urdf urdf文件,如果不抛出异常,说明文件合法,否则非法

合法

yuan@yuan-Legion-Y9000P-IAH7H:~/catkin_ws/src/urdf01_rviz/urdf/urdf$ check_urdf demo05_test.urdf 
robot name is: my_robot
---------- Successfully Parsed XML ---------------
root Link: base_footprint has 1 child(ren)
    child(1):  base_link
        child(1):  back_wheel
        child(2):  front_wheel
        child(3):  left_wheel
        child(4):  right_wheel

3.5.2 urdf_to_graphiz 结构查看

进入urdf文件所属目录,调用:urdf_to_graphiz urdf文件,当前目录下会生成 pdf 文件

yuan@yuan-Legion-Y9000P-IAH7H:~/catkin_ws/src/urdf01_rviz/urdf/urdf$ urdf_to_graphiz demo05_test.urdf 
Created file my_robot.gv
Created file my_robot.pdf

在这里插入图片描述

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

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

相关文章

Lock锁原理解析【Android进阶】

Lock锁原理解析【Android进阶】 Lock简介 Lock接口位于J.U.C下locks包内&#xff0c;其定义了Lock应该具备的方法。 Lock 方法签名&#xff1a; void lock()&#xff1a;获取锁&#xff08;不死不休&#xff0c;拿不到就一直等&#xff09;boolean tryLock()&#xff1a;获…

13.0、Linux-安装Tomcat、以及防火墙常用命令

13.0、Linux-安装Tomcat、以及防火墙常用命令 防火墙常用命令在本文最下方-> 安装 Tomcat -> 第一步&#xff1a;进入官网下载 Tomcat8 -> Apache Tomcat - Apache Tomcat 8 Software Downloads 第二步&#xff1a;将下载好的文件 通过 Xshell 和 Xftp 工具上传到 L…

前端面试题——React重点

文章目录React相关问题1. 函数式组件与Class组件有什么不同&#xff1f;2. 说说React的fiber架构&#xff1f;3. 协调4. 虚拟DOM (Virtual DOM)React相关问题 1. 函数式组件与Class组件有什么不同&#xff1f; 答&#xff1a; ① 函数式组件不需要继承&#xff0c;直接 “fun…

YUV 文件读取、显示、缩放、裁剪等操作教程

系列文章目录 文章目录系列文章目录前言一、Chroma subsampling二、读取 YUV 文件2.1 准备工作2.2 Planar 模式2.2.1 YUV420P 格式读取2.2.2 YUV422P 格式读取2.2.3 NV21 格式读取2.2.4 NV12 格式读取2.2.5 小结2.3 Packed 模式2.3.1 YUYV 格式读取2.3.2 小结三、SDL 显示 YUV …

自动化测试是什么?为什么要做自动化测试?

自动化测试是什么&#xff1f;相信对软件测试有一定了解的朋友都不会感到陌生。自动化测试正如字面上理解得那样&#xff0c;是一种自动完成测试工作的测试方式。虽然是说的自动化&#xff0c;但是也是需要测试员手动编写代码去完成测试工作。那么&#xff0c;为什么要做自动化…

【链表】leetcode19.删除链表的倒数第N个节点(C/C++/Java/Js)

leetcode19.删除链表的倒数第N个节点1 题目2 思路3 代码3.1 C版本3.2 C版本3.3 Java版本3.4 JavaScript版本4 总结1 题目 题源链接 给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff0c;并且返回链表的头结点。 示例 1&#xff1a; 输入&#xff1a;head [1,2…

微服务了解

1、什么是微服务 微服务就是根据业务功能模块把一个单体的应用拆分成许多个独立的项目&#xff0c;每个项目完成一部分的业务功能&#xff0c;然后独立开发和部署。这些独立的项目就成为一个微服务。进而构成一个服务集群。 微服务个人理解就是将之前的单一服务架构&#xff…

【Python】词云之wordcloud参数全解析

写了一半&#xff0c;明天继续 目录一基础用法二、WordCloud类形参说明2.1 常用参数2.11 字体 font_path2.12 画布尺寸 width、hight2.13 比例&#xff08;缩放&#xff09;scale2.14 颜色 colormap2.15 颜色color_func2.16 组合频率collocations2.17 遮罩&#xff08;蒙版&…

SpringBoot(57) 整合Plumelog实现日志查询

文章目录一、前言二、docker-compose一键搭建日志服务docker-compose.yml三、SpringBoot整合Plumelog1、pom.xml2、application.yml3、logback-spring.xml4、启动项目记录日志四、本文案例demo源码一、前言 Plumelog 一个简单易用的java分布式日志组件 https://gitee.com/plum…

机器学习笔记之深度信念网络(三)贪心逐层预训练算法

机器学习笔记之深度信念网络——贪心逐层预训练算法引言回顾&#xff1a;深度信念网络的结构表示回顾&#xff1a;RBM\text{RBM}RBM叠加思想贪心逐层预训练算法引言 上一节介绍了深度信念网络模型的构建思想&#xff0c;本节将介绍后验概率求解——贪心逐层预训练算法。 回顾…

窥探Swift源码下的Array

本文字数&#xff1a;6730字预计阅读时间&#xff1a;15 分钟用最通俗的语言&#xff0c;描述最难懂的技术前情提要我在之前的文章一次遍历导致的崩溃中提到了&#xff0c;如果有机会会把相关的Swift集合源码阅读。首先对自己的开发和知识储备会有进一步的升华&#xff0c;另外…

Redis -- IO多路复用及redis6的多线程

都知道redis是通过单线程io多路复用来避免并发问题的&#xff0c;然后在redis6的时候redis引入了多线程&#xff0c;这里就来详细说说IO多路复用模型以及redis的多线程。 Redis 的 I/O 多路复用模型有效的解决单线程的服务端&#xff0c;使用不阻塞方式处理多个 client 端请求…

optional妙用解决NullPointerException

背景 作为一个java程序员&#xff0c;我们在日常开发中经常会碰到一个臭名昭著空异常&#xff0c;所有程序员都经历过的痛点&#xff0c;空指针异常&#xff08;NullPointerException&#xff09; java8中出现的Optional是java开始迈向函数式编程的一大步&#xff0c;也有效的…

实验 4 图像复原与重建

目录一、实验目的二、实验例题1. 噪声模型2. 只存在噪声的滤波——空间滤波3. 退化函数建模4. 存在线性退化和噪声的滤波(1) 逆滤波(2) 最小均方误差(维纳)滤波附录一、实验目的 了解一些常用随机噪声的生成方法。掌握根据指定退化函数对图像进行退化的方法。掌握当模糊图像只…

十一、Gtk4-Instance Initialization and destruction

文本文件编辑器(tfe)的新版本将在本节和以下四节中编写。它是tfe5。与之前的版本相比&#xff0c;有很多变化。它们位于两个目录中&#xff0c;src/tfe5和src/tfetextview。 1 封装 我们将C源文件分为两部分。但就封装而言&#xff0c;这还不够。 tfe.c包含除Tfe TextView之…

【Linux】线程控制

目录&#x1f308;前言&#x1f338;1、Linux线程控制&#x1f361;1.1、创建线程(pthread_create)&#x1f362;1.2、通过指令查看线程PID和LWP&#x1f367;1.3、获取线程ID(pthread_self)&#x1f368;1.4、线程终止(pthread_exit/cancel)&#x1f368;1.5、线程等待(pthrea…

一文读懂PCB阻焊工艺

PCB阻焊油墨根据固化方式&#xff0c;阻焊油墨有感光显影型的油墨&#xff0c;有热固化的热固油墨&#xff0c;还有UV光固化的UV油墨。而根据板材分类&#xff0c;又有PCB硬板阻焊油墨&#xff0c;FPC软板阻焊油墨&#xff0c;还有铝基板阻焊油墨&#xff0c;铝基板油墨也可以用…

力扣算法(Java实现)—数组入门(11题)

文章目录1.删除排序数组中的重复项2.买卖股票的最佳时机 II3.旋转数组4.存在重复元素5.找出只出现一次的元素6.两个数组的交集7.移动零8.加一9.两数之和10.有效的数独11.旋转图像&#x1f48e;&#x1f48e;&#x1f48e;&#x1f48e;&#x1f48e; 更多资源链接&#xff0c;欢…

【手写 Vue2.x 源码】第十八篇 - 根据 render 函数,生成 vnode

一&#xff0c;前言 上篇&#xff0c;介绍了render 函数的生成&#xff0c;主要涉及以下两点&#xff1a; 使用 with 对生成的 code 进行一次包装将包装后的完整 code 字符串&#xff0c;通过 new Function 输出为 render 函数 本篇&#xff0c;根据 render 函数&#xff0c…

linux系统中QT里面的视频播放器的实现方法

大家好&#xff0c;今天主要和大家聊一聊&#xff0c;如何使用QT中视频播放器的方法。 目录 第一&#xff1a;视频播放器基本简介 第二&#xff1a;视频播放器头文件说明 第三&#xff1a;源文件的具体实现方法 第四&#xff1a;运行效果显示 第一&#xff1a;视频播放器基本…