ROS2手写接收IMU数据(Imu)代码并发布

news/2024/5/19 9:22:49/文章来源:https://blog.csdn.net/scarecrow_sun/article/details/129178198

目录

  • 前言
  • 接收IMU数据
    • IMU的串口连接
      • 问题
    • python接收串口数据
    • python解析数据
    • ROS2发布IMU数据
    • 可视化IMU数据
    • 效果

前言

在前面测试完了单独用激光雷达建图之后,一直想把IMU的数据融合进去,由于经费的限制,忍痛在淘宝上买了一款便宜的IMU—GY95T,如下图所示
在这里插入图片描述

东西买回来了,但是还需要写一个读取数据的代码,商家并没有提供在ROS2上用python接收数据,并且将其转换为ROS2的数据格式的代码,于是自己只能手搓一遍。
读取IMU数据的代码倒是不难,但是要怎么将其转换为ROS2的数据格式是我之前完全没接触到的,把整个流程记录一下,便于回忆。

环境

ROS2 humble
Ubuntu22.04
IMU:GY-95T

我将整个流程分成了以下步骤

串口接收IMU数据
解析IMU数据
ROS2发布IMU数据
利用rviz2可视化检查

接收IMU数据

流程如下 ,利用python打开串口,然后接收数据即可。具体的过程后面一步步写出

IMU的串口连接

首先通过USB将IMU连接到电脑上。用lsusb查看连接到Ubuntu上面的USB设备有哪些,我用的虚拟机测试,所以有一些虚拟机的设备

lsusb
# 返回以下信息Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 038: ID 1a86:7523 QinHeng Electronics CH340 serial converter
Bus 002 Device 029: ID 0e0f:0008 VMware, Inc. Virtual Bluetooth Adapter
Bus 002 Device 003: ID 0e0f:0002 VMware, Inc. Virtual USB Hub
Bus 002 Device 002: ID 0e0f:0003 VMware, Inc. Virtual Mouse
Bus 002 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub

可以看到有一个叫QinHeng Electronics CH340 serial converter的CH340设备,这就是IMU的串口连接设备了,再通过ls指令查看其被映射为了什么端口

ls /dev/ttyUSB*# 返回
/dev/ttyUSB0

即这里的USB设备被映射为了/dev/ttyUSB0这个文件,后面还会用得上

问题

我在中途遇到了这么一个问题
能够找到USB设备,但是没有被映射为/dev/ttyUSB0的问题

我首先查看了是否存在ch340的驱动

lsmod | grep ch34# 返回
ch341                  24576  0
usbserial              57344  1 ch341

说明我的虚拟机是存在串口驱动的,但是没有找到设备,那通过这篇博客,我发现了是端口被占用了

Ubuntu22.04没有ttyUSB(无法访问 ‘/dev/ttyUSB‘: 没有那个文件或目录)问题解决

文中所说的方法如下:
sudo dmesg | grep brltty

若出现[ 7033.078452] usb 1-13: usbfs: interface 0 claimed by ch341 while 'brltty' sets config #1 则说明驱动被占用

使用sudo apt remove brltty后,重新插拔设备即可

问题探究到底,这个brltty卸载后会不会对以后使用有影响呢?用chatgpt搜索这个软件后,给出的解释如下:

在Ubuntu中,Brltty 是一个用于盲人和视力受损人士的文本转换工具。它提供了一个用于显示在Braille终端上的用户界面,这些终端通常由触觉读取器件(如盲文显示器)或语音合成器(如屏幕阅读器)使用。
Brltty 可以将文本数据转换成 Braille 码,通过串口或并口将其发送到 Braille 终端。它支持多种不同类型的 Braille 终端,包括常见的 VarioUltra、BrailleNote 和 Focus 14/40。
除了将文本数据转换为 Braille 码之外,Brltty 还提供了一些其他的辅助功能,如语音反馈、支持多国语言、自动检测插入/拔出设备等。

因此对于非盲人和视力受损人士用处不大,因此卸载后无影响

注意:由于串口是具有权限的,为了确保在后续运行python代码的时候具有程序启动串口的权限,我们这里把端口的权限进行更改

sudo chmod 777 /dev/ttyUSB0 

python接收串口数据

在Ubuntu连接了串口之后,我们就可以使用python来读取IMU的数据了

这里用到了python的serial库

sudo apt install python3-serial

为确保读取IMU数据的准确性,我们用python读取串口的方法是,在一个周期下,收取该周期内所有信息,每隔time,将数据返回一次

因此,我们需要按照如下设置我们的串口

# 串口初始化
IMU_Usart = serial.Serial(port = '/dev/ttyUSB0',      # 串口baudrate=115200,            # 波特率timeout = 0.001             # 由于后续使用read按照一个timeout周期时间读取数据# imu在波特率115200返回数据时间大概是1ms,9600下大概是10ms# 所以读取时间设置0.001s)
# ----读取IMU的内部数据-----------------------------------
try:count = IMU_Usart.inWaiting()if count > 0:# 接收数据至缓存区Read_buffer=self.IMU_Usart.read(40)         # 我们需要读取的是40个寄存器数据,即40个字节
except KeyboardInterrupt:if serial != None:print("close serial port")self.IMU_Usart.close()#--------------------------------------------------------

其中.inWaiting()函数的作用如下:

用于检查串口缓冲区中等待读取的字节数。
在串口通信中,发送方发送的数据可能需要一定时间才能到达接收方。因此,接收方需要先将接收到的数据存储在缓冲区中,等待读取。.inWaiting() 方法可以用于检查当前串口缓冲区中等待读取的字节数,以便读取相应数量的字节。

我用流程图表述一下代码的读取原理

初始化串口
是否达到一个周期时间
根据真实数据长度读取数据
继续等待

python解析数据

在接收到了IMU传过来的数据之后,我们就需要对其数据进行解析了。

解析这个部分,没有特别多要说的,我是根据卖家给出的数据手册,按照状态机的方式接收并检查数据是否准确。这里把状态机的代码贴出来

def Read_data(self):'''Author: Liu Yuxiang Time: 2022.12.13description: 读取IMU数据'''# 初始化数据counter = 0 Recv_flag = 0Read_buffer = []# 接收数据至缓存区Read_buffer=self.IMU_Usart.read(40)         # 我们需要读取的是40个寄存器数据,即40个字节# 状态机判断收包数据是否准确while(1):# 第1帧是否是帧头ID 0xA4if (counter == 0):if(Read_buffer[0] != 0xA4):break    # 第2帧是否是读功能码 0x03  elif (counter == 1):if(Read_buffer[1] != 0x03):counter=0break# 第3帧判断起始帧        elif (counter == 2):if(Read_buffer[2] < 0x2c):start_reg=Read_buffer[2]else:counter=0 # 第4帧判断帧有多少数量 elif (counter == 3):if((start_reg+Read_buffer[3]) < 0x2C): # 最大寄存器为2C 大于0x2C说明数据肯定错了len=Read_buffer[3]else:counter=0break                  else:if(len+5==counter):#print('Recv done!')Recv_flag=1# 收包完毕if(Recv_flag):Recv_flag = 0sum = 0#print(Read_buffer)                                 # Read_buffer中的是byte数据字节流,用struct包解包data_inspect = str(binascii.b2a_hex(Read_buffer))   # data是将数据转化为原本的按照16进制的数据try:        # 如果接收数据无误,则执行数据解算操作for i in range(2,80,2):                 # 根据手册,检验所有帧之和低八位是否等于末尾帧sum += int(data_inspect[i:i+2],16)if (str(hex(sum))[-2:] == data_inspect[80:82]): # 如果数据检验没有问题,则进入解包过程#print('the Rev data is right')# 数据低八位在前,高八位在后#print(Read_buffer[4:-1])                       unpack_data = struct.unpack('<hhhhhhhhhBhhhhhhhh',Read_buffer[4:-1])# 切片并将其解析为我们所需要的数据,切出我们所需要的数据部分g = 9.8self.ACC_X  = unpack_data[0]/2048 * g       # unit m/s^2self.ACC_Y  = unpack_data[1]/2048 * g    self.ACC_Z  = unpack_data[2]/2048 * gself.GYRO_X = unpack_data[3]/16.4           # unit 度/sself.GYRO_Y = unpack_data[4]/16.4                self.GYRO_Z = unpack_data[5]/16.4                     self.roll   = unpack_data[6]/100                self.pitch  = unpack_data[7]/100                 self.yaw    = unpack_data[8]/100                          self.level  = unpack_data[9]self.temp   = unpack_data[10]/100 self.MAG_X  = unpack_data[11]/1000          # unit Gaos             self.MAG_Y  = unpack_data[12]/1000           self.MAG_Z  = unpack_data[13]/1000self.Q0     = unpack_data[14]/10000        self.Q1     = unpack_data[15]/10000                 self.Q2     = unpack_data[16]/10000                 self.Q3     = unpack_data[17]/10000#print(self.__dict__) except:print("Have Error in receiving data!!")counter=0               breakelse:counter += 1                        # 遍历整个接收数据的buffer

ROS2发布IMU数据

在跑通了整个读取数据的流程,并与卖家给的上位机返回的数据对比没问题之后,下一步就是需要将数据转换为ROS2的数据格式,并将其发布出来,ROS2中IMU的数据格式类型如下

std_msgs/Header header      # 时间戳和坐标系ID
geometry_msgs/Quaternion orientation # 四元数形式的方向
float64[9] orientation_covariance # 方向估计的协方差矩阵
geometry_msgs/Vector3 angular_velocity # 三维角速度
float64[9] angular_velocity_covariance # 角速度估计的协方差矩阵
geometry_msgs/Vector3 linear_acceleration # 三维线性加速度
float64[9] linear_acceleration_covariance # 线性加速度估计的协方差矩阵
  • header:标准的ROS消息头,包含测量的时间戳和坐标系。
    • 时间戳没有单位,坐标系ID是字符串类型;
  • orientation:以四元数形式表示的IMU传感器的方向,以 geometry_msgs/Quaternion 消息表示。四元数表示从IMU坐标系到由header指定的参考坐标系的旋转。四元数应该被归一化。
    • 四元数表示的方向没有单位;
  • orientation_covariance:一个包含9个元素的数组,表示方向估计的协方差矩阵。矩阵以行优先顺序存储。协方差值应以(x、y、z、x-y、x-z、y-z)的顺序表示。
    • 协方差矩阵是无单位的;
  • angular_velocity:以IMU坐标系表示的IMU传感器的角速度,以 geometry_msgs/Vector3 消息表示。
    • 角速度以弧度/秒(rad/s)为单位;
  • angular_velocity_covariance:一个包含9个元素的数组,表示角速度估计的协方差矩阵。矩阵以行优先顺序存储。协方差值应以(x、y、z、x-y、x-z、y-z)的顺序表示。
    • 角速度估计的协方差矩阵是以 (rad/s)^2 为单位的;
  • linear_acceleration:以IMU坐标系表示的IMU传感器的线性加速度,以 geometry_msgs/Vector3 消息表示。
    • 线性加速度以米/秒²(m/s²)为单位;
  • linear_acceleration_covariance:一个包含9个元素的数组,表示线性加速度估计的协方差矩阵。矩阵以行优先顺序存储。协方差值应以(x、y、z、x-y、x-z、y-z)的顺序表示。
    • 线性加速度估计的协方差矩阵是以 (m/s²)^2 为单位的。

这个IMU是可以直接传回四元数,因此我可以直接进行传参,而不需要再进行四元数转换

注意,这里需要用到ROS2的serial库,但是由于在ROS2 humble中并没有此库,因此,我们需要去下载这个库的源码,并手动安装,安装的教程参考我之前的这篇博客,地址如下:

ROS2安装serial库

这里把完整的代码贴出来

import rclpy                                     # ROS2 Python Client Library
from rclpy.node import Node                      # ROS2 Node
from sensor_msgs.msg import Imu# Usart Library
import serial
import struct
import binascii'''Author: Liu Yuxiang Time: 2022.12.13description: IMU底层串口收发代码
'''# imu接收数据类型
class IMU(Node):send_data = []def __init__(self):super().__init__('imu_publisher')self.publisher_ = self.create_publisher(Imu, 'imu_data', 1)# 串口初始化self.IMU_Usart = serial.Serial(port = '/dev/ttyUSB0',      # 串口baudrate=115200,            # 波特率timeout = 0.001             # 由于后续使用read_all按照一个timeout周期时间读取数据# imu在波特率115200返回数据时间大概是1ms,9600下大概是10ms# 所以读取时间设置0.001s)# 接收数据初始化self.ACC_X:float = 0.0                   # X轴加速度self.ACC_Y:float = 0.0                   # Y轴加速度self.ACC_Z:float  =  0.0                 # Z轴加速度self.GYRO_X :float = 0.0                 # X轴陀螺仪self.GYRO_Y :float = 0.0                 # Y轴陀螺仪self.GYRO_Z :float = 0.0                 # Z轴陀螺仪self.roll :float = 0.0                   # 横滚角    self.pitch :float = 0.0                  # 俯仰角self.yaw :float = 0.0                    # 航向角self.leve :float = 0.0                   # 磁场校准精度self.temp :float = 0.0                   # 器件温度self.MAG_X :float = 0.0                  # 磁场X轴self.MAG_Y :float = 0.0                  # 磁场Y轴self.MAG_Z :float = 0.0                  # 磁场Z轴self.Q0 :float = 0.0                     # 四元数Q0.0self.Q1 :float = 0.0                     # 四元数Q1self.Q2 :float = 0.0                     # 四元数Q2self.Q3 :float = 0.0                     # 四元数Q3# 判断串口是否打开成功if self.IMU_Usart.isOpen():print("open success")else:print("open failed")# 回调函数返回周期time_period = 0.001         self.timer = self.create_timer(time_period, self.timer_callback)# 发送读取指令self.Send_ReadCommand()def Send_ReadCommand(self):'''Author: Liu Yuxiang Time: 2022.12.13description: 发送读取IMU内部数据指令· 第一个寄存器0x08 最后一个读取寄存器0x2A 共35个· 读寄存器例子,读取模块内部温度,主站发送帧为:A4 03 1B 02 C4|   A4    |    03    |    1B   |     02    |    C4|  帧头ID  | 读功能码 |起始寄存器| 寄存器数量 |校验和低 8 位'''# 使用优雅的方式发送串口数据send_data = [0xA4,0x03,0x08,0x23,0xD2]                      #需要发送的串口包#send_data = [0xA4,0x03,0x08,0x1B,0xCA]                      #需要发送的串口包send_data=struct.pack("%dB"%(len(send_data)),*send_data)    #解析成16进制print(send_data)self.IMU_Usart.write(send_data)                             #发送def Read_data(self):'''Author: Liu Yuxiang Time: 2022.12.13description: 读取IMU数据'''# 初始化数据counter = 0 Recv_flag = 0Read_buffer = []# 接收数据至缓存区Read_buffer=self.IMU_Usart.read(40)         # 我们需要读取的是40个寄存器数据,即40个字节# 状态机判断收包数据是否准确while(1):# 第1帧是否是帧头ID 0xA4if (counter == 0):if(Read_buffer[0] != 0xA4):break    # 第2帧是否是读功能码 0x03  elif (counter == 1):if(Read_buffer[1] != 0x03):counter=0break# 第3帧判断起始帧        elif (counter == 2):if(Read_buffer[2] < 0x2c):start_reg=Read_buffer[2]else:counter=0 # 第4帧判断帧有多少数量 elif (counter == 3):if((start_reg+Read_buffer[3]) < 0x2C): # 最大寄存器为2C 大于0x2C说明数据肯定错了len=Read_buffer[3]else:counter=0break                  else:if(len+5==counter):#print('Recv done!')Recv_flag=1# 收包完毕if(Recv_flag):Recv_flag = 0sum = 0#print(Read_buffer)                                 # Read_buffer中的是byte数据字节流,用struct包解包data_inspect = str(binascii.b2a_hex(Read_buffer))   # data是将数据转化为原本的按照16进制的数据try:        # 如果接收数据无误,则执行数据解算操作for i in range(2,80,2):                 # 根据手册,检验所有帧之和低八位是否等于末尾帧sum += int(data_inspect[i:i+2],16)if (str(hex(sum))[-2:] == data_inspect[80:82]): # 如果数据检验没有问题,则进入解包过程#print('the Rev data is right')# 数据低八位在前,高八位在后#print(Read_buffer[4:-1])                       unpack_data = struct.unpack('<hhhhhhhhhBhhhhhhhh',Read_buffer[4:-1])# 切片并将其解析为我们所需要的数据,切出我们所需要的数据部分g = 9.8self.ACC_X  = unpack_data[0]/2048 * g       # unit m/s^2self.ACC_Y  = unpack_data[1]/2048 * g    self.ACC_Z  = unpack_data[2]/2048 * gself.GYRO_X = unpack_data[3]/16.4           # unit 度/sself.GYRO_Y = unpack_data[4]/16.4                self.GYRO_Z = unpack_data[5]/16.4                     self.roll   = unpack_data[6]/100                self.pitch  = unpack_data[7]/100                 self.yaw    = unpack_data[8]/100                          self.level  = unpack_data[9]self.temp   = unpack_data[10]/100 self.MAG_X  = unpack_data[11]/1000          # unit Gaos             self.MAG_Y  = unpack_data[12]/1000           self.MAG_Z  = unpack_data[13]/1000self.Q0     = unpack_data[14]/10000        self.Q1     = unpack_data[15]/10000                 self.Q2     = unpack_data[16]/10000                 self.Q3     = unpack_data[17]/10000#print(self.__dict__) except:print("Have Error in receiving data!!")counter=0               breakelse:counter += 1                        # 遍历整个接收数据的bufferdef timer_callback(self):# ----读取IMU的内部数据-----------------------------------try:count = self.IMU_Usart.inWaiting()if count > 0:self.Read_data()# 发布sensor_msgs/Imu 数据类型imu_data = Imu()imu_data.header.frame_id = "map"imu_data.header.stamp = self.get_clock().now().to_msg()imu_data.linear_acceleration.x = self.ACC_Ximu_data.linear_acceleration.y = self.ACC_Yimu_data.linear_acceleration.z = self.ACC_Zimu_data.angular_velocity.x = self.GYRO_X * 3.1415926 / 180.0  # unit transfer to rad/simu_data.angular_velocity.y = self.GYRO_Y * 3.1415926 / 180.0imu_data.angular_velocity.z = self.GYRO_Z * 3.1415926 / 180.0imu_data.orientation.x = self.Q0imu_data.orientation.y = self.Q1imu_data.orientation.z = self.Q2imu_data.orientation.w = self.Q3self.publisher_.publish(imu_data)             # 发布imu的数据# --------------------------------------------------------#print('读取中')except KeyboardInterrupt:if serial != None:print("close serial port")self.IMU_Usart.close()#--------------------------------------------------------def main(args=None):# 变量初始化---------------------------------------------    rclpy.init(args=args)IMU_node = IMU()rclpy.spin(IMU_node)rclpy.shutdown()if __name__ == '__main__':main()'''
░░░░░░░░░░░░░░░░░░░░░░░░▄░░
░░░░░░░░░▐█░░░░░░░░░░░▄▀▒▌░
░░░░░░░░▐▀▒█░░░░░░░░▄▀▒▒▒▐░
░░░░░▄▄▀▒░▒▒▒▒▒▒▒▒▒█▒▒▄█▒▐░
░░░▄▀▒▒▒░░░▒▒▒░░░▒▒▒▀██▀▒▌░
░░▐▒▒▒▄▄▒▒▒▒░░░▒▒▒▒▒▒▒▀▄▒▒░
░░▌░░▌█▀▒▒▒▒▒▄▀█▄▒▒▒▒▒▒▒█▒▐
░▐░░░▒▒▒▒▒▒▒▒▌██▀▒▒░░░▒▒▒▀▄
░▌░▒▄██▄▒▒▒▒▒▒▒▒▒░░░░░░▒▒▒▒
▀▒▀▐████▌▄░▀▒▒░░░░░░░░░░▒▒▒
狗狗保佑代码无bug!
'''

其实最关键的部分就是对其进行一个赋值并发布出去即可。

可视化IMU数据

当我们有了数据之后,我们希望对其进行可视化,这样能够非常直观的看到我们的数据,并且符不符合ROS2的数据格式,因此,我们接下来用rviz2来可视化

首先,需要安装IMU的可视化工具,imu-tools

sudo apt install ros-humble-imu-tools

注意:如果你的ROS2的不是humble版本,就将其改为你自己的版本即可

安装完毕后,运行节点,并开启rviz2,点击add,在By topic中添加Imu就可以可视化IMU数据啦

效果

请添加图片描述

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

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

相关文章

某直聘tp_token解析

尊重版权&#xff0c;请勿盗版&#xff0c;不放代码。截至2023-02-23更新---------------------------------------检测windows属性总数大于150 改成大于15 > 150检测了document属性大于50检测了navigate属性检测了navigate.plugins 属性值检测moudle nodejs是否存在&#x…

前端开发:JS中深拷贝和浅拷贝的区别

前言 前端开发中&#xff0c;关于JS原生的原理使用是前端开发者的看家本领&#xff0c;尤其是关于底层和原理的掌握使用&#xff0c;甚为重要。而且编程语言有一些比较共性的概念在不同的编程语言中会有相同的概念&#xff0c;比如深拷贝和浅拷贝它们不仅在JS中有&#xff0c;在…

Prometheus之Alertmanager告警

告警流程 Prometheus主要是提供了数据的采集和存储&#xff0c;Alertmanager组件主要实现告警功能。Alertmanager 主要用于接收 Prometheus 发送的告警信息&#xff0c;它支持丰富的告警通知渠道&#xff0c;而且很容易做到告警信息进行去重&#xff0c;降噪&#xff0c;分组等…

双碳”目标下二氧化碳地质封存技术应用前景及模型构建实践方法

2022年七月七日&#xff0c;工业和信息化部、发展改革委、生态环境部关于印发工业领域碳达峰实施方案的通知落地。全国各省份积极响应&#xff0c;纷纷出台地方指导文件&#xff0c;标志着我国碳减排事业的全面铺开。二氧化碳地质封存技术作为实现我国“双碳”目标的重要一环&a…

易点易动助力企业固定资产信息化管理

对于生产制造或者互联网企业而言&#xff0c;固定资产比重较高&#xff0c;是企业资产的大头&#xff0c;一些办公设备、生产设备数量和金额都比较大。提升企业固定资产管理水平&#xff0c;是企业实现信息化建设的必要条件。 目前&#xff0c;国内的很多企业在固定资产管理中…

一口吃不成ChatGPT,复旦版MOSS服务器被挤崩后续

ChatGPT 是目前最先进的 AI&#xff0c;由于 ChatGPT 的训练过程所需算力资源大、标注成本高&#xff0c;此前国内暂未出现对大众开放的同类产品。 适逢ChatGPT概念正火&#xff0c;2 月 21 日&#xff0c;复旦团队发布首个中国版类 ChatGPT 模型「MOSS」&#xff0c;没想到瞬时…

编译原理【运行时环境】—什么是活动记录、 活动记录与汇编代码的关系

系列文章戳这里&#x1f447; 什么是上下文无关文法、最左推导和最右推导如何判断二义文法及消除文法二义性何时需要消除左递归什么是句柄、什么是自上而下、自下而上分析什么是LL(1)、LR(0)、LR(1)文法、LR分析表LR(0)、SLR(1)、LR(1)、LALR(1)文法之间的关系编译原理第三章习…

扬帆优配|翻倍牛股“高台跳水”,一度跌停,啥情况

2月23日上午&#xff0c;A股商场窄幅震荡&#xff0c;上证指数上午收盘涨0.07%&#xff0c;煤炭、电力设备等板块领涨。 总的来看&#xff0c;A股商场上午整体体现安静&#xff0c;不过仍有个股大幅动摇&#xff0c;比如前期翻倍热门股汉王科技盘中“高台跳水”&#xff0c;一…

JS - 原型对象、原型链是什么

一 阅读掘金 https://juejin.cn/post/7007416743215759373 https://juejin.cn/post/7007416743215759373 二 阅读掘金小册原型知识点 原型 涉及面试题&#xff1a;如何理解原型&#xff1f;如何理解原型链&#xff1f; 当我们创建一个对象时 let obj { age: 25 }&#xff0…

一篇文章搞定linux网络模型

网络协议感觉晦涩难懂&#xff1f;什么七层网络模型&#xff1f;又五层网络模型&#xff1f;又四层网络模型&#xff1f;TCP/IP协议是个啥&#xff1f;UDP是啥&#xff1f;什么是三次握手&#xff1f;什么是四次挥手&#xff1f;tcpdump听说是抓包的&#xff0c;怎么用&#xf…

Docker 容器命令 和安装各种镜像环境

CentOS安装Docker 1.1.卸载&#xff08;可选&#xff09; 如果之前安装过旧版本的Docker&#xff0c;可以使用下面命令卸载&#xff1a; yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotat…

SCG failure information

我们知道5G网络有独立组网和非独立组网&#xff0c;独立组网中不论是核心网还是接入网都是5G&#xff0c;但是部署成本高&#xff1b;非独立组网也就是双连接(MRDC)也是目前比较流行的一种方式&#xff0c;其中的ENDC&#xff0c;即E-UTRA-NRDual Connectivity&#xff0c;是将…

设备太分散?如何一站式管理边缘 OS、K8s 和应用?

作者简介 张志龙&#xff0c;SUSE 大中华区资深解决方案架构师&#xff0c;CNCF 官方认证的 CKA&CKAD 工程师&#xff0c;深耕以 Kubernetes 为代表的云原生领域&#xff0c;具备丰富的架构设计、业务容器化改造和项目落地实践经验。 据 Gartner 预测&#xff0c;到 2025 年…

插画网课平台排名

插画网课平台哪个好&#xff0c;插画网课排名靠前的有哪些&#xff0c;今天给大家梳理了国内5家专业的插画网课平台&#xff0c;各有优势和特色&#xff0c;给学插画的小伙伴提供选择&#xff0c;报插画网课一定要选择靠谱的&#xff0c;否则人钱两空泪两行&#xff01; 一&am…

node版本管理器 nvm

一、nvm介绍 在工作中&#xff0c;我们可能同时在进行2个或者多个不同的项目开发&#xff0c;每个项目的需求不同&#xff0c;进而不同项目必须依赖不同版本的NodeJS运行环境&#xff0c;这种情况下&#xff0c;对于维护多个版本的node将会是一件非常麻烦的事情&#xff0c;nv…

【2023】Prometheus-相关知识点(面试点)

目录1.Prometheus1.1.什么是Prometheus1.2.Prometheus的工作流程1.3.Prometheus的组件有哪些1.4.Prometheus有什么特点1.5.Metric的几种类型&#xff1f;分别是什么&#xff1f;1.6.Prometheus的优点和缺点1.7.Prometheus怎么采集数据1.8.Prometheus怎么获取采集对象1.9.Promet…

【测试面试】头条大厂,测试开发岗真实一面。你能抵得住吗?

目录&#xff1a;导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09;前言 小吴&#xff1a; 现…

PHP7中Reids键空间通知配合TP5实现分布式延时任务的方法

本篇文章主要给大家介绍PHP7中Reids键空间通知配合TP5实现分布式延时任务的方法&#xff0c;希望对需要的朋友有所帮助&#xff01; 测试环境&#xff1a;windows 10 phpStudy 配置redis配置文件 redis.windows.conf notify-keyspace-events "Ex" 重启redis服务 …

超实用的公众号运营攻略分享,纯干货

很多小伙伴抱怨&#xff0c;公众号运营真的越来越难做了&#xff01; 每天会因为少得可怜的阅读量发愁&#xff0c;每天会因为纠结写什么选题发愁&#xff0c;每天更会因为公众号没有什么起色而感到无力。 现阶段公众号运营趋于饱和状态&#xff0c;公众号创建门槛低&#xf…

【unity细节】基于unity子对象(如相机)为什么无法进行z轴的拖拽移动和z轴自动归位的问题

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! 本文由 秩沅 原创 收录于专栏&#xff1a;unity细节和bug ⭐基于unity子对象为什么无法进行z轴的拖拽移动和z轴自动归位⭐ 文章目录⭐基于u…