LQR的横向控制与算法仿真实现

news2025/1/8 13:23:53

文章目录

    • 1. 引言
    • 2. 车辆运动学线性离散模型
    • 3. LQR求解
    • 4. 算法和仿真实现

1. 引言

在现代控制理论的领域中,线性二次型调节器(Linear Quadratic Regulator,简称LQR)被广泛认可为一种高效的优化控制方法。LQR的核心优势在于其能力,通过最小化一个定义良好的二次型代价函数,来设计出能够引导系统达到预定性能指标的控制策略。尽管LQR最初是为线性时不变系统(Linear Time-Invariant, LTI)设计的,但其在稳定性和性能优化方面的卓越表现,已经使得它在航空航天、机器人技术、汽车工业等多个高端技术领域得到了广泛应用。

在车辆横向控制的具体应用场景中,我们面临车辆运动学模型的非线性特性的挑战。为了克服这一难题,我们通常采用线性化技术,将非线性模型转化为线性近似模型,从而使得LQR方法得以应用。此外,为了适应计算机控制系统的实现需求,模型的离散化处理也成为了一个不可或缺的步骤。通过将连续时间模型转换为离散时间模型,我们可以有效地利用LQR算法进行控制设计,实现对车辆横向运动的精确控制。

2. 车辆运动学线性离散模型

在车辆运动学模型的线性化和离散化及代码实现中,我们详细介绍了单车模型的线性化和离散化,其离散线性化后的微分方程如下
X e ( k + 1 ) = ( T A + I ) A X e ( k ) + T B u e ( k ) = [ 1 0 − T v r s i n φ r 0 1 T v r c o s φ r 0 0 1 ] [ x − x r y − y r φ − φ r ] + [ T c o s φ r 0 T s i n φ r 0 T v r t a n δ f r L T v r L c o s 2 δ f r ] [ v − v r δ − δ r ] (1) \begin{align*} X_e(k+1)&=(TA+I)AX_e(k)+TBu_e(k)\\ &= \begin{bmatrix} 1 & 0 & -Tv_rsin\varphi_r\\ 0 & 1 & Tv_rcos\varphi_r\\ 0 & 0 & 1\\ \end{bmatrix} \begin{bmatrix} x-x_r\\ y-y_r\\ \varphi-\varphi_r\\ \end{bmatrix} + \begin{bmatrix} Tcos\varphi_r & 0 \\ Tsin\varphi_r & 0 \\ \frac{Tv_r tan\delta_{fr}}{L} & \frac{Tv_r}{Lcos^2\delta_{fr}} \\ \end{bmatrix} \begin{bmatrix} v-v_r\\ \delta-\delta_r\\ \end{bmatrix} \\ \end{align*} \tag{1} Xe(k+1)=(TA+I)AXe(k)+TBue(k)= 100010TvrsinφrTvrcosφr1 xxryyrφφr + TcosφrTsinφrLTvrtanδfr00Lcos2δfrTvr [vvrδδr](1)
其中 T T T为采样步长, I I I为3x3的单位矩阵。

这里的 ( T A + I ) A (TA+I)A (TA+I)A为该系统的控制矩阵, T B TB TB为输入矩阵, u e ( k ) u_e(k) ue(k)为输入控制量误差,状态 X e ( K + 1 ) X_e(K+1) Xe(K+1)为状态误差,在控制过程中,我们期望状态误差逐渐稳定趋近为0,因此,定义代价函数
J = ∑ k = 0 N − 1 ( x k T Q x k + u k T R u k ) + x N T F x N (2) J = \sum_{k=0}^{N-1} (x_k^T Q x_k + u_k^T R u_k) + x_N^T F x_N \tag{2} J=k=0N1(xkTQxk+ukTRuk)+xNTFxN(2)
其中:

  • x k x_k xk 是在离散时间步 k k k的系统状态。
  • u k u_k uk是在时间步 k k k的控制输入。
  • Q Q Q是状态权重 m × m m \times m m×m的半正定方阵,用于衡量状态的代价,通常将其设计为对角矩阵。
  • $R 是控制权重 是控制权重 是控制权重n \times n$的正定对称矩阵,用于衡量控制输入的代价,通常将其设计为对角矩阵。
  • F F F是末端状态权重 m × m m \times m m×m的半正定方阵,用于衡量最终状态的代价,通常将其设计为对角矩阵。
  • N N N是控制的总时间步数。

3. LQR求解

采用LQR算法进行控制率求解的步骤(推导过程详见LQR求解推导及代码实现)概括为:

  1. 确定迭代范围 N N N

  2. 设置迭代初始值 P N = F P_{N}=F PN=F,其中 Q f = Q Q_f=Q Qf=Q

  3. 循环迭代, 从后往前 k = N − 1 , … , 0 k=N-1, \ldots, 0 k=N1,,0
    K k = ( B T P k + 1 B + R ) − 1 B T P k + 1 A P k = ( A − B K k ) T P k + 1 ( A − B K k ) + Q + K k T R K k \begin{align*} K_{k}&=(B^TP_{k+1}B + R)^{-1}B^TP_{k+1}A\\ P_{k}&=(A-BK_{k})^T P_{k+1} (A-BK_{k}) + Q + K_{k}^T R K_{k} \end{align*} KkPk=(BTPk+1B+R)1BTPk+1A=(ABKk)TPk+1(ABKk)+Q+KkTRKk

    判断 K k K_k Kk K k + 1 K_{k+1} Kk+1每个对应元素的差值是否小于 ϵ \epsilon ϵ(这里 ϵ \epsilon ϵ代表迭代精度,一般是非常小的数字),如果都小于则跳出循环,此时的 K t K_t Kt即为最终的最优反馈矩阵,否则继续循环。

  4. 最终得优化的控制量 u t ∗ = − K t x t u_{t}^{*}=-K_{t} x_{t} ut=Ktxt

4. 算法和仿真实现

这里我们将权重矩阵 Q Q Q R R R F F F分别设为
Q = [ 8 0 0 0 8 0 0 0 8 ] R = [ 2 0 0 0 2 0 0 0 2 ] F = [ 10 0 0 0 10 0 0 0 10 ] (3) Q=\begin{bmatrix} 8 & 0 & 0\\ 0 & 8 & 0\\ 0 & 0 & 8\\ \end{bmatrix} \\ R=\begin{bmatrix} 2 & 0 & 0\\ 0 & 2 & 0\\ 0 & 0 & 2\\ \end{bmatrix} \\ F=\begin{bmatrix} 10 & 0 & 0\\ 0 & 10 & 0\\ 0 & 0 & 10\\ \end{bmatrix} \tag{3} Q= 800080008 R= 200020002 F= 100001000010 (3)
实际使用过程可以根据需要动态调整相关权重。其具体实现如下

kinematicsLQR.py

import numpy as np
import math
from scipy.linalg import inv
from kinematic_bicycle_model import update_ABMatrix


N = 200  # 迭代范围
EPS = 1e-4  # 迭代精度
Q = np.eye(3) * 8
R = np.eye(2) * 2
F = np.eye(3) * 10


def cal_lqr_k(A, B, Q, R, F):
    """计算LQR反馈矩阵K
    Args:
        A : mxm状态矩阵A
        B : mxn状态矩阵B
        Q : Q是状态权重mxm的半正定方阵,用于衡量状态的代价,通常将其设计为对角矩阵。
        R : R是控制权重nxn的正定对称矩阵,用于衡量控制输入的代价,通常将其设计为对角矩阵。
        F : F是末端状态权重mxm的半正定方阵,用于衡量最终状态的代价,通常将其设计为对角矩阵。
    Returns:
        K : 反馈矩阵K
    """
    # 设置迭代初始值
    P = F
    # 循环迭代
    for t in range(N):
        K_t = inv(B.T @ P @ B + R) @ B.T @ P @ A
        P_t = (A - B @ K_t).T @ P @ (A - B @ K_t) + Q + K_t.T @ R @ K_t
        if (abs(P_t - P).max() < EPS):
            break
        P = P_t
    return K_t


def normalize_angle(angle):
    a = math.fmod(angle + np.pi, 2 * np.pi)
    if a < 0.0:
        a += (2.0 * np.pi)
    return a - np.pi


def calc_preparation(vehicle, ref_path):
    """
    计算角度误差theta_e、横向误差er、曲率rk和索引index
    """

    rx, ry, ref_yaw, ref_kappa = ref_path[:, 0], ref_path[:, 1], ref_path[:, 2], ref_path[:, 4]
    dx = [vehicle.x - icx for icx in rx]
    dy = [vehicle.y - icy for icy in ry]
    d = np.hypot(dx, dy)
    index = np.argmin(d)
    rk = ref_kappa[index]
    ryaw = ref_yaw[index]
    rdelta = math.atan2(vehicle.L * rk, 1)

    vec_nr = np.array([math.cos(ryaw + math.pi / 2.0),
                       math.sin(ryaw + math.pi / 2.0)])

    vec_target_2_rear = np.array([vehicle.x - rx[index],
                                  vehicle.y - ry[index]])

    er = np.dot(vec_target_2_rear, vec_nr)
    theta_e = normalize_angle(vehicle.yaw - ryaw)

    return dx[index], dy[index], theta_e, er, rdelta, ryaw, index


def LQRController(vehicle, ref_path):
    x_e, y_e, theta_e, er, rdelta, ryaw, index = calc_preparation(vehicle, ref_path)
    x = np.matrix([[x_e],
                   [y_e],
                   [theta_e]])
    A, B = update_ABMatrix(vehicle, rdelta, ryaw)
    K = cal_lqr_k(A, B, Q, R, F)

    u = -K @ x
    delta_f = rdelta + u[1,0]
    return delta_f, index, er

kinematic_bicycle_model.py

import math
import numpy as np

class Vehicle:
    def __init__(self,
                 x=0.0,
                 y=0.0,
                 yaw=0.0,
                 v=0.0,
                 dt=0.1,
                 l=3.0):
        self.steer = 0
        self.x = x
        self.y = y
        self.yaw = yaw
        self.v = v
        self.dt = dt
        self.L = l  # 轴距
        self.x_front = x + l * math.cos(yaw)
        self.y_front = y + l * math.sin(yaw)

    def update(self, a, delta, max_steer=np.pi):
        delta = np.clip(delta, -max_steer, max_steer)
        self.steer = delta

        self.x = self.x + self.v * math.cos(self.yaw) * self.dt
        self.y = self.y + self.v * math.sin(self.yaw) * self.dt
        self.yaw = self.yaw + self.v / self.L * math.tan(delta) * self.dt

        self.v = self.v + a * self.dt
        self.x_front = self.x + self.L * math.cos(self.yaw)
        self.y_front = self.y + self.L * math.sin(self.yaw)


class VehicleInfo:
    # Vehicle parameter
    L = 2.0  # 轴距
    W = 2.0  # 宽度
    LF = 2.8  # 后轴中心到车头距离
    LB = 0.8  # 后轴中心到车尾距离
    MAX_STEER = 0.6  # 最大前轮转角
    TR = 0.5  # 轮子半径
    TW = 0.5  # 轮子宽度
    WD = W  # 轮距
    LENGTH = LB + LF  # 车辆长度

def draw_vehicle(x, y, yaw, steer, ax, vehicle_info=VehicleInfo, color='black'):
    vehicle_outline = np.array(
        [[-vehicle_info.LB, vehicle_info.LF, vehicle_info.LF, -vehicle_info.LB, -vehicle_info.LB],
         [vehicle_info.W / 2, vehicle_info.W / 2, -vehicle_info.W / 2, -vehicle_info.W / 2, vehicle_info.W / 2]])

    wheel = np.array([[-vehicle_info.TR, vehicle_info.TR, vehicle_info.TR, -vehicle_info.TR, -vehicle_info.TR],
                      [vehicle_info.TW / 2, vehicle_info.TW / 2, -vehicle_info.TW / 2, -vehicle_info.TW / 2,
                       vehicle_info.TW / 2]])

    rr_wheel = wheel.copy()  # 右后轮
    rl_wheel = wheel.copy()  # 左后轮
    fr_wheel = wheel.copy()  # 右前轮
    fl_wheel = wheel.copy()  # 左前轮
    rr_wheel[1, :] += vehicle_info.WD / 2
    rl_wheel[1, :] -= vehicle_info.WD / 2

    # 方向盘旋转
    rot1 = np.array([[np.cos(steer), -np.sin(steer)],
                     [np.sin(steer), np.cos(steer)]])
    # yaw旋转矩阵
    rot2 = np.array([[np.cos(yaw), -np.sin(yaw)],
                     [np.sin(yaw), np.cos(yaw)]])
    fr_wheel = np.dot(rot1, fr_wheel)
    fl_wheel = np.dot(rot1, fl_wheel)
    fr_wheel += np.array([[vehicle_info.L], [-vehicle_info.WD / 2]])
    fl_wheel += np.array([[vehicle_info.L], [vehicle_info.WD / 2]])

    fr_wheel = np.dot(rot2, fr_wheel)
    fr_wheel[0, :] += x
    fr_wheel[1, :] += y
    fl_wheel = np.dot(rot2, fl_wheel)
    fl_wheel[0, :] += x
    fl_wheel[1, :] += y
    rr_wheel = np.dot(rot2, rr_wheel)
    rr_wheel[0, :] += x
    rr_wheel[1, :] += y
    rl_wheel = np.dot(rot2, rl_wheel)
    rl_wheel[0, :] += x
    rl_wheel[1, :] += y
    vehicle_outline = np.dot(rot2, vehicle_outline)
    vehicle_outline[0, :] += x
    vehicle_outline[1, :] += y

    ax.plot(fr_wheel[0, :], fr_wheel[1, :], color)
    ax.plot(rr_wheel[0, :], rr_wheel[1, :], color)
    ax.plot(fl_wheel[0, :], fl_wheel[1, :], color)
    ax.plot(rl_wheel[0, :], rl_wheel[1, :], color)

    ax.plot(vehicle_outline[0, :], vehicle_outline[1, :], color)
    ax.axis('equal')


def update_ABMatrix(vehicle, ref_delta, ref_yaw):
    """
    计算离散线性车辆运动学模型状态矩阵A和输入矩阵B
    return: A, b
    """
    A = np.matrix([
        [1.0, 0.0, -vehicle.v * vehicle.dt * math.sin(ref_yaw)],
        [0.0, 1.0, vehicle.v * vehicle.dt * math.cos(ref_yaw)],
        [0.0, 0.0, 1.0]])

    B = np.matrix([
        [vehicle.dt * math.cos(ref_yaw), 0],
        [vehicle.dt * math.sin(ref_yaw), 0],
        [vehicle.dt * math.tan(ref_delta) / vehicle.L,
         vehicle.v * vehicle.dt / (vehicle.L * math.cos(ref_delta) * math.cos(ref_delta))]])
    return A, B


def update_ABMatrix1(vehicle, ref_delta, ref_yaw):
    """将模型离散化后的状态空间表达

    Args:
        delta (_type_): 参考输入

    Returns:
        _type_: _description_
    """
    A = np.matrix([
        [1.0, 0.0, -vehicle.v * vehicle.dt * math.sin(ref_yaw)],
        [0.0, 1.0, vehicle.v * vehicle.dt * math.cos(ref_yaw)],
        [0.0, 0.0, 1.0]])

    B = np.matrix([
        [vehicle.dt * math.cos(ref_yaw), 0],
        [vehicle.dt * math.sin(ref_yaw), 0],
        [vehicle.dt * math.tan(ref_delta) / vehicle.L,
         vehicle.v * vehicle.dt / (vehicle.L * math.cos(ref_delta) * math.cos(ref_delta))]
    ])
    return A, B

path_generator.py

"""
路径轨迹生成器
"""

import math
import numpy as np

class Path:
    def __init__(self):
        self.ref_line = self.design_reference_line()
        self.ref_yaw = self.cal_yaw()
        self.ref_s = self.cal_accumulated_s()
        self.ref_kappa = self.cal_kappa()

    def design_reference_line(self):
        rx = np.linspace(0, 50, 1000) + 5 # x坐标
        ry = 20 * np.sin(rx / 20.0) + 60  # y坐标
        return np.column_stack((rx, ry))
    def cal_yaw(self):
        yaw = []
        for i in range(len(self.ref_line)):
            if i == 0:
                yaw.append(math.atan2(self.ref_line[i + 1, 1] - self.ref_line[i, 1],
                                 self.ref_line[i + 1, 0] - self.ref_line[i, 0]))
            elif i == len(self.ref_line) - 1:
                yaw.append(math.atan2(self.ref_line[i, 1] - self.ref_line[i - 1, 1],
                                 self.ref_line[i, 0] - self.ref_line[i - 1, 0]))
            else:
                yaw.append(math.atan2(self.ref_line[i + 1, 1] - self.ref_line[i -1, 1],
                                  self.ref_line[i + 1, 0] - self.ref_line[i - 1, 0]))
        return yaw

    def cal_accumulated_s(self):
        s = []
        for i in range(len(self.ref_line)):
            if i == 0:
                s.append(0.0)
            else:
                s.append(math.sqrt((self.ref_line[i, 0] - self.ref_line[i-1, 0]) ** 2
                                 + (self.ref_line[i, 1] - self.ref_line[i-1, 1]) ** 2))
        return s

    def cal_kappa(self):
        # 计算曲线各点的切向量
        dp = np.gradient(self.ref_line.T, axis=1)
        # 计算曲线各点的二阶导数
        d2p = np.gradient(dp, axis=1)
        # 计算曲率
        kappa = (d2p[0] * dp[1] - d2p[1] * dp[0]) / ((dp[0] ** 2 + dp[1] ** 2) ** (3 / 2))

        return kappa

    def get_ref_line_info(self):
        return self.ref_line[:, 0], self.ref_line[:, 1], self.ref_yaw, self.ref_s, self.ref_kappa

main.py

from kinematic_bicycle_model import Vehicle, VehicleInfo, draw_vehicle
from kinematicsLQR import LQRController
from path_generator import Path
import numpy as np
import matplotlib.pyplot as plt
import imageio.v2 as imageio

MAX_SIMULATION_TIME = 200.0  # 程序最大运行时间200*dt

def main():
    # 设置跟踪轨迹
    rx, ry, ref_yaw, ref_s, ref_kappa = Path().get_ref_line_info()
    ref_path = np.column_stack((rx, ry, ref_yaw, ref_s, ref_kappa))
    # 假设车辆初始位置为(5,60),航向角yaw=0.0,速度为2m/s,时间周期dt为0.1秒
    vehicle = Vehicle(x=5.0,
                      y=60.0,
                      yaw=0.0,
                      v=2.0,
                      dt=0.1,
                      l=VehicleInfo.L)

    time = 0.0  # 初始时间
    target_ind = 0
    # 记录车辆轨迹
    trajectory_x = []
    trajectory_y = []
    lat_err = []  # 记录横向误差

    i = 0
    image_list = []  # 存储图片
    plt.figure(1)

    last_idx = ref_path.shape[0] - 1  # 跟踪轨迹的最后一个点的索引
    while MAX_SIMULATION_TIME >= time and last_idx > target_ind:
        time += vehicle.dt  # 累加一次时间周期

        # rear_wheel_feedback
        delta_f, target_ind, e_y = LQRController(vehicle, ref_path)

        # 横向误差
        lat_err.append(e_y)

        # 更新车辆状态
        vehicle.update(0.0, delta_f, np.pi / 10)  # 由于假设纵向匀速运动,所以加速度a=0.0
        trajectory_x.append(vehicle.x)
        trajectory_y.append(vehicle.y)

        # 显示动图
        plt.cla()
        plt.plot(ref_path[:, 0], ref_path[:, 1], '-.b', linewidth=1.0)
        draw_vehicle(vehicle.x, vehicle.y, vehicle.yaw, vehicle.steer, plt)

        plt.plot(trajectory_x, trajectory_y, "-r", label="trajectory")
        plt.plot(ref_path[target_ind, 0], ref_path[target_ind, 1], "go", label="target")
        plt.axis("equal")
        plt.grid(True)
        plt.pause(0.001)
    #     plt.savefig("temp.png")
    #     i += 1
    #     if (i % 5) == 0:
    #         image_list.append(imageio.imread("temp.png"))
    #
    # imageio.mimsave("display.gif", image_list, duration=0.1)

    plt.figure(2)
    plt.subplot(2, 1, 1)
    plt.plot(ref_path[:, 0], ref_path[:, 1], '-.b', linewidth=1.0)
    plt.plot(trajectory_x, trajectory_y, 'r')
    plt.title("actual tracking effect")

    plt.subplot(2, 1, 2)
    plt.plot(lat_err)
    plt.title("lateral error")
    plt.show()


if __name__ == '__main__':
    main()

运行结果如下
在这里插入图片描述

在这里插入图片描述

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

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

相关文章

python练习五

1. 给定一个包含n1个整数的数组nums&#xff0c;其数字在1到n之间&#xff08;包含1和n&#xff09;&#xff0c;可知至少存在一个重复的整数&#xff0c;假设只有一个重复的整数&#xff0c;请找出这个重复的数 def find_difnumber(ls):for index in range(0, len(ls)):for n…

Linux应用实战之网络服务器(四)JavaScript介绍

0、前言 准备做一个Linux网络服务器应用实战&#xff0c;通过网页和运行在Linux下的服务器程序通信&#xff0c;这是第四篇&#xff0c;介绍一下JS&#xff0c;让HTML网页实现与服务器通信。 1、JS常用语法 JavaScript是一种脚本语言&#xff0c;主要用于前端开发&#xff0…

纯前端搭建ChatGpt应用(全部代码在这了)

话不多说直接放代码&#xff1a; &#xff08;需要下载并导入axios包&#xff0c;懒省事的人也可以直接使用uni.request等请求方法&#xff09; 目录 1、html代码&#xff1a; &#xff08;本例使用的uniapp编写&#xff09; 2、js代码&#xff1a;&#xff08;API-KEY需要…

基于ssm电子竞技管理平台的设计与实现论文

摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本电子竞技管理平台就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间内处理完毕庞大的数据信息…

尾盘拉升超8个点,速腾聚创交出来一份怎样的超预期答卷?

“如果说2024年是智驾加速渗透&#xff0c;L3级智能驾驶陆续落地的一年&#xff0c;那么激光雷达将是这股潮流中不可缺失的那一份。” 2024年开年&#xff0c;速腾聚创以相当“闪亮的姿态”成为“港股2024年首只IPO上市成功”的企业。 然而&#xff0c;其上市之后的市场表现却…

每日一练 两数相加问题(leetcode)

原题如下&#xff1a; 这道题目是一道链表题&#xff0c;我们对于这种链表类&#xff0c;很显然我们最后输出的是初始节点&#xff0c;所以我们要保留我们的初始头指针&#xff0c;那么我们的第一步一定是把头指针保留一份&#xff0c;然后再让头指针往后进行操作。那么我们进行…

EXCEL通过VBA字典快速分类求和

EXCEL通过VBA字典快速分类求和 汇总截图 Option ExplicitOption Explicit Sub answer3() Dim wb As Workbook Dim sht As Worksheet Set wb ThisWorkbook Set sht wb.Worksheets(2) Dim ss1 As Integer Dim ss2 As Integer Dim i As Integer Dim j As Integer j 1Dim aa()…

基于Arduino IDE 野火ESP8266模块 文件系统LittleFS 的开发

一、文件系统LittleFS的介绍 LittleFS是一个为微控制器设计的轻量级、可靠且高性能的文件系统。它专为嵌入式设备打造&#xff0c;拥有占用空间小、对硬件要求低的特点&#xff0c;同时保证在断电情况下数据的完整性和稳定性。 1.设计与特点 LittleFS的设计旨在提供嵌入式系统所…

AcWing刷题-空调

空调 差分&#xff1a; N int(input()) p list(map(int, input().split())) t list(map(int, input().split())) d,s[0]*100010,[0]*100010 for i in range(N):d[i] p[i]-t[i]for i in range(N):s[i] d[i]s[i1] - d[i] ans 0 for i in range(N1):if s[i]>0:ans s[i]…

开源,微信小程序-超级计算器T3000 简介

笔者于四年前自学微信小程序开发&#xff0c;这个超级计算器T3000就是当时的练习作品。超级计算器T3000的功能有很多&#xff0c;其中的核心技术是矩阵计算&#xff0c;使用的工具库是math.js&#xff0c;其次是复杂运算和分式运算。关于math.js的使用&#xff0c;可以参考另一…

【SpringBoot】【经典面试题】每天10个Java面试题-面试大厂起飞系列-day02

嗨&#xff0c;各位小伙伴&#xff01; &#x1f431;‍&#x1f4bb; 我是【行走的程序喵】&#xff01;一个兼具Web前端和Java后端技能的技术宅&#xff01; &#x1f31f; 我的博客上分享最新的Web前端和Java后端技术文章&#xff0c;从基础入门到进阶应用&#xff0c;应有…

基于Axios封装请求---防止接口重复请求解决方案

一、引言 前端接口防止重复请求的实现方案主要基于以下几个原因&#xff1a; 用户体验&#xff1a;重复发送请求可能导致页面长时间无响应或加载缓慢&#xff0c;从而影响用户的体验。特别是在网络不稳定或请求处理时间较长的情况下&#xff0c;这个问题尤为突出。 服务器压力…

memcached缓存数据库简介

memcached是一套分布式的高速缓存系统&#xff0c;由LiveJournal的Brad Fitzpatrick开发&#xff0c;但被许多网站使用。这是一套开放源代码软件&#xff0c;以BSD license授权发布。 memcached缺乏认证以及安全管制&#xff0c;这代表应该将memcached服务器放置在防火墙后。 …

nginx详解(持续更新)

nginx定义 nginx安装 nginx目录 程序相关命令 服务相关命令 虚拟主机&#xff08;server&#xff09; 路由匹配&#xff08;location&#xff09; 代理&#xff08;proxy_pass&#xff09; 正向代理 反向代理 负载均衡&#xff08;upstream&#xff09; 负载均衡策略 动静分…

电动汽车充放电V2G模型(Matlab代码)

目录 1 主要内容 1.1 模型背景 1.2 目标函数 1.3 约束条件 2 部分代码 3 效果图 4 下载链接 1 主要内容 本程序主要建立电动汽车充放电V2G模型&#xff0c;采用粒子群算法&#xff0c;在保证电动汽车用户出行需求的前提下&#xff0c;为了使工作区域电动汽车尽可能多的…

<QT基础(3)>QLineEdit使用笔记

LineEdit 这次要用的是两个功能&#xff1a;初始化展示参数值&#xff0c;修改参数值。 初始化 将l_num的默认值显示 ui.lineEdit->setText(QString::number(l_num));信号 textChanged() 文本发生改变textEdited() 文本编辑信号cursorPositionChanged(&#xff09;光标发…

java子集(力扣Leetcode78)

子集 力扣原题链接 问题描述 给定一个整数数组 nums&#xff0c;数组中的元素互不相同。返回该数组所有可能的子集&#xff08;幂集&#xff09;。解集不能包含重复的子集。可以按任意顺序返回解集。 示例 示例 1&#xff1a; 输入&#xff1a;nums [1,2,3] 输出&#x…

C++11入门手册第一节,学完直接上手Qt(共两节)

入门 hello.cpp #include <iostream>int main() { std::cout << "Hello Quick Reference\n"<<endl; return 0;} 编译运行 $ g hello.cpp -o hello$ ./hello​Hello Quick Reference 变量 int number 5; // 整数float f 0.95; //…

32-1 命令执行漏洞 - RCE挖掘与防范

一、漏洞绕过 1、编码绕过 利用base64编码绕过:Base64 在线编码解码 | Base64 加密解密 - Base64.us 如将 whoami 命令进行编码 利用hex编码(十六进制)绕过:Hex编码/Hex解码 - 站长工具 (chinaz.com) 利用oct编码(八进制)绕过: 这个我没找到编码工具 利用16进制编码…

数据结构——lesson11排序之快速排序

&#x1f49e;&#x1f49e; 前言 hello hello~ &#xff0c;这里是大耳朵土土垚~&#x1f496;&#x1f496; &#xff0c;欢迎大家点赞&#x1f973;&#x1f973;关注&#x1f4a5;&#x1f4a5;收藏&#x1f339;&#x1f339;&#x1f339; &#x1f4a5;个人主页&#x…