Jetson nano 之 ROS入门 - - 机器人坐标变换

news2024/11/27 4:17:48

文章目录

  • 前言
  • 一、空间坐标变换原理
    • 1. 位姿描述
    • 2. 欧拉角与四元数
  • 二、ROS中python实现坐标变换
    • 1. 坐标msg消息载体
    • 2. 乌龟跟随的程序实现
  • 总结


前言

在这里插入图片描述

ROS给开发者们提供了很多集成度很高的开发工具,例如rviz和gazebo。rviz是三维可视化工具,可以显示图像、模型、路径等信息,但是前提都是这些数据已经以话题、参数的形式发布,rviz做的事情就是订阅这些数据,并完成可视化的渲染,这次博主主要依托rviz的三维平台,学习坐标变换和机器人三维建模


一、空间坐标变换原理

1. 位姿描述

学习位姿描述之前首先要了解矩阵的本质。如果我们将矩阵和函数联想起来,将它理解成一种映射变化,那么矩阵的本质是在描述一种对基向量的空间变换,而行列式表达的正好是基向量变换后围成的面积

在这里插入图片描述

i \boldsymbol{i} i j \boldsymbol{j} j 是成形二维平面的最简单的一对基,而矩阵关注的就是对这两对基向量的线性变换,一种类似于函数的作用
a ⃗ = f ( b ⃗ ) \vec{a} = f(\vec{b}) a =f(b )

比如, [ i j ] \left[ \begin{array}{ccc} i \\ j \end{array} \right ] [ij] 这个基经过 [ 3 2 − 2 1 ] \left[ \begin{array}{ccc} 3 & 2\\ -2 & 1 \end{array} \right ] [3221] 的映射, i i i 变成了 ( 3 , − 2 ) (3,-2) (3,2) 这个新的基向量, j j j 变为 ( 2 , 1 ) (2,1) (2,1) 这个新的基向量,整个二维平面就发生了如下变化:
在这里插入图片描述
我们将变化后的2个基向量按如下方式放入矩阵,这样这个矩阵 [ 3 2 − 2 1 ] \left[ \begin{array}{ccc} 3 & 2\\ -2 & 1 \end{array} \right ] [3221] 就表示了一次对二维空间的变换映射,其中的2个列分别为经过变换后的 i \boldsymbol{i} i j \boldsymbol{j} j

我们来讲讲位姿,位姿代表位置和姿态。任何一个刚体在空间坐标系 O X Y Z OXYZ OXYZ 中可以用位置和姿态来精确、唯一地表示其位置状态。对于直角坐标系{A},空间任一点 p p p 的位置可以用3x1的列矢量 A P ^{A}P AP 来表示。
A P = [ p x p y p z ] ^{A}P = \left[ \begin{array}{ccc} p_{x}\\ p_{y}\\ p_{z} \end{array} \right ] AP= pxpypz

在这里插入图片描述
假设主坐标系为 A {A} A ,我们用 X B ˆ 、 Y B ˆ 、 Z B ˆ \^{X_{B}}、\^{Y_{B}}、\^{Z_{B}} XBˆYBˆZBˆ来表示另一个坐标系 B {B} B 三个轴的单位向量,则坐标系 B {B} B 相对于坐标系 A {A} A 的旋转矩阵可以表达为 B A R = ( A X B ˆ A Y B ˆ A Z B ˆ ) = [ X B ˆ ∙ X A ˆ Y B ˆ ∙ X A ˆ Z B ˆ ∙ X A ˆ X B ˆ ∙ Y A ˆ Y B ˆ ∙ Y A ˆ Y B ˆ ∙ Y A ˆ X B ˆ ∙ Z A ˆ Y B ˆ ∙ Z A ˆ Z B ˆ ∙ Z A ˆ ] _{B}^{A}R = ( ^{A}\^{X_{B}} ^{A}\^{Y_{B}} ^{A}\^{Z_{B}} ) = \left[ \begin{array}{ccc} \^{X_{B}} ∙ \^{X_{A}} & \^{Y_{B}} ∙ \^{X_{A}} & \^{Z_{B}} ∙ \^{X_{A}}\\ \^{X_{B}} ∙ \^{Y_{A}} & \^{Y_{B}} ∙ \^{Y_{A}}& \^{Y_{B}} ∙ \^{Y_{A}}\\ \^{X_{B}} ∙ \^{Z_{A}} & \^{Y_{B}} ∙ \^{Z_{A}} & \^{Z_{B}} ∙ \^{Z_{A}} \end{array} \right ] BAR=(AXBˆAYBˆAZBˆ)= XBˆXAˆXBˆYAˆXBˆZAˆYBˆXAˆYBˆYAˆYBˆZAˆZBˆXAˆYBˆYAˆZBˆZAˆ

按照刚刚我们理解的矩阵的本质, X A ˆ \^{X_{A}} XAˆ 被矩阵映射后,变成单位向量 X B ˆ \^{X_{B}} XBˆ X A ˆ 、 Y A ˆ 、 Z A ˆ \^{X_{A}}、\^{Y_{A}}、\^{Z_{A}} XAˆYAˆZAˆ 三个基向量上的投影,合成后刚刚好是 X B ˆ \^{X_{B}} XBˆ Y A ˆ \^{Y_{A}} YAˆ 被矩阵映射后,变成单位向量 Y B ˆ \^{Y_{B}} YBˆ X A ˆ 、 Y A ˆ 、 Z A ˆ \^{X_{A}}、\^{Y_{A}}、\^{Z_{A}} XAˆYAˆZAˆ 三个基向量上的投影,合成后刚刚好是 Y B ˆ \^{Y_{B}} YBˆ Z A ˆ \^{Z_{A}} ZAˆ 被矩阵映射后,变成单位向量 Z B ˆ \^{Z_{B}} ZBˆ X A ˆ 、 Y A ˆ 、 Z A ˆ \^{X_{A}}、\^{Y_{A}}、\^{Z_{A}} XAˆYAˆZAˆ 三个基向量上的投影,合成后刚刚好是 Z B ˆ \^{Z_{B}} ZBˆ,这个旋转矩阵其实就是对坐标系 A {A} A 的空间变换,形成了坐标系 B {B} B

有了 B {B} B 坐标系的姿态,现在我们要还需要一个位矢 A P B O R G ^{A}{P_{BORG}} APBORG 来确定 B {B} B 坐标系相对于 A {A} A 坐标系的相对位置,最终可以将 B {B} B 坐标系的姿态表达为
B = B A R , A P B O R G {B} = {{_{B}^{A}R, ^{A}{P_{BORG}}}} B=BAR,APBORG

学习完三维空间中的两个坐标系的位姿表达后,我们来讨论坐标系 A {A} A 中的一个位矢如何在坐标系 B {B} B 中表达出来,我们先在两个坐标系的原点重合的情况下讨论,假设坐标系 A {A} A 中有个位矢 P P P,根据矩阵的映射原理可得,位矢 P P P 在坐标系 A {A} A 中的表达等价于位矢 P P P 在坐标系 B {B} B 中的表达再从坐标系 B {B} B 映射到坐标系 A {A} A
A P = B P B A R ^{A}P = ^{B}P_ {B}^{A}R AP=BPBAR

在这里插入图片描述

如果两个坐标系的原点不重合,我们还要考虑两个坐标系原点的位矢 A P B O R G ^{A}{P_{BORG}} APBORG ,位矢 A P B O R G ^{A}{P_{BORG}} APBORG 是以坐标系 A {A} A 为参照给出来的,所以不需要进行坐标系映射,直接进行矢量加和即可

A P = B P B A R + A P B O R G ^{A}P = ^{B}P_ {B}^{A}R + ^{A}{P_{BORG}} AP=BPBAR+APBORG
在这里插入图片描述

下面我们引入一个4x4的齐次变换矩阵来替换上面的式子,这样子表达更加明确简洁
[ A P 1 ] = [ B A R A P B O R G [ 0 0 0 ] 1 ] [ B P 1 ] \left[ \begin{array}{ccc} ^{A}P\\ 1\\ \end{array} \right ] = \left[ \begin{array}{ccc} _ {B}^{A}R & ^{A}{P_{BORG}}\\ \left[ \begin{array}{ccc} 0& 0 & 0\\ \end{array} \right ] & 1\\ \end{array} \right ]\left[ \begin{array}{ccc} ^{B}P \\ 1 \end{array} \right ] [AP1]=[BAR[000]APBORG1][BP1]

2. 欧拉角与四元数

试着想象一架飞机,在飞机质心处有一个坐标系 B {B} B,坐标系 B {B} B 绕它的 Z Z Z 轴旋转 α \alpha α 角,再绕它的 Y Y Y 轴旋转 β \beta β 角,最后绕它的 X X X 轴旋转 γ \gamma γ 角,这一组旋转三个角的集合被称为欧拉角。欧拉角有三个分别为yaw(偏航角)、pitch(俯仰角)、roll(翻滚角),代表着绕着Z/Y/X轴旋转的角度

在这里插入图片描述
按照上面欧拉角形成的过程,我们结合旋转矩阵的原理可以给出每次旋转的数学表达式
R Z ( α ) = [ c o s ( α ) − s i n ( α ) 0 s i n ( α ) c o s ( α ) 0 0 0 1 ] R_{Z}(\alpha) = \left[ \begin{array}{ccc} cos(\alpha) & -sin(\alpha) & 0\\ sin(\alpha) & cos(\alpha)& 0\\ 0 &0 & 1 \end{array} \right ] RZ(α)= cos(α)sin(α)0sin(α)cos(α)0001
R Y ( β ) = [ c o s ( β ) 0 s i n ( β ) 0 1 0 − s i n ( β ) 0 c o s ( β ) ] R_{Y}(\beta) = \left[ \begin{array}{ccc} cos(\beta) & 0 & sin(\beta)\\ 0 & 1& 0\\ -sin(\beta) &0 & cos(\beta) \end{array} \right ] RY(β)= cos(β)0sin(β)010sin(β)0cos(β)
R X ( γ ) = [ 1 0 0 0 c o s ( γ ) − s i n ( γ ) 0 s i n ( γ ) c o s ( γ ) ] R_{X}(\gamma) = \left[ \begin{array}{ccc} 1 & 0 & 0\\ 0 & cos(\gamma)& -sin(\gamma)\\ 0 &sin(\gamma) & cos(\gamma) \end{array} \right ] RX(γ)= 1000cos(γ)sin(γ)0sin(γ)cos(γ)
最后我们整合三个旋转矩阵的乘积就可以得到坐标系 B {B} B 在经过一组旋转后的形成的新的坐标系 B ′ {B^{'}} B 的相关参数,我们用一个旋转矩阵 B ′ B R ^{B}_{B^{'}}R BBR 来表达坐标系 B {B} B 到坐标系 B ′ {B^{'}} B 映射关系
B ′ B R Z − Y − X ( α , β , γ ) = [ c o s ( α ) c o s ( β ) c o s ( α ) s i n ( β ) s i n ( γ ) − s i n ( α ) c o s ( γ ) c o s ( α ) s i n ( β ) c o s ( γ ) + s i n ( α ) s i n ( γ ) s i n ( α ) c o s ( β ) s i n ( α ) s i n ( β ) s i n ( γ ) + c o s ( α ) c o s ( γ ) s i n ( α ) s i n ( β ) c o s ( γ ) − c o s ( α ) s i n ( γ ) − s i n ( β ) c o s ( β ) s i n ( γ ) c o s ( β ) c o s ( γ ) ] ^{B}_{B^{'}}R_{Z-Y-X} (\alpha,\beta,\gamma )= \left[ \begin{array}{ccc} cos(\alpha)cos(\beta) & cos(\alpha)sin(\beta)sin(\gamma)-sin(\alpha)cos(\gamma) & cos(\alpha)sin(\beta)cos(\gamma)+sin(\alpha)sin(\gamma)\\ sin(\alpha)cos(\beta) & sin(\alpha)sin(\beta)sin(\gamma)+cos(\alpha)cos(\gamma)& sin(\alpha)sin(\beta)cos(\gamma)-cos(\alpha)sin(\gamma)\\ -sin(\beta) &cos(\beta)sin(\gamma) & cos(\beta)cos(\gamma) \end{array} \right ] BBRZYX(α,β,γ)= cos(α)cos(β)sin(α)cos(β)sin(β)cos(α)sin(β)sin(γ)sin(α)cos(γ)sin(α)sin(β)sin(γ)+cos(α)cos(γ)cos(β)sin(γ)cos(α)sin(β)cos(γ)+sin(α)sin(γ)sin(α)sin(β)cos(γ)cos(α)sin(γ)cos(β)cos(γ)

四元数与复数类似,四元数其实就是对于基 ( a , i ⃗ , j ⃗ , k ⃗ ) {(a,\vec{i},\vec{j},\vec{k})} (a,i ,j ,k ) 的线性组合,是由一个标量和一个3x1的矢量组成,我们以复数类比四元数,四元数的标量就是复数的实部,四元数的矢量就是复数的虚部
在这里插入图片描述
四元数的乘法遵循下面的性质,自身相乘就是-1,和其他相乘与叉乘的性质一样,遵循右手定则
在这里插入图片描述

在这里插入图片描述
我们定义 q \mathbf{q} q 是一个单位四元数,又可将其表达为 q = w + x i + y j + z k \mathbf{q} = w +xi +yj+zk q=w+xi+yj+zk,由于 q \mathbf{q} q 是一个单位四元数
在这里插入图片描述

四元数 q \mathbf{q} q 的旋转矩阵 R q \mathbf{R}_{\mathbf{q}} Rq 可以表达为
在这里插入图片描述

二、ROS中python实现坐标变换

1. 坐标msg消息载体

订阅发布模型中数据载体 msg 是一个重要实现环节,在坐标转换实现中常用的坐标数据消息载体msg有geometry_msgs/TransformStamped和geometry_msgs/PointStamped

下面是geometry_msgs/TransformStamped消息返回后的一些数据,我们就可以得到两个坐标系之间的位姿关系,一般这里的父级坐标系我们选择世界坐标系"world"

std_msgs/Header header                     #头信息
  uint32 seq                                #|-- 序列号
  time stamp                                #|-- 时间戳
  string frame_id                            #|-- 坐标 ID
string child_frame_id                    #子坐标系的 id
geometry_msgs/Transform transform        #坐标信息
  geometry_msgs/Vector3 translation        #偏移量
    float64 x                                #|-- X 方向的偏移量
    float64 y                                #|-- Y 方向的偏移量
    float64 z                                #|-- Z 方向上的偏移量
  geometry_msgs/Quaternion rotation        #四元数
    float64 x                                
    float64 y                                
    float64 z                                
    float64 w

下面是geometry_msgs/PointStamped消息返回后的一些数据,我们就可以确定该点在所属坐标系的位置

std_msgs/Header header                    #头信息
  uint32 seq                                #|-- 序号
  time stamp                                #|-- 时间戳
  string frame_id                            #|-- 所属坐标系的 id
geometry_msgs/Point point                #点坐标
  float64 x                                    #|-- x y z 坐标
  float64 y
  float64 z

有了这些消息数据,我们就能实现一些好玩强大的功能,比如仿真环境中的乌龟跟随

2. 乌龟跟随的程序实现

乌龟跟随实现的核心,是乌龟A和B都要发布相对世界坐标系的坐标信息,然后订阅到该信息需要转换获取A相对于B坐标系的信息,最后生成线速度和角速度信息,并控制乌龟B运动。

首先在工作空间的src目录下,选择Create Catkin Package选项新建一个功能包,添加 tf2、tf2_ros、tf2_geometry_msgs、roscpp rospy std_msgs等依赖包,接着新建scripts文件夹用于存放python文件,创建launch文件夹用于存放launch文件

首先我们调用ROS的服务生成第二只小乌龟,创建第二只乌龟需要使用rosservice,话题使用的是 /spawn

#! /usr/bin/env python

#1.导包
import rospy
from turtlesim.srv import Spawn, SpawnRequest, SpawnResponse

if __name__ == "__main__":
    # 2.初始化 ros 节点
    rospy.init_node("turtle_spawn_p")
    # 3.创建服务客户端
    client = rospy.ServiceProxy("/spawn",Spawn)
    # 4.等待服务启动
    client.wait_for_service()
    # 5.创建请求数据
    req = SpawnRequest()
    req.x = 1.0
    req.y = 1.0
    req.theta = 0
    req.name = "turtle2"
    # 6.发送请求并处理响应
    try:
        response = client.call(req)
        rospy.loginfo("乌龟创建成功,名字是:%s",response.name)
    except Exception as e:
        rospy.loginfo("服务调用失败....")

接着我们需要编写坐标消息话题发布节点,我们通过话题 / 乌龟名称 / p o s e /乌龟名称/pose /乌龟名称/pose 来获取乌龟位姿,并将其解算成相对世界坐标系的坐标消息,然后发布出去

#! /usr/bin/env python

# 1.导包
import rospy
import sys
from turtlesim.msg import Pose
from geometry_msgs.msg import TransformStamped
import tf2_ros
import tf_conversions

turtle_name = ""

def doPose(pose):
    # rospy.loginfo("x = %.2f",pose.x)
    #1.创建坐标系广播器
    broadcaster = tf2_ros.TransformBroadcaster()
    #2.将 pose 信息转换成 TransFormStamped
    tfs = TransformStamped()
    tfs.header.frame_id = "world"
    tfs.header.stamp = rospy.Time.now()

    tfs.child_frame_id = turtle_name
    tfs.transform.translation.x = pose.x
    tfs.transform.translation.y = pose.y
    tfs.transform.translation.z = 0.0

    qtn = tf_conversions.transformations.quaternion_from_euler(0, 0, pose.theta)
    tfs.transform.rotation.x = qtn[0]
    tfs.transform.rotation.y = qtn[1]
    tfs.transform.rotation.z = qtn[2]
    tfs.transform.rotation.w = qtn[3]

    #3.广播器发布 tfs
    broadcaster.sendTransform(tfs)


if __name__ == "__main__":
    # 2.初始化 ros 节点
    rospy.init_node("sub_tfs_p")
    # 3.解析传入的命名空间
    rospy.loginfo("-------------------------------%d",len(sys.argv))
    if len(sys.argv) < 2:
        rospy.loginfo("请传入参数:乌龟的命名空间")
    else:
        turtle_name = sys.argv[1]
    rospy.loginfo("///乌龟:%s",turtle_name)

    rospy.Subscriber(turtle_name + "/pose",Pose,doPose)
    #     4.创建订阅对象
    #     5.回调函数处理订阅的 pose 信息
    #         5-1.创建 TF 广播器
    #         5-2.将 pose 信息转换成 TransFormStamped
    #         5-3.发布
    #     6.spin
    rospy.spin()

最后我们需要编写坐标消息话题订阅节点,通过订阅 turtle1 和 turtle2 的 TF坐标 广播信息,查找并转换时间最近的 TF坐标 信息将 turtle1 转换成相对 turtle2 的坐标,再计算线速度和角速度并发布到乌龟运动控制话题

#! /usr/bin/env python

# 1.导包
import rospy
import tf2_ros
from geometry_msgs.msg import TransformStamped, Twist
import math

if __name__ == "__main__":
    # 2.初始化 ros 节点
    rospy.init_node("sub_tfs_p")
    # 3.创建 TF 订阅对象
    buffer = tf2_ros.Buffer()
    listener = tf2_ros.TransformListener(buffer)
    # 4.处理订阅到的 TF
    rate = rospy.Rate(10)
    # 创建速度发布对象
    pub = rospy.Publisher("/turtle2/cmd_vel",Twist,queue_size=1000)
    while not rospy.is_shutdown():

        rate.sleep()
        try:
            #def lookup_transform(self, target_frame, source_frame, time, timeout=rospy.Duration(0.0)):
            trans = buffer.lookup_transform("turtle2","turtle1",rospy.Time(0))
            # rospy.loginfo("相对坐标:(%.2f,%.2f,%.2f)",
            #             trans.transform.translation.x,
            #             trans.transform.translation.y,
            #             trans.transform.translation.z
            #             )   
            # 根据转变后的坐标计算出速度和角速度信息
            twist = Twist()
            # 间距 = x^2 + y^2  然后开方
            twist.linear.x = 0.5 * math.sqrt(math.pow(trans.transform.translation.x,2) + math.pow(trans.transform.translation.y,2))
            twist.angular.z = 4 * math.atan2(trans.transform.translation.y, trans.transform.translation.x)

            pub.publish(twist)

        except Exception as e:
            rospy.logwarn("警告:%s",e)

在终端里给python文件添加可执行权限

chmod +777 *.py

按照上次笔记的方法配置好CMakeLists.txt文件,将要编译三个.py文件声明一下,然后catkin_make:build编译后看看有没有报错,没有报错就可以编写launch文件

<launch>
    <node pkg="turtlesim" type="turtlesim_node" name="turtle1" output="screen" />
    <node pkg="turtlesim" type="turtle_teleop_key" name="key_control" output="screen"/>

    <node pkg="xxx" type="xxx.py" name="turtle_spawn" output="screen"/>

    <node pkg="xxx" type="xxx.py" name="tf_pub1" args="turtle1" output="screen"/>
    <node pkg="xxx" type="xxx.py" name="tf_pub2" args="turtle2" output="screen"/>
    <node pkg="xxx" type="xxx.py" name="tf_sub" output="screen"/>
</launch>

编写好launch文件后右键launch文件打开终端运行launch文件就可以看见乌龟跟随效果

roslaunch xxx(功能包) xxx.launch(launch文件)

总结

以上就是机器人坐标变换的学习笔记,本片笔记简单地介绍了机器人坐标变换的理论基础和ROS中的TF坐标变换实现过程。机器人坐标变换的重要性在于它可以使机器人在不同坐标系下保持一致的运动精度。因为在不同的坐标系下,机器人的运动轨迹和位置信息都会发生变化。例如,机器人在基座坐标系下的运动可能是直线运动,但在工具坐标系下的运动可能是旋转运动。如果不进行坐标变换,机器人的运动轨迹和位置信息就会出现偏差,导致机器人无法精确地完成任务。

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

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

相关文章

【P23】JMeter 用户参数(User Parameters)

&#xff08;1&#xff09;、测试计划右键 <<< 添加 <<< 前置处理器 <<< 用户参数 如图&#xff0c;添加两个变量&#xff0c;每个变量包含两个用户 &#xff08;2&#xff09;、测试计划右键 <<< 添加 <<< 线程&#xff08;用户…

ChatGPT的工作原理(纯干货,万字长文)

ChatGPT 能够自动生成一些读起来表面上甚至像人写的文字的东西&#xff0c;这非常了不起&#xff0c;而且出乎意料。但它是如何做到的&#xff1f;为什么它能发挥作用&#xff1f;我在这里的目的是大致介绍一下 ChatGPT 内部的情况&#xff0c;然后探讨一下为什么它能很好地生成…

Python采集二手房源数据信息并做多线程

前言 嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! 目录标题 前言环境使用:模块使用:代码展示多线程 尾语 &#x1f49d; 环境使用: Python 3.8 Pycharm 模块使用: requests >>> pip install requests 数据请求模块 parsel >>> pip install parsel 数据…

详述:冒泡排序

一、接下来讲解一下c语言中比较简单的排序方法&#xff1a;冒泡排序 1.冒泡排序的核心思想&#xff1a;是两两相邻的元素进行比较 动画演示&#xff1a; 应用冒泡排序需要明确2点&#xff1a; 1.需要进行多少趟冒泡排序 2.每趟冒泡排序&#xff0c;需要比较的对数 二、代码实…

发布 Copilot Chat Sample App

我们很高兴为您介绍 Semantic Kernel 的 Copilot Chat Sample App&#xff01;借助此应用程序&#xff0c;开发人员可以使用自然语言处理、语音识别和文件上传等高级功能轻松构建自己的聊天机器人。通过利用基于 LLM 的 AI&#xff0c;您可以通过 Semantic Kernel 使用您自己的…

LayerZero有何发展潜力?空投热潮和大额融资双重加持

前言 近期Arbitrum的如愿空投再次点燃了市场「刷空投」的热情&#xff0c;除了ZK系的zkSync、Starknet及Scroll&#xff0c;也有部分用户将注意力投向了估值30亿美元的LayerZero。而 LayerZero刚刚完成的1.2亿美元B轮融资也让其市场热度持续攀升&#xff0c;在「空投热潮」及「…

【1++的Linux】之Linux常见指令(二)

&#x1f44d;作者主页&#xff1a;进击的1 &#x1f929; 专栏链接&#xff1a;【1的Linux】 文章目录 一&#xff0c;man指令二&#xff0c;cp指令三&#xff0c;mv指令四&#xff0c;cat指令五&#xff0c;more指令六&#xff0c;less指令七&#xff0c;head与tail指令八&am…

【免交互】

目录 一、免交互1.1、语法格式1.2、命令演示1、多行写入文件内容2、多行注释 二、Expect2.1、基本命令2.2、脚本操作 一、免交互 1、使用I/O重定向的方式将命令列表提供给交互式程序或命令&#xff0c;比如 ftp、cat 或 read 命令。 2、是标准输入的一种替代品可以帮助脚本开发…

从C语言到C++⑩(第四章_模板初阶+STL简介)如何学习STL

目录 1. 泛型编程 1.1 函数重载弊端 1.2 泛型编程概念 2. 函数模板 2.1 函数模板的概念 2.2 函数模板格式 2.3 函数模板原理 2.4 函数模板实例化 2.4.1 隐式实例化 2.4.2 显式实例化 2.5 模板参数的匹配原则 3. 类模板 3.1 类模板的定义 3.2 类模板实例化 4.…

David Silver Lecture 7: Policy Gradient

1 Introduction 1.1 Policy-Based Reinforcement Learning 1.2 Value-based and policy based RL 基于值的强化学习 在基于值的 RL 中&#xff0c;目标是找到一个最优的值函数&#xff0c;通常是 Q 函数或 V 函数。这些函数为给定的状态或状态-动作对分配一个值&#xff0c;表…

【JAVAEE】JUC(java.util.concurrent)的常见类

目录 1.Callable接口 1.1简介 1.2代码演示 1.3Runnable与Callable的区别 2.ReentrantLock 2.1ReentrantLock的常用方法 2.2ReentrantLock的代码演示 2.3ReentrantLock和synchronized的区别 3.Semaphore信号量 3.1概念 3.2代码演示 4.CountDownLatch 4.1概念 4.2代…

【SpringBoot整合RabbitMQ(下)】

八、死信队列 先从概念解释上搞清楚这个定义&#xff0c;死信&#xff0c;顾名思义就是无法被消费的消息&#xff0c;字面意思可以这样理解&#xff0c;一般来说&#xff0c;producer 将消息投递到 broker 或者直接到 queue 里了&#xff0c; consumer 从 queue 取出消…

用Pin自动对二进制文件脱壳

Intel Pin Intel Pin在可执行二进制代码中插入一些探测函数,用于观察、记录、分析宿主代码执行过程中的一些与计算机体系结构相关的特性,如访存指令,寄存器内容,寄存器地址等,通过Pin提供的API可以编写各种分析函数,这样程序运行完以后,统计和分析结果也同时产生,分析…

I3D--视频理解必读论文总结

论文标题&#xff1a;Quo Vadis, Action Recognition? A New Model and the Kinetics会议期刊&#xff1a; CVPR 2017Dataset 论文地址&#xff1a;https://arxiv.org/pdf/1705.07750.pdf 文章目录 前言文章核心摘要引入方法a. 2DConvLSTMb. 3DConvc d. Two-StrwamTwo-Stream …

C语言学习分享(第七次)------操作符

&#x1f493;博主CSDN主页:杭电码农-NEO&#x1f493;   ⏩专栏分类:C语言学习分享⏪   &#x1f69a;代码仓库:NEO的学习日记&#x1f69a;   &#x1f339;关注我&#x1faf5;带你学习更多C语言知识   &#x1f51d;&#x1f51d; 操作符详解 1. 前言&#x1f6a9;2…

Ajax,前后端分离开发,前端工程化,Element,Vue路由,打包部署

Ajax介绍 Axios <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"widthdevice-wid…

为什么我掌握了大量软测知识,却还是找不到工作?

很多朋友都在疑惑&#xff0c;为什么随着对于软件测试了解的加深&#xff0c;不断掌握更多测试知识与技巧&#xff0c;找工作貌似越来越难了&#xff1f; 不免让人联想到最近偶然间看到一句话&#xff1a;“软件测试是整个 IT 行业中最差的岗位”。 打工人的问题出在哪&#xf…

使用Jmeter应该如何进行http接口性能测试?

在进行网页或应用程序后台接口开发时&#xff0c;一般要及时测试开发的接口能否正确接收和返回数据&#xff0c;对于单次测试&#xff0c;Postman插件是个不错的Http请求模拟工具。 但是Postman只能模拟单客户端的单次请求&#xff0c;而对于模拟多用户并发等性能测试&#xff…

11.1网络编程——

多线程 一、基础知识概念相关API二、任务创建一个简单的本地客户端创建一个简单的本地服务器三、总结四、问题一、基础知识 概念 网络编程中客户端和服务器指的是进程,而不是常提到的机器或者主机。注意三个概念:请求、响应、事务。 网络编程中客户端-服务器事务是指客户端和…

刷题day65:分割等和子集

题意描述&#xff1a; 给你一个 只包含正整数 的 非空 数组 nums 。请你判断是否可以将这个数组分割成两个子集&#xff0c;使得两个子集的元素和相等。 思路&#xff1a; 使用01背包&#xff0c; 背包的体积为sum / 2背包要放入的商品&#xff08;集合里的元素&#xff09;…