【局部路径规划算法】—— DWA动态窗口法(c++实现))

参考资料:
(1)机器人局部避障的动态窗口法(dynamic window approach)
(2)机器人局部避障的动态窗口法
(3)局部规划算法:DWA算法原理
(4)SLAM学习:DWA算法原理和编程实现(PYTHON)
(5)【路径规划】局部路径规划算法——DWA算法(动态窗口法)|(含python实现 | c++实现)

1 DWA动态窗口法

动态窗口法(Dynamic Window Approach):常用的局部避障规划方法
在这里插入图片描述
(1) 轨迹预测:建立智能汽车关于速度和角速度的运动学模型
x = x + v Δ t cos ⁡ ( θ t ) y = y + v Δ t sin ⁡ ( θ t ) θ t = θ t + w Δ t \begin{array}{l} x=x+v \Delta t \cos \left(\theta_{t}\right) \\ y=y+v \Delta t \sin \left(\theta_{t}\right) \\ \theta_{t}=\theta_{t}+w \Delta t \end{array} x=x+vΔtcos(θt)y=y+vΔtsin(θt)θt=θt+wΔt

  • 上式表明在一定时间窗口内,车辆的位置和航向角可由当前车辆速度和当前角速度决定,那么不同的速度和角速度组合将产生不同的车辆位置和航向角,也就产生不同的车辆运动轨迹。
  • 在速度和加速度所构成的二维空间,由于不受任何约束,存在着无穷多种组合,速度和加速度采样的目的就是将采样区域缩小在一定范围,并适当设置速度分辨率,以生成若干组数量有限的速度和加速度组合。缩小采样区域通过设置各类约束条件实现。

(2) 速度采样:充分考虑智能汽车的速度、加速度等物理限制约束条件,在速度和角速度空间内采样获取一对速度指令,通过设定一个时间区间获得一簇轨迹曲线
在这里插入图片描述

(3) 轨迹评价:构造一种轨迹性能评价指标选取最优轨迹

  • 在每一个蓝色虚线框内,车辆都会根据当前的速度组合生成若干条备选运动轨迹,这些轨迹构成的轨迹曲线簇就称为一个时间窗
  • 车辆在这个窗口内按照特定规则选择一条最优轨迹运动。当运动到1号窗口轨迹的末端后又重新生成一个新的轨迹曲线簇(即2号窗口),如此反复循环动态执行,故命名为动态窗口法
  1. 航向角评价函数。我们设在当前采样速度组合下的时间窗口轨迹末端的航向角为heading,该朝向与目标点的角度差值越小,则方位角评价函数值越高,表明此速度组合对应的运动轨迹越好。
  2. 障碍物距离评价函数。设dist为速度组合(v,w)对应的轨迹曲线与障碍车的最小距离, 数值越大,则障碍物距离评价函数值越高,表明此速度组合对应的运动轨迹越好。
  3. 速度评价函数。我们希望车辆在正常行驶过程中与目标速度越接近越好,故速度越高,可以认为评价函数值越高。

在这里插入图片描述

最后,利用归一化思想对上述三种轨迹评价函数进行相加构成综合评价函数指标,以此作为标准筛选时间窗内的最优轨迹

在这里插入图片描述DWA算法demo

BEGIN DWA(robotPose,robotGoal,robotModel)  
   laserscan = readScanner()  
   allowable_v = generateWindow(robotV, robotModel)  
   allowable_w  = generateWindow(robotW, robotModel)  
   // 根据能否及时刹车剔除不安全的速度
   for each v in allowable_v  
      for each w in allowable_w  
      dist = find_dist(v,w,laserscan,robotModel)  
      breakDist = calculateBreakingDistance(v)//刹车距离  
      if (dist > breakDist)  //如果能够及时刹车,该对速度可接收
         heading = hDiff(robotPose,goalPose, v,w)   
          //clearance与原论文稍不一样  
         clearance = (dist-breakDist)/(dmax - breakDist)   
         cost = costFunction(heading,clearance, abs(desired_v - v))  
         if (cost > optimal)  
            best_v = v  
            best_w = w  
            optimal = cost  
    set robot trajectory to best_v, best_w  
END  

2 DWA算法流程

在这里插入图片描述

3 应用场景

应用模型: 适用于两轮差分和全向移动模型、不能用在阿克曼模型。
优点
(1)计算复杂度低:考虑到速度和加速度的限制,只有安全的轨迹会被考虑,且每次采样的时间较短,因此轨迹空间较小
(2)可以实现避障:可以实时避障,但是避障效果一般
(3)适用于两轮差分和全向移动模型
缺点
(1)前瞻性不足: 只模拟并评价了下一步,如在机器人前段遇见“C”字形障碍时,不能很好的避障
(2)非全局最优路径: 每次都选择下一步的最佳路径,而非全局最优路径
(3)动态避障效果差
(4)不能用在阿克曼模型

4 DWA可视化

参考b站Ally大佬的代码
dwa.h

#include <stdio.h>
#include <eigen3/Eigen/Dense>
#include <iostream>
#include <memory>
#include <vector>
#include <unordered_map>
#include "matplotlibcpp.h"
#include <stdlib.h>
#include <algorithm>

#define PI 3.14159
class DWA {
private:
    // 位姿
    typedef struct
    {
        double x = 0;
        double y = 0;
    } Pos;
    // 权重
    struct Weight
    {
        double heading = 1;
        double dist = 3;
        double speed = 3;
    } weight_;
    // 速度采样
    typedef struct
    {
        double linear_vel_min = 0;
        double linear_vel_max = 0;
        double angular_vel_min = 0;
        double angular_vel_max = 0;

    } SpeedRange;
    // 车辆状态
    typedef struct
    {
        double pos_x = 0;
        double pos_y = -1.75;
        double heading = 0;
        double linear_vel = 2;
        double angular_vel = 0;
    } VehicleState;
    // 窗口信息
    typedef struct
    {
        double linear_vel = 0;
        double angular_vel = 0;
        std::vector<VehicleState> trajectory;
        double heading_value;
        double dist_value;
        double vel_value;
        double value = 0;
    } WindowInfo;
    // 障碍物
    typedef struct
    {
        double center_x = 0;
        double center_y = 0;
        double radius = 0;
    } Obstacle;

    // 场景基本参数
    double road_width_ = 3.5; // 道路标准宽度
    double road_len_ = 60;    // 道路长度
    double veh_width_ = 1.6;  // 汽车宽度
    double veh_len_ = 4.5;    // 车长
    Pos goal_pos_;            // 目标点位置

    // 时间参数
    double dt_ = 0.1;        // 车辆单步运动时间
    double window_time_ = 3; // 窗口时间

    // 自车运动学模型参数
    double v_max_ = 15;                 // 最高速度
    double omega_max_ = 200 * PI / 180; // 最高角速度
    double acc_max_ = 3;                // 最高加速度
    double alpha_max_ = 50 * PI / 180;  // 最高角加速度
    double v_res_ = 0.1;                // 速度分辨率
    double omega_res_ = 2 * PI / 180;   // 角速度分辨率

    VehicleState vehicle_state_;
    std::vector<WindowInfo> window_info_;
    std::vector<Obstacle> obstacles_;
    std::vector<double> path_x;
    std::vector<double> path_y;
public:
    DWA() {}
    ~DWA() {}

    bool run();

    // 设置障碍物环境
    void setObstacles();

    // 根据当前状态和约束计算当前的速度参数允许范围
    SpeedRange GetSpeedRange();

    // 获取窗口信息
    void GetWindowInfo(DWA::SpeedRange speed_range);
    
    // 更新自车状态
    void UpdateState(int max_value_idx);

    // 找到最大评价函数对应的索引
    int FindMaxValue();

    // 获取本时间窗内的轨迹
    void GetTrajectory(std::vector<VehicleState> *trajectory, double linear_vel, double angular_vel);

    // 可视化
    void Plot(bool to_goal_dist_flag, int max_value_idx);

    // 获取自车几个点位
    void GetEgoPoint(std::vector<double> *x_list, std::vector<double> *y_list);
};

dwa.cpp

#include "../include/dwa.h"

bool DWA::run() {
    goal_pos_.x = 57;
    goal_pos_.y = 2.5;

    // 设置障碍物环境
    DWA::setObstacles();
    bool to_goal_dist_flag = false;
    for (size_t i = 0; i < 1000; i++)
    {
        // 根据当前状态和约束计算当前的速度参数允许范围
        DWA::SpeedRange speed_range = GetSpeedRange();

        // 根据速度范围和分辨率,生成若干条运动轨迹
        DWA::GetWindowInfo(speed_range);

        // 找到最大评价函数对应的索引
        int max_value_idx = DWA::FindMaxValue();

        // 更新自车状态
        DWA::UpdateState(max_value_idx);

        // 判断是否到达终点,并画图
        std::cout << "iter: " << i << "; pos_x: " << vehicle_state_.pos_x << "; pos_y: " << vehicle_state_.pos_y
                  << "; heading: " << vehicle_state_.heading << "; linear_vel: " << vehicle_state_.linear_vel
                  << "; angular_vel: " << vehicle_state_.angular_vel << std::endl;
        double to_goal_dist = std::sqrt(std::pow(vehicle_state_.pos_x - goal_pos_.x, 2) +
                                        std::pow(vehicle_state_.pos_y - goal_pos_.y, 2));
        if (to_goal_dist < 1)
        {
            std::cout << "finish !" << std::endl;
            to_goal_dist_flag = true;
            DWA::Plot(to_goal_dist_flag, max_value_idx);
            break;
        }
        DWA::Plot(to_goal_dist_flag, max_value_idx);
    }
    return true;
}

void DWA::setObstacles()
{
    DWA::Obstacle obstacle_tmp;
    // 1
    obstacle_tmp.center_x = 13.0;
    obstacle_tmp.center_y = -1.75;
    obstacle_tmp.radius = 2.0;
    obstacles_.push_back(obstacle_tmp);

    // 2
    obstacle_tmp.center_x = 27.0;
    obstacle_tmp.center_y = -1.75;
    obstacle_tmp.radius = 2.0;
    obstacles_.push_back(obstacle_tmp);

    // 3
    obstacle_tmp.center_x = 40.0;
    obstacle_tmp.center_y = 1.75;
    obstacle_tmp.radius = 2.0;
    obstacles_.push_back(obstacle_tmp);

    // 4
    obstacle_tmp.center_x = 50.0;
    obstacle_tmp.center_y = -1.75;
    obstacle_tmp.radius = 2.0;
    obstacles_.push_back(obstacle_tmp);

    // 将道路便捷模拟为若干个小的障碍物,下边界
    for (size_t i = 0; i < 120; i++)
    {
        obstacle_tmp.center_x = i * 0.5;
        obstacle_tmp.center_y = 3.5;
        obstacle_tmp.radius = 0.5;
        obstacles_.push_back(obstacle_tmp);
    }

    // 将道路便捷模拟为若干个小的障碍物,上边界
    for (size_t i = 0; i < 120; i++)
    {
        obstacle_tmp.center_x = i * 0.5;
        obstacle_tmp.center_y = -3.5;
        obstacle_tmp.radius = 0.5;
        obstacles_.push_back(obstacle_tmp);
    }
}

DWA::SpeedRange DWA::GetSpeedRange()
{
    DWA::SpeedRange speed_range;
    speed_range.linear_vel_min = std::max(vehicle_state_.linear_vel - acc_max_ * dt_, 0.0);
    speed_range.linear_vel_max = std::min(vehicle_state_.linear_vel + acc_max_ * dt_, v_max_);
    speed_range.angular_vel_min = std::max(vehicle_state_.angular_vel - alpha_max_ * dt_, -omega_max_);
    speed_range.angular_vel_max = std::min(vehicle_state_.angular_vel + alpha_max_ * dt_, omega_max_);
    return speed_range;
}

void DWA::GetWindowInfo(DWA::SpeedRange speed_range)
{
    window_info_.clear(); //清空
    DWA::WindowInfo window_info_tmp;
    std::vector<VehicleState> trajectory;

    double linear_vel = speed_range.linear_vel_min;
    while (true)
    {
        double angular_vel = speed_range.angular_vel_min;
        while (true)
        {
            // 初始化轨迹
            trajectory.clear();
            GetTrajectory(&trajectory, linear_vel, angular_vel);

            // 赋值
            window_info_tmp.linear_vel = linear_vel;
            window_info_tmp.angular_vel = angular_vel;
            window_info_tmp.trajectory = trajectory;
            window_info_.push_back(window_info_tmp);

            // 判断是否退出循环
            angular_vel = angular_vel + omega_res_;
            if (angular_vel >= speed_range.angular_vel_max)
            {
                break;
            }
        }
        // 判断是否退出循环
        linear_vel = linear_vel + v_res_;
        if (linear_vel >= speed_range.linear_vel_max)
        {
            break;
        }
    }
}

void DWA::GetTrajectory(std::vector<DWA::VehicleState> *trajectory, double linear_vel, double angular_vel)
{
    DWA::VehicleState vehicle_state = vehicle_state_;
    trajectory->push_back(vehicle_state);

    // 循环获得窗口时间内的轨迹
    double time = 0;
    while (time <= window_time_)
    {
        time = time + dt_; // 时间更新

        Eigen::Matrix<double, 5, 5> A;
        A << 1, 0, 0, 0, 0,
             0, 1, 0, 0, 0,
             0, 0, 1, 0, 0,
             0, 0, 0, 0, 0,
             0, 0, 0, 0, 0;

        Eigen::Matrix<double, 5, 2> B;
        B << dt_ * std::cos(vehicle_state.heading), 0,
             dt_ * std::sin(vehicle_state.heading), 0,
             0, dt_,
             1, 0,
             0, 1;

        Eigen::Matrix<double, 5, 1> x;
        x << vehicle_state.pos_x,
             vehicle_state.pos_y,
             vehicle_state.heading,
             vehicle_state.linear_vel,
             vehicle_state.angular_vel;

        Eigen::Matrix<double, 2, 1> u;
        u << linear_vel,
             angular_vel;

        // 状态更新
        Eigen::Matrix<double, 5, 1> state_new;
        state_new = A * x + B * u;

        // 更新state指针
        vehicle_state.pos_x = state_new(0);
        vehicle_state.pos_y = state_new(1);
        vehicle_state.heading = state_new(2);
        vehicle_state.linear_vel = state_new(3);
        vehicle_state.angular_vel = state_new(4);

        trajectory->push_back(vehicle_state);
    }
}

int DWA::FindMaxValue()
{
    double heading_value_sum = 0;
    double dist_value_sum = 0;
    double vel_value_sum = 0;
    for (std::vector<DWA::WindowInfo>::iterator iter = window_info_.begin(); iter != window_info_.end();)
    {
        DWA::VehicleState end_state = iter->trajectory[iter->trajectory.size() - 1];

        // 计算航向角评价函数
        double theta = end_state.heading * 180 / PI;
        double goal_theta = std::atan2(goal_pos_.y - end_state.pos_y, goal_pos_.x - end_state.pos_x) * 180 / PI;
        double target_theta = std::abs(goal_theta - theta);
        double heading_value = 180 - target_theta;

        // 计算轨迹终点距离最近障碍物距离的评价函数
        double dist_value = 1e5;
        for (size_t i = 0; i < obstacles_.size(); i++)
        {
            double dist = std::sqrt(std::pow(end_state.pos_x - obstacles_[i].center_x, 2) +
                                    std::pow(end_state.pos_y - obstacles_[i].center_y, 2)) -
                          obstacles_[i].radius;
            dist_value = std::min(dist_value, dist);
        }
        if (dist_value < 0)
        {
            iter = window_info_.erase(iter);
            continue;
        }
        iter->dist_value = dist_value;

        // 计算速度的评价函数
        double vel_value = end_state.linear_vel;
        double stop_dist = std::pow(end_state.linear_vel, 2) / (2 * acc_max_);
        if (dist_value < stop_dist)
        {
            iter = window_info_.erase(iter);
            continue;
        }
        iter->vel_value = vel_value;

        // 计算累计值,用于归一化处理
        heading_value_sum = heading_value_sum + heading_value;
        dist_value_sum = dist_value_sum + dist_value;
        vel_value_sum = vel_value_sum + vel_value;

        iter++;
    }

    // 归一化处理
    int idx = 0;
    double max_value = 0;
    for (size_t i = 0; i < window_info_.size(); i++)
    {
        double heading_value_tmp = window_info_[i].heading_value / std::max(heading_value_sum, 0.01);
        double dist_value_tmp = window_info_[i].dist_value / std::max(dist_value_sum, 0.01);
        double vel_value_tmp = window_info_[i].vel_value / std::max(vel_value_sum, 0.01);
        window_info_[i].value = heading_value_tmp * weight_.heading +
                                dist_value_tmp * weight_.dist + vel_value_tmp * weight_.speed;
        window_info_[i].value > max_value ? idx = i : idx = idx;
    }
    return idx;
}

void DWA::UpdateState(int max_value_idx)
{
    std::vector<DWA::WindowInfo>::iterator iter = window_info_.begin() + max_value_idx;
    vehicle_state_ = *(iter->trajectory.begin() + 1);
    path_x.push_back(vehicle_state_.pos_x);
    path_y.push_back(vehicle_state_.pos_y);
}

void DWA::Plot(bool to_goal_dist_flag, int max_value_idx)
{
    matplotlibcpp::clf();
    matplotlibcpp::title("DWA");
    matplotlibcpp::xlabel("X-axis");
    matplotlibcpp::ylabel("Y-axis");

    // 画灰色路面
    std::vector<double> x_list = {-5, -5, road_len_, road_len_};
    std::vector<double> y_list = {-road_width_ - 0.5, road_width_ + 0.5,
                                  road_width_ + 0.5, -road_width_ - 0.5};
    std::map<std::string, std::string> keywords = {{"color", "0.55"}};
    matplotlibcpp::fill(x_list, y_list, keywords);

    // 画车道线
    x_list = {-5, road_len_};
    y_list = {0, 0};
    keywords = {{"linestyle", "dashed"}, {"color", "w"}};
    matplotlibcpp::plot(x_list, y_list, keywords);

    x_list = {-5, road_len_};
    y_list = {road_width_, road_width_};
    matplotlibcpp::plot(x_list, y_list, "w");

    x_list = {-5, road_len_};
    y_list = {-road_width_, -road_width_};
    matplotlibcpp::plot(x_list, y_list, "w");

    // 画交通车辆
    for (size_t i = 0; i < 4; i++)
    {
        x_list = {obstacles_[i].center_x, obstacles_[i].center_x,
                  obstacles_[i].center_x - veh_len_, obstacles_[i].center_x - veh_len_};
        y_list = {obstacles_[i].center_y - veh_width_ / 2, obstacles_[i].center_y + veh_width_ / 2,
                  obstacles_[i].center_y + veh_width_ / 2, obstacles_[i].center_y - veh_width_ / 2};
        keywords = {{"color", "b"}};
        matplotlibcpp::fill(x_list, y_list, keywords);
    }

    // 画自车
    GetEgoPoint(&x_list, &y_list);
    keywords = {{"color", "r"}};
    matplotlibcpp::fill(x_list, y_list, keywords);

    // 画窗口轨迹簇
    for (size_t i = 0; i < window_info_.size(); i++)
    {
        x_list.clear();
        y_list.clear();
        for (size_t j = 0; j < window_info_[i].trajectory.size(); j++)
        {
            x_list.push_back(window_info_[i].trajectory[j].pos_x);
            y_list.push_back(window_info_[i].trajectory[j].pos_y);
        }
        matplotlibcpp::plot(x_list, y_list, "g");
    }

    // 画本窗口内的最优轨迹
    x_list.clear();
    y_list.clear();
    for (size_t i = 0; i < window_info_[max_value_idx].trajectory.size(); i++)
    {
        x_list.push_back(window_info_[max_value_idx].trajectory[i].pos_x);
        y_list.push_back(window_info_[max_value_idx].trajectory[i].pos_y);
    }
    matplotlibcpp::plot(x_list, y_list, "r");

    // 画历史轨迹
    matplotlibcpp::plot(path_x, path_y, "y");

    // 限制横纵范围
    matplotlibcpp::xlim(-5.0, road_len_);
    matplotlibcpp::ylim(-4.0, 4.0);

    // 设置横纵比例
    matplotlibcpp::set_aspect(1);

    // 若还未到终点,则每一次执行结束后停顿0.1s
    if (to_goal_dist_flag == false)
    {
        matplotlibcpp::show(false); // 阻塞标志位置为false
        matplotlibcpp::pause(0.01);
    }
    else
    {
        matplotlibcpp::show(true);
    }

// 保存图片
matplotlibcpp::save("./dwa.png");

}

void DWA::GetEgoPoint(std::vector<double> *x_list, std::vector<double> *y_list)
{
    x_list->clear();
    y_list->clear();

    // 车头中心点
    double front_posx = vehicle_state_.pos_x;
    double front_posy = vehicle_state_.pos_y;
    double heading = vehicle_state_.heading;

    // 根据车头中心点位置和航向角计算车尾中心点位置
    double rear_posx = front_posx - veh_len_ * std::cos(heading);
    double rear_posy = front_posy - veh_len_ * std::sin(heading);

    // 根据前后中心点、航向角计算目障碍车四个轮廓点位置(顺时针编号)
    x_list->push_back(rear_posx - veh_width_ / 2 * std::sin(heading));
    y_list->push_back(rear_posy + veh_width_ / 2 * std::cos(heading));
    x_list->push_back(front_posx - veh_width_ / 2 * std::sin(heading));
    y_list->push_back(front_posy + veh_width_ / 2 * std::cos(heading));
    x_list->push_back(front_posx + veh_width_ / 2 * std::sin(heading));
    y_list->push_back(front_posy - veh_width_ / 2 * std::cos(heading));
    x_list->push_back(rear_posx + veh_width_ / 2 * std::sin(heading));
    y_list->push_back(rear_posy - veh_width_ / 2 * std::cos(heading));
}

main.cpp

#include <iostream>
#include <fstream>
#include <string>
#include "../include/dwa.h"

int main()
{
    std::shared_ptr<DWA> dwa = std::make_shared<DWA>();
    dwa->run();
    return 0;
}

CmakeList.txt

cmake_minimum_required(VERSION 3.0.2)
project(DWA)

set(CMAKE_CXX_STANDARD 11)

file(GLOB_RECURSE PYTHON2.7_LIB "/usr/lib/python2.7/config-x86_64-linux-gnu/*.so")
set(PYTHON2.7_INLCUDE_DIRS "/usr/include/python2.7")

find_package(catkin REQUIRED COMPONENTS
  roscpp
  std_msgs
)

catkin_package(
#  INCLUDE_DIRS include
#  LIBRARIES DWA
#  CATKIN_DEPENDS roscpp std_msgs
#  DEPENDS system_lib
)
# 找python包
find_package(Python3 COMPONENTS Development NumPy)

include_directories(include
        ${PYTHON2.7_INLCUDE_DIRS}
)

add_executable(dwa src/dwa.cpp
                   src/main.cpp)

target_link_libraries(dwa
  ${catkin_LIBRARIES}
  ${PYTHON2.7_LIB}
)

可视化结果:
在这里插入图片描述


DWA算法不正之处望指教

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

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

相关文章

Android Monkey自动化测试

monkey一般用于压力测试&#xff0c;用户模拟用户事件 monkey 基本用法 adb shell monkey [参数] [随机事件数]monkey常用命令 -v&#xff1a;用于指定反馈信息级别&#xff0c;总共分三个等级-v -v -vadb shell mokey -v -v -v 100-s&#xff1a;用于指定伪随机数生成器的种…

安卓MT管理器v2.15.1

软件介绍 MT管理器是一款强大的文件管理工具和APK逆向修改神器。如果你喜欢它的双窗口操作风格&#xff0c;可以单纯地把它当成文件管理器使用。如果你对修改APK有深厚的兴趣&#xff0c;那么你可以用它做许许多多的事&#xff0c;例如汉化应用、替换资源、修改布局、修改逻辑…

相交链表 - LeetCode 热题 22

大家好&#xff01;我是曾续缘&#x1f4a4; 今天是《LeetCode 热题 100》系列 发车第 22 天 链表第 1 题 ❤️点赞 &#x1f44d; 收藏 ⭐再看&#xff0c;养成习惯 相交链表 给你两个单链表的头节点 headA 和 headB &#xff0c;请你找出并返回两个单链表相交的起始节点。如果…

CVE-2021-30517:Type confusion bug in LoadSuperIC

前言 这个漏洞是一个比较老的洞&#xff0c;之所以分析这个漏洞&#xff0c;只要是想再学习一下 ICs 相关的知识。并该漏洞的利用是利用与 String/Function 之间的混淆&#xff0c;比较有意思。 环境搭建 sudo apt install python git checkout 7d5e5f6c62c3f38acee12dc4114…

【蓝桥杯第十四届省赛B】(部分详解)

【01串的熵】 https://www.lanqiao.cn/problems/3498/learning/?subject_code1&group_code4&match_num14&match_flow1&origincup #include <iostream> #include<cmath> using namespace std; int main() {double n23333333;double sum0;for(int…

代码学习记录35

随想录日记part35 t i m e &#xff1a; time&#xff1a; time&#xff1a; 2024.04.03 主要内容&#xff1a;今天开始要学习动态规划的相关知识了&#xff0c;今天的内容主要涉及三个方面&#xff1a; 最后一块石头的重量 II &#xff1b;目标和 &#xff1b;一和零 。 1049…

Linux基础篇:文件系统介绍——根目录下文件夹含义与作用介绍

Linux文件系统介绍——文件夹含义与作用 Linux文件系统是一个组织和管理文件的层次结构。它包括了目录、子目录和文件&#xff0c;这些都是按照一定的规则和标准进行组织的。以下是Linux文件系统的一些关键组成部分&#xff1a; 1./bin&#xff1a; 该目录包含了系统启动和运…

抽象类与接口(3)(接口部分)

❤️❤️前言~&#x1f973;&#x1f389;&#x1f389;&#x1f389; hellohello~&#xff0c;大家好&#x1f495;&#x1f495;&#xff0c;这里是E绵绵呀✋✋ &#xff0c;如果觉得这篇文章还不错的话还请点赞❤️❤️收藏&#x1f49e; &#x1f49e; 关注&#x1f4a5;&…

TiDB单机版安装和连接访问

TiDB单机版安装和连接访问 1、下载 $wget http://download.pingcap.org/tidb-latest-linux-amd64.tar.gz 2、解压缩 $tar -zxvf tidb-latest-linux-amd64.tar.gz 3、启动TiDB 启动PD $./bin/pd-server --data-dirpd --log-filepd.log 启动tikv $./bin/tikv-server --pd…

基于深度学习的扑克牌识别软件(网页版+YOLOv8_v7_v6_v5代码+训练数据集)

摘要&#xff1a;本文深入研究了基于YOLOv8/v7/v6/v5的扑克牌识别软件&#xff0c;核心采用YOLOv8并整合了YOLOv7、YOLOv6、YOLOv5算法&#xff0c;进行性能指标对比&#xff1b;详述了国内外研究现状、数据集处理、算法原理、模型构建与训练代码&#xff0c;及基于Streamlit的…

NASA数据集——1983 ——2016 年期间北美森林地点的野外地块特征数据、衍生的地上和地下燃烧碳以及获取的火灾气象指数(FWI)

文件修订日期&#xff1a;2022-05-04 数据集版本: 1 简介 该数据集综合了 1983 年至 2016 年期间美国阿拉斯加、西北地区和加拿大萨斯喀彻温省被烧毁的北方森林地点的野外地块特征数据、衍生的地上和地下燃烧碳以及获取的火灾气象指数&#xff08;FWI&#xff09;系统组件。…

基于 Quartz.NET 可视化任务调度平台 QuartzUI

一、简介 QuartzUI 是基于 Quartz.NET3.0 的定时任务 Web 可视化管理&#xff0c;Docker 打包开箱即用、内置 SQLite 持久化、语言无关、业务代码零污染、支持 RESTful 风格接口、傻瓜式配置、异常请求邮件通知等。 二、部署 QuartzUI 从 2022 年到现在没有提交记录&#xf…

计算机网络:局域网的数据链路层

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢&#xff0c;在这里我会分享我的知识和经验。&am…

SQLyog连接数据库8.0版本解析错误问题解决方案

问题描述&#xff1a; 解决方案&#xff1a; alter userrootlocalhostidentified with mysql_native_password by 密码; 再次连接就可以了。

Autodesk AutoCAD 2025 (macOS, Windows) - 自动计算机辅助设计软件

Autodesk AutoCAD 2025 (macOS, Windows) - 自动计算机辅助设计软件 AutoCAD 2024 开始原生支持 Apple Silicon&#xff0c;性能提升至 2 倍 请访问原文链接&#xff1a;https://sysin.org/blog/autodesk-autocad/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处…

Express框架搭建项目 node.js

文章目录 引言Express框架介绍express安装环境准备写一个简单的项目展示 文章总结 引言 Express是一个基于Node.js平台的轻量级Web应用框架&#xff0c;它提供了简洁的API和丰富的功能&#xff0c;使得开发者能够快速地构建Web服务器和API。本文将带领大家从零开始&#xff0c…

【初阶数据结构】——leetcode:160. 相交链表

文章目录 1. 题目介绍2. 思路1&#xff1a;暴力求解算法思想代码实现 3. 思路2&#xff1a;快慢指针算法思想代码实现 1. 题目介绍 链接: link 给你两个单链表的头节点 headA 和 headB &#xff0c;请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点&…

文件批量重命名管理,一键将图片的名称进行统一重命名,高效管理文件

在数字时代&#xff0c;我们的生活中充满了各种文件&#xff0c;特别是图片文件。随着时间的推移&#xff0c;我们可能会遇到这样的问题&#xff1a;文件命名不规范&#xff0c;难以快速找到需要的图片。这时&#xff0c;一款强大的文件批量重命名管理工具就显得尤为重要。 首…

简约好用的TCPUDP小工具

csdn下载地址&#xff1a; https://download.csdn.net/download/a876106354/89077745

RUST语言流控制语句使用示例

1.判断语句 单条件判断: let mut x128;//声明一个32位整数x512;//修改变量原来的值为新值//如果 ... 否则//判断变量x是否大于256if x>256 {println!("x>256,x{}",x);}else {println!("x<256,x{}",x);}let is_ok:bool true;//rust中不用()if i…