stanley 路徑跟蹤控制算法

文章目錄

  • 寫在前面的話
  • 算法思路
  • 核心代碼
    • 1 路徑發布
    • 2 獲取車子當前位置
    • 3 預瞄路徑點
    • 4 計算航向誤差
    • 5 計算橫向誤差
  • 完整控制代碼
  • 演示視頻

寫在前面的話

軌跡跟蹤 Trajectory Tracking路徑跟蹤 Path Following 是機器人控制和自動駕駛領域中的兩個核心概念,盡管它們都涉及讓系統沿預定路徑運動,但目標和方法存在顯著差異。以下是它們的區別及實際應用場景的分析:

在這里插入圖片描述

本文介紹的 stenley 控制算法是一個路徑跟蹤算法,是根據前輪的轉向來控制車子按指定路徑行駛,下圖來自國防科技大學的論文《Ribbon model based path tracking method for autonomous ground vehicles》。

在這里插入圖片描述

算法思路

在這里插入圖片描述

上圖是我按自己思路畫出的示意圖

圖案作用
黑色小箭頭發布的路徑信息(posestamped數據,包括坐標和方向)
白色大箭頭航向對齊后前輪方向
綠色大箭頭最終的前輪方向
藍色大箭頭初始前輪方向
θ1小橫向偏角
θ2大橫向偏角

理解 stanley 控制算法最核心的是分為兩步,一個是擺正航向,一個是貼近路徑。擺正航向可以理解車子可以跟著路徑平行運動,貼近路徑可以理解為讓兩個路徑的平行的運行重合。

參考鏈接:Stanley理論篇

核心代碼

1 路徑發布

這里路徑的發布很簡單,路徑點的數據格式用的是 PoseStamped ,需要點的坐標和方向(四元數表示),下面代碼設置的是一個直線路徑。

注意:要設置參考系是 world,因為本文的環境是在 gazebo 的 world 中進行仿真

import rclpy
import csv
import os
import numpy as np
from rclpy.node import Node
from launch_ros.substitutions import FindPackageShare
from tf_transformations import quaternion_from_euler
from geometry_msgs.msg import PoseStamped
from nav_msgs.msg import Pathclass PathPublisher(Node):def __init__(self):super().__init__('path_publisher')# Initializing the titles and rows listYY = -9.5self.path = [[5,YY,0,0,0,0],[7,YY,0,0,0,0], [9,YY,0,0,0,0], [11,YY,0,0,0,0], [13,YY,0,0,0,0]]self.direction = 0self.path_points = 1# Create path publisherself.publisher_ = self.create_publisher(Path, '/path_points', 10)timer_period = 0.1self.timer = self.create_timer(timer_period, self.timer_callback)self.i = 0def timer_callback(self):path = Path()for i in range(len(self.path)):points = PoseStamped()points.header.frame_id = 'world'row = self.path[i]#[(self.i + i) % self.path_points]points.pose.position.x = float(row[0])points.pose.position.y = float(row[1])points.pose.position.z = float(self.direction)x,y,z,w = quaternion_from_euler(row[3],row[4],row[5])points.pose.orientation.x = float(x)points.pose.orientation.y = float(y)points.pose.orientation.z = float(z)points.pose.orientation.w = float(w)path.poses.append(points)path.header.frame_id = 'world'self.publisher_.publish(path)self.get_logger().info('Publishing point no %f: %f'%(self.i % self.path_points, float(self.path[self.i % self.path_points][0])))def main(args=None):rclpy.init(args=args)minimal_subscriber = PathPublisher()rclpy.spin(minimal_subscriber)minimal_subscriber.destroy_node()rclpy.shutdown()if __name__ == '__main__':main()

2 獲取車子當前位置

在之前的車子控制中選用的阿克曼前輪轉向的設置,在gazebo中會發布模型的 tf 話題信息,話題里面包含 tf/odom_demo/base_footprint 信息,可以查看車子的 pose 參數( xyz 和 rpy )

在這里插入圖片描述

        self.tf_buffer = Buffer()self.tf_listener = TransformListener(self.tf_buffer, self)self.timer = self.create_timer(1.0, self.lookup_transform)=======================================================================================     def lookup_transform(self):try:self.last_time = self.curr_timetrans = self.tf_buffer.lookup_transform('odom_demo', 'base_footprint', rclpy.time.Time())# Orientationself.curr_qw = trans.transform.rotation.wself.curr_qx = trans.transform.rotation.xself.curr_qy = trans.transform.rotation.yself.curr_qz = trans.transform.rotation.z# PositionR = quaternion_rotation_matrix([self.curr_qw, self.curr_qx, self.curr_qy, self.curr_qz])forward_dir = R[:2, 0]  # 提取X軸(前進方向)self.curr_x = trans.transform.translation.x #+ 0.5*forward_dir[0] #位置提前可以提前轉彎self.curr_y = trans.transform.translation.y #+ 0.5*forward_dir[1]self.curr_z = trans.transform.translation.zself.get_logger().info(f"Translation: {trans.transform.translation}")self.get_logger().info(f"Rotation: {trans.transform.rotation}")# Timeself.curr_time = time.time()except (tf2_ros.LookupException, tf2_ros.ConnectivityException, tf2_ros.ExtrapolationException):self.get_logger().warn("Could not find global pose of car!!")

3 預瞄路徑點

代碼原理是計算路徑所有點的坐標和車子的坐標的歐式距離,最小的就是預備的預瞄路徑點 ref_point
如果預設的最大預瞄距離(self.lookahead_distance)小于預備的預瞄路徑點到車子的距離,就選用當前的預瞄路徑點;
但是如果預測的最大預瞄距離大于預備的預瞄路徑點到車子的距離,就選擇路徑的下一個點,如果都大于
就選擇路徑最后的一個點。

     ref_points = np.array([[p[0], p[1]] for p in self.ref_path])curr_pose = np.array([self.curr_x, self.curr_y])nearest_idx = np.argmin(np.linalg.norm(ref_points - curr_pose, axis=1))# Find the lookahead point on the reference trajectory 找最近點前面的點for i in range(nearest_idx, len(self.ref_path)):ref_point = np.array([self.ref_path[i][0], self.ref_path[i][1]])if np.linalg.norm(ref_point - curr_pose) > self.lookahead_distance:lookahead_point = ref_pointlpn_idx = ibreakelse:lookahead_point = ref_points[-1]lpn_idx = -1

4 計算航向誤差

航向誤差就是車子當前的航向和當前預瞄路徑點的方向之間的偏差,通過向量叉積的符號明確車輛與路徑的相對位置,適用于任意方向的航向和路徑指向。

    def _yaw(self, q_vehicle, q_path):# 轉換為方向向量vehicle_yaw = self.quat_to_yaw(q_vehicle)path_yaw = self.quat_to_yaw(q_path)vehicle_dir = np.array([np.cos(vehicle_yaw), np.sin(vehicle_yaw)])path_dir = np.array([np.cos(path_yaw), np.sin(path_yaw)])# 計算有符號偏角dot = np.dot(vehicle_dir, path_dir)cross = vehicle_dir[0] * path_dir[1] - vehicle_dir[1] * path_dir[0]alpha = np.arctan2(cross, dot)# print(f"偏角: {np.degrees(alpha):.1f} 度")return alphadef quat_to_yaw(self, q):[qw, qx, qy, qz] = q"""四元數轉偏航角(弧度)"""t3 = 2.0 * (qw * qz + qx * qy)t4 = 1.0 - 2.0 * (qy**2 + qz**2)return np.arctan2(t3, t4)===========================================================================
R_trackj = [self.ref_path[lpn_idx][5], self.ref_path[lpn_idx][2], self.ref_path[lpn_idx][3], self.ref_path[lpn_idx][4]]#軌跡方向
R_car = [self.curr_qw, self.curr_qx, self.curr_qy, self.curr_qz]
yaw = self._yaw(R_car, R_trackj)

5 計算橫向誤差

這個橫向誤差是車子到預瞄路徑點的航向的距離,簡單理解就是點到線的距離,進一步可以理解成車子相對于預瞄路徑點航向坐標系的y軸坐標,航向誤差最終要得到轉向角delta

參考鏈接: 利用向量推導坐標旋轉公式(方案一)

在這里插入圖片描述

    def calculate_lateral_error(self, x, y, path_x, path_y, path_yaw):# 計算到路徑點切線的垂直距離dx = path_x - xdy = path_y - yreturn dx * np.sin(path_yaw) + dy * np.cos(path_yaw)
===========================================================================================
ex =  self.calculate_lateral_error(self.curr_x, self.curr_y, lookahead_point[0], lookahead_point[1],quat2eulers(R_trackj)[-1]) # 橫向誤差
self.speed = 0.2
delta2 = np.arctan2(ex, self.lookahead_distance) #       

完整控制代碼

import rclpy
from rclpy.node import Node
from geometry_msgs.msg import PoseStamped, Twist,  Point, TransformStamped
import tf2_ros
from tf2_ros.buffer import Buffer
from tf2_ros.transform_listener import TransformListener
from nav_msgs.msg import Path
import math
from rclpy.qos import QoSProfile, ReliabilityPolicy, HistoryPolicy, QoSDurabilityPolicy
import numpy as np
import time
from tf_transformations import quaternion_from_eulerdef quat2eulers(q) -> tuple:"""Compute yaw-pitch-roll Euler angles from a quaternion.@author: michaelwroArgs----q0: Scalar component of quaternion. [qw]q1, q2, q3: Vector components of quaternion. [qx, qy, qz]Returns-------(roll, pitch, yaw) (tuple): 321 Euler angles in radians"""[q0, q1, q2, q3] = qroll = math.atan2(2 * ((q2 * q3) + (q0 * q1)),q0**2 - q1**2 - q2**2 + q3**2)  # radianspitch = math.asin(2 * ((q1 * q3) - (q0 * q2)))yaw = math.atan2(2 * ((q1 * q2) + (q0 * q3)),q0**2 + q1**2 - q2**2 - q3**2)return (roll, pitch, yaw)
def quaternion_rotation_matrix(Q):"""Covert a quaternion into a full three-dimensional rotation matrix.Input:param Q: A 4 element array representing the quaternion (q0,q1,q2,q3) Output:return: A 3x3 element matrix representing the full 3D rotation matrix. This rotation matrix converts a point in the local reference frame to a point in the global reference frame."""# Extract the values from Qq0 = Q[0]q1 = Q[1]q2 = Q[2]q3 = Q[3]# First row of the rotation matrixr00 = 2 * (q0 * q0 + q1 * q1) - 1r01 = 2 * (q1 * q2 - q0 * q3)r02 = 2 * (q1 * q3 + q0 * q2)# Second row of the rotation matrixr10 = 2 * (q1 * q2 + q0 * q3)r11 = 2 * (q0 * q0 + q2 * q2) - 1r12 = 2 * (q2 * q3 - q0 * q1)# Third row of the rotation matrixr20 = 2 * (q1 * q3 - q0 * q2)r21 = 2 * (q2 * q3 + q0 * q1)r22 = 2 * (q0 * q0 + q3 * q3) - 1# 3x3 rotation matrixrot_matrix = np.array([[r00, r01, r02],[r10, r11, r12],[r20, r21, r22]])return rot_matrixdef quaternion_multiply(q1, q2):"""四元數乘法(Hamilton約定)"""[w1, x1, y1, z1] = q1[w2, x2, y2, z2] = q2return np.array([w1*w2 - x1*x2 - y1*y2 - z1*z2,w1*x2 + x1*w2 + y1*z2 - z1*y2,w1*y2 - x1*z2 + y1*w2 + z1*x2,w1*z2 + x1*y2 - y1*x2 + z1*w2])def rotation_angles(matrix, order):"""inputmatrix = 3x3 rotation matrix (numpy array)oreder(str) = rotation order of x, y, z : e.g, rotation XZY -- 'xzy'outputtheta1, theta2, theta3 = rotation angles in rotation order"""r11, r12, r13 = matrix[0]r21, r22, r23 = matrix[1]r31, r32, r33 = matrix[2]if order == 'xzx':theta1 = np.arctan(r31 / r21)theta2 = np.arctan(r21 / (r11 * np.cos(theta1)))theta3 = np.arctan(-r13 / r12)elif order == 'xyx':theta1 = np.arctan(-r21 / r31)theta2 = np.arctan(-r31 / (r11 *np.cos(theta1)))theta3 = np.arctan(r12 / r13)elif order == 'yxy':theta1 = np.arctan(r12 / r32)theta2 = np.arctan(r32 / (r22 *np.cos(theta1)))theta3 = np.arctan(-r21 / r23)elif order == 'yzy':theta1 = np.arctan(-r32 / r12)theta2 = np.arctan(-r12 / (r22 *np.cos(theta1)))theta3 = np.arctan(r23 / r21)elif order == 'zyz':theta1 = np.arctan(r23 / r13)theta2 = np.arctan(r13 / (r33 *np.cos(theta1)))theta3 = np.arctan(-r32 / r31)elif order == 'zxz':theta1 = np.arctan(-r13 / r23)theta2 = np.arctan(-r23 / (r33 *np.cos(theta1)))theta3 = np.arctan(r31 / r32)elif order == 'xzy':theta1 = np.arctan(r32 / r22)theta2 = np.arctan(-r12 * np.cos(theta1) / r22)theta3 = np.arctan(r13 / r11)elif order == 'xyz':theta1 = np.arctan(-r23 / r33)theta2 = np.arctan(r13 * np.cos(theta1) / r33)theta3 = np.arctan(-r12 / r11)elif order == 'yxz':theta1 = np.arctan(r13 / r33)theta2 = np.arctan(-r23 * np.cos(theta1) / r33)theta3 = np.arctan(r21 / r22)elif order == 'yzx':theta1 = np.arctan(-r31 / r11)theta2 = np.arctan(r21 * np.cos(theta1) / r11)theta3 = np.arctan(-r23 / r22)elif order == 'zyx':theta1 = np.arctan(r21 / r11)theta2 = np.arctan(-r31 * np.cos(theta1) / r11)theta3 = np.arctan(r32 / r33)elif order == 'zxy':theta1 = np.arctan(-r12 / r22)theta2 = np.arctan(r32 * np.cos(theta1) / r22)theta3 = np.arctan(-r31 / r33)theta1 = theta1 * 180 / np.pitheta2 = theta2 * 180 / np.pitheta3 = theta3 * 180 / np.pireturn (theta1, theta2, theta3)class StanleyControllerNode(Node):def __init__(self):super().__init__('stanley_controller')self.get_logger().info('Stanley Controller start!')# Current poseself.tf_buffer = Buffer()self.tf_listener = TransformListener(self.tf_buffer, self)self.timer = self.create_timer(1.0, self.lookup_transform)# self.current_pose_subscription = self.create_subscription(PoseStamped,'/ground_truth/pose', self.current_pose_listener_callback, 10)# Positionself.curr_x = Noneself.curr_y = Noneself.curr_z = None# Orientationself.curr_qw = Noneself.curr_qx = Noneself.curr_qy = Noneself.curr_qz = None# Timeself.curr_time = None# Last position and timeself.last_time = Noneself.last_x = Noneself.last_y = None# # Reference trajectoryself.reference_trajectory_subscription = self.create_subscription(Path, '/path_points', self.reference_trajectory_listener_callback, 10)# Positionself.ref_path = Noneself.ref_side = None# Control publisherself.control_publisher = self.create_publisher(Twist, '/car_nav2/cmd_demo', 10)control_publisher_timer_period = 1/50  # secondsself.control_publisher_timer = self.create_timer(control_publisher_timer_period, self.control_publisher_timer_callback)control_timer = 0.1 # secondsself.control_timer = self.create_timer(control_timer, self.control_timer_callback)# Steering angleself.theta = None # speedself.speed = None # Controller parameterself.K = 0.5self.last_u = 0self.lookahead_distance = 1.0def lookup_transform(self):try:self.last_time = self.curr_timetrans = self.tf_buffer.lookup_transform('odom_demo', 'base_footprint', rclpy.time.Time())# Orientationself.curr_qw = trans.transform.rotation.wself.curr_qx = trans.transform.rotation.xself.curr_qy = trans.transform.rotation.yself.curr_qz = trans.transform.rotation.z# PositionR = quaternion_rotation_matrix([self.curr_qw, self.curr_qx, self.curr_qy, self.curr_qz])forward_dir = R[:2, 0]  # 提取X軸(前進方向)self.curr_x = trans.transform.translation.x #+ 0.5*forward_dir[0] #位置提前可以提前轉彎self.curr_y = trans.transform.translation.y #+ 0.5*forward_dir[1]self.curr_z = trans.transform.translation.zself.get_logger().info(f"Translation: {trans.transform.translation}")self.get_logger().info(f"Rotation: {trans.transform.rotation}")# Timeself.curr_time = time.time()except (tf2_ros.LookupException, tf2_ros.ConnectivityException, tf2_ros.ExtrapolationException):self.get_logger().warn("Could not find global pose of car!!")# def current_pose_listener_callback(self, msg:PoseStamped):#     # Previous#     self.last_time = self.curr_time#     self.last_x = self.curr_x#     self.last_y = self.curr_y#     # Position#     self.curr_x = msg.pose.position.x#     self.curr_y = msg.pose.position.y#     self.curr_z = msg.pose.position.z#     # Orientation#     self.curr_qw = msg.pose.orientation.w#     self.curr_qx = msg.pose.orientation.x#     self.curr_qy = msg.pose.orientation.y#     self.curr_qz = msg.pose.orientation.z#     # Time#     self.curr_time = msg.header.stamp.nanosecdef reference_trajectory_listener_callback(self, msg:Path):self.ref_path = []for pose in msg.poses:x = pose.pose.position.xy = pose.pose.position.yself.ref_side = pose.pose.position.zqx = pose.pose.orientation.xqy = pose.pose.orientation.yqz = pose.pose.orientation.zqw = pose.pose.orientation.wself.ref_path.append([x, y, qx, qy, qz, qw])def publish_control(self, theta, speed):vel_msg = Twist()   vel_msg.linear.x = speedvel_msg.angular.z = theta #左轉是正數,車輪右轉是負數self.control_publisher.publish(vel_msg)def control_publisher_timer_callback(self):if (self.theta is not None) and (self.speed is not None):self.publish_control(self.theta, self.speed)self.get_logger().info(f'Controller output: theta: {self.theta}, speed: {self.speed}')else:self.get_logger().info(f'Stanley Controller wrong control!')def control_timer_callback(self):# Calculate controlif (self.ref_path is not None) and (self.curr_x is not None) and (self.last_time is not None):# If the robot reaches the goal, reset is_goal_pose_received 到達目標(距離小于0.05)goal_point = np.array([self.ref_path[-1][0], self.ref_path[-1][1]])curr_xy = np.array([self.curr_x, self.curr_y])if np.linalg.norm(curr_xy - goal_point) < 0.1:self.theta = 0.0self.speed = 0.0self.get_logger().info(f'Reached goal. Goal pose reset')return# 橫向誤差ref_points = np.array([[p[0], p[1]] for p in self.ref_path])curr_pose = np.array([self.curr_x, self.curr_y])nearest_idx = np.argmin(np.linalg.norm(ref_points - curr_pose, axis=1))# Find the lookahead point on the reference trajectory 找最近點前面的點for i in range(nearest_idx, len(self.ref_path)):ref_point = np.array([self.ref_path[i][0], self.ref_path[i][1]])if np.linalg.norm(ref_point - curr_pose) > self.lookahead_distance:lookahead_point = ref_pointlpn_idx = ibreakelse:lookahead_point = ref_points[-1]lpn_idx = -1R_trackj = [self.ref_path[lpn_idx][5], self.ref_path[lpn_idx][2], self.ref_path[lpn_idx][3], self.ref_path[lpn_idx][4]]#軌跡方向R_car = [self.curr_qw, -self.curr_qx, -self.curr_qy, -self.curr_qz]#車輛當前方向 四元數共軛W = quaternion_multiply(R_car,  R_trackj)[0]yaw = -2*np.arccos(np.clip(abs(W), 0.0, 1.0))ex =  self.calculate_lateral_error(self.curr_x, self.curr_y, lookahead_point[0], lookahead_point[1],quat2eulers(R_trackj)[-1]) # 橫向誤差self.speed = 0.2delta2 = np.arctan2(ex, self.lookahead_distance) #           self.get_logger().info(f'e: {ex}, delta: {delta2}, yaw: {yaw}')self.theta = np.clip((yaw + delta2), -0.5, 0.5)def calculate_lateral_error(self, x, y, path_x, path_y, path_yaw):# 計算到路徑點切線的垂直距離dx = path_x - xdy = path_y - yreturn -dx * np.sin(path_yaw) + dy * np.cos(path_yaw)def main(args=None):rclpy.init(args=args)StanleyController = StanleyControllerNode()rclpy.spin(StanleyController)StanleyController.destroy_node()rclpy.shutdown()if __name__ == '__main__':main()

演示視頻

stanley 控制算法(阿克曼前輪轉向小車)

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/73350.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/73350.shtml
英文地址,請注明出處:http://en.pswp.cn/web/73350.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Qt中通過QLabel實時顯示圖像

Qt中的QLabel控件用于顯示文本或圖像&#xff0c;不提供用戶交互功能。以下測試代碼用于從內置攝像頭獲取圖像并實時顯示&#xff1a; Widgets_Test.h&#xff1a; class Widgets_Test : public QMainWindow {Q_OBJECTpublic:Widgets_Test(QWidget *parent nullptr);~Widgets…

在STM32F7上實現CAN總線收發隊列

下面我將提供一個完整的STM32F7 CAN總線通信實現方案&#xff0c;包含中斷驅動的收發隊列管理。 1. CAN總線配置與隊列定義 can_bus.h #ifndef __CAN_BUS_H #define __CAN_BUS_H#include "stm32f7xx_hal.h" #include "queue.h"// CAN消息結構體 typedef …

【例3.5】位數問題(信息學奧賽一本通-1313)

【題目描述】 在所有的N位數中&#xff0c;有多少個數中有偶數個數字3?由于結果可能很大&#xff0c;你只需要輸出這個答案對12345取余的值。 【輸入】 讀入一個數N(N≤1000)。 【輸出】 輸出有多少個數中有偶數個數字3。 【輸入樣例】 2 【輸出樣例】 73 【題解代碼】 #incl…

pyQt學習筆記——Qt資源文件(.qrc)的創建與使用

Qt資源文件&#xff08;.qrc&#xff09;的創建與使用 1. 選擇打開資源2. 創建新資源3. 添加資源文件夾4. 選擇要加載的圖片文件5. 編譯resource.qrc文件6. 替換PySlide6為PyQt57. 其他說明 1. 選擇打開資源 在Qt項目中&#xff0c;可以通過windowIcon點擊選擇打開資源。 2. 創…

光電效應及普朗克常數的測定數據處理 Python實現

內容僅供參考&#xff0c;如有錯誤&#xff0c;歡迎指正&#xff0c;如有疑問&#xff0c;歡迎交流。 因為我不會Excel所以只能用Python來處理 祝大家早日擺脫物理實驗的苦海 用到的一些方法 PCHIP &#xff08;分段三次埃爾米特插值多項式&#xff09; 因為實驗時記錄的數…

2025最新3個wordpress好用的主題

紅色大氣的wordpress企業主題&#xff0c;適合服務行業的公司搭建企業官方網站使用。是一款專為中小企業和個人開發者設計的WordPress主題&#xff0c;旨在提供專業的網站構建解決方案。 通過此WordPress主題&#xff0c;用戶可以輕松創建和維護一個專業的企業網站&#xff0c…

OLLVM 增加 CC++ 字符串加密功能

版權歸作者所有&#xff0c;如有轉發&#xff0c;請注明文章出處&#xff1a;https://cyrus-studio.github.io/blog/ 前言 當我們如果沒有對字符串進行加密&#xff0c;使用 IDA 反匯編一下 so 可以看到 C 代碼中的字符串就直接暴露了。 字符串加密原理 sobf.c #include <…

桑福德·韋爾策劃美國捷運公司收購南美銀行案例分析

桑福德韋爾(Sanford I. Weill)在1981年策劃美國捷運公司(American Express)以5.5億美元收購南美貿易發展銀行所屬外國銀行機構的案例中,展現了其作為戰略家與執行者的雙重能力。這一交易的流程和韋爾的具體行為可從以下六個關鍵環節解析: 一、戰略定位與目標篩選 戰略目標…

人工智能與區塊鏈融合:開啟數字信任新時代

引言 在當今數字化飛速發展的時代&#xff0c;人工智能&#xff08;AI&#xff09;與區塊鏈技術正以前所未有的速度改變著我們的生活和工作方式。AI以其強大的數據處理和智能決策能力&#xff0c;為各行業帶來了效率的飛躍&#xff1b;而區塊鏈則以其去中心化、不可篡改的特性…

自動化逆向框架使用(Objection+Radare2)

1. 工具鏈架構與核心優勢 1.1 動靜結合逆向體系 graph LR A[動態分析] -->|Objection實時Hook| B[關鍵點定位] B --> C[行為數據捕獲] D[靜態分析] -->|Radare2深度解析| E[控制流重建] E --> F[漏洞模式識別] B --> F C --> F 組合優勢對比&…

流式ETL配置指南:從MySQL到Elasticsearch的實時數據同步

流式ETL配置指南&#xff1a;從MySQL到Elasticsearch的實時數據同步 場景介紹 假設您運營一個電商平臺&#xff0c;需要將MySQL數據庫中的訂單、用戶和產品信息實時同步到Elasticsearch&#xff0c;以支持實時搜索、分析和儀表盤展示。傳統的批處理ETL無法滿足實時性要求&…

Docker-Volume數據卷詳講

Docker數據卷-Volume 一&#xff1a;Volume是什么&#xff0c;用來做什么的 當刪除docker容器時&#xff0c;容器內部的文件就會跟隨容器所銷毀&#xff0c;在生產環境中我們需要將數據持久化保存&#xff0c;就催生了將容器內部的數據保存在宿主機的需求&#xff0c;volume …

單片機和微控制器知識匯總——《器件手冊--單片機、數字信號處理器和可編程邏輯器件》

目錄 四、單片機和微控制器 4.1 單片機(MCU/MPU/SOC) 一、定義 二、主要特點 三、工作原理 四、主要類型 五、應用領域 六、選型與設計注意事項 七、發展趨勢 4.2 數字信號處理器(DSP/DSC) ?編輯?編輯 一、定義 二、工作原理 三、結構特點 四、應用領域 五、選型與設計注…

macOS 安裝 Miniconda

macOS 安裝 Miniconda 1. Quickstart install instructions2. 執行3. shell 上初始化 conda4. 關閉 終端登錄用戶名前的 base參考 1. Quickstart install instructions mkdir -p ~/miniconda3 curl https://repo.anaconda.com/miniconda/Miniconda3-latest-MacOSX-arm64.sh -o…

高數下---8.1平面與直線

目錄 平面的確定 直線的確定 若要求某一直線或平面就根據要素來求。 例題 平面中的特殊情況 平面中的解題思路 直線的解題思路 平面的確定 兩要素 一 一點 二 傾斜角 即法向量 點法式 可化為一般式 Ax By Cz D 0; (A,B,C) 即法向量&#xff1b; 改變D 即…

CMS遷移中SEO優化整合步驟詳解

內容概要 在CMS遷移過程中&#xff0c;系統化的規劃與執行是保障SEO排名穩定性的核心。首先需明確遷移流程的關鍵階段&#xff0c;包括數據備份、URL適配、元數據同步及安全配置等環節。其中&#xff0c;數據備份不僅需覆蓋原始數據庫與靜態資源&#xff0c;還需驗證備份文件的…

存儲過程、存儲函數與觸發器詳解(MySQL 案例)

存儲過程、存儲函數與觸發器詳解&#xff08;MySQL 案例&#xff09; 一、存儲過程&#xff08;Stored Procedure&#xff09; 定義 存儲過程是預先編譯好并存儲在數據庫中的一段 SQL 代碼集合&#xff0c;可以接收參數、執行邏輯操作&#xff08;如條件判斷、循環&#xff09;…

Python:進程間的通信,進程的操作隊列

進程間的隊列&#xff1a; 隊列的基本操作&#xff1a; 入隊&#xff1a;將數據放到隊列尾部 出隊&#xff1a;從隊列的頭部取出一個元素 maxsize&#xff1a;隊列中能存放數據個數的上限(整數)&#xff0c;一旦達到上限插入會導致阻塞&#xff0c;直到隊列中的數據被消費掉 …

【C++初階】--- 類與對象(中)

1.類的默認成員函數 默認成員函數就是??沒有顯式實現&#xff0c;編譯器會?動?成的成員函數稱為默認成員函數。?個類&#xff0c;我們不寫的情況下編譯器會默認?成以下6個默認成員函數&#xff0c;我們主要需要掌握前4個&#xff0c;后兩個了解以下即可&#xff0c;默認…

python處理音頻相關的庫

1 音頻信號采集與播放 pyaudio import sys import pyaudio import wave import timeCHUNK 1024 FORMAT pyaudio.paInt16 CHANNELS 1#僅支持單聲道 RATE 16000 RECORD_SECONDS 3#更改錄音時長#錄音函數&#xff0c;生成wav文件 def record(file_name):try:os.close(file_…