【Chrono Engine学习总结】4-vehicle-4.2-车辆轨迹跟踪

news2025/1/19 3:39:43

由于Chrono的官方教程在一些细节方面解释的并不清楚,自己做了一些尝试,做学习总结。

0、Vehicle的driver

driver在上一篇总结中有过介绍,【Chrono Engine学习总结】4-vehicle-4.1-vehicle的基本概念,这里进一步介绍。

对于一个具体的driver系统,控制的状态量即:油门、刹车、转向。这里重点介绍轨迹跟踪用到的driver:ChPathFollowerDriver

driver本质上就是驾驶这个车的东西,本文中的驾驶员、控制器等都可以是指这个driver。当然控制器严格来讲应该是controller。个人认为,上层一些的东西,就叫这个driver,包括转向、速度等多方面的handle,而具体到某个变量例如速度,就叫做controller。

1、闭环驾驶控制器 ChClosedLoopDriver

https://api.projectchrono.org/classchrono_1_1vehicle_1_1_ch_closed_loop_driver.html

顾名思义,这是“闭环”驾驶系统,因此肯定包括控制环节。具体的,一个ChClosedLoopDriver包括:转向控制器ChSteeringController和速度控制器ChSpeedController
在初始化一个ChClosedLoopDriver时,会自动生成上述两个控制器。

速度控制器ChSpeedController
https://api.projectchrono.org/classchrono_1_1vehicle_1_1_ch_speed_controller.html
速度控制器包括:通过代码设定恒定速度、或通过JSON文件读取速度配置,设置PID参数等。
速度控制器只有一个,即不管是采用何种driver,都是同一个速度控制器。而下面的转向控制器稍微会复杂一些。

转向控制器ChSteeringController
https://api.projectchrono.org/classchrono_1_1vehicle_1_1_ch_steering_controller.html
在这里插入图片描述转向控制器是一个基类,不同路径跟踪driver会有不同的转向控制器,例如接下来要重点介绍的ChPathFollowerDriver采用的是ChPathSteeringController控制器。

对于转向控制器,理论上也存在PID参数等,但在这个ChSteeringController基类中没有实现,而是在后面继承的类中进行的实现。

有一个新概念,叫“哨兵点”,和“目标点”:

  • Sentinel(哨兵): 通常用来监视或标记某个特定区域、路径或条件的存在。在仿真或游戏环境中,一个哨兵点可能用来指示玩家或系统需要特别注意的地方,或者作为触发某些事件的标记。
  • 通过SetLookAheadDistance函数,给出在仿真时“哨兵点”的位置,即我关注车辆前方多远的具体,在这个点范围内的变化对仿真产生影响。这个距离是以底盘为坐标系的,车辆“前方”。
  • Target(目标): 通常指一个要达到或影响的点。在仿真中,这可能是需要导航到的位置,或者是需要与之交互的对象。
    进一步解释:在仿真时,vehicle的真实位置,是target真正要到的位置,而为了仿真系统高效的运行,设置一个“安全距离/提前注意”的位置,作为哨兵点,在哨兵点外的轨迹暂时不考虑。类似于碰撞检测,在短时间内不会发生碰撞时,避免复杂的碰撞条件计算。

Specify the look-ahead distance. This defines the location of the “sentinel” point (in front of the vehicle, at the given distance from the chassis reference frame).

2、轨迹跟踪控制器 ChPathFollowerDriver

https://api.projectchrono.org/classchrono_1_1vehicle_1_1_ch_path_follower_driver.html

这个控制器包括:速度控制器ChSpeedController和轨迹转向控制器ChPathSteeringController。
正如1.1 所说,速度控制器都是一样的,这里重点介绍轨迹转向控制器。

ChPathSteeringController
https://api.projectchrono.org/classchrono_1_1vehicle_1_1_ch_path_steering_controller.html

这个控制器继承了基类ChSteeringController,包括上面所说的所有功能。除此之外,包括:

  • 设置PID参数 void SetGains (double Kp, double Ki, double Kd)
  • 计算目标点位置:由于需要跟踪轨迹,因此哨兵点给的位置不一定落在目标轨迹上,因此需要通过计算出真正需要抵达的目标点。这个目标点就通过CalcTargetLocation函数计算哨兵点对应轨迹上的最近点是哪个,用于具体的控制。

轨迹跟踪控制器部分的关键代码如下:

// 控制器创建与设置
ChPathFollowerDriver driver(hmmwv.GetVehicle(), path, "my_path", 5.0);	// 目标速度是5.0m/s,轨迹是path
driver.SetColor(ChColor(0.0f, 0.0f, 0.8f));
driver.GetSteeringController().SetLookAheadDistance(5);	// 设置转向控制器的哨兵点距离
driver.GetSteeringController().SetGains(0.8, 0, 0);      // 设置转向控制器的PID参数,这里P=0.8
driver.GetSpeedController().SetGains(0.4, 0, 0);			// 设置速度控制器的PID
driver.Initialize();

// 循环仿真部分。只需要进行子系统的时间同步,然后动力学仿真一步即可。
driver.Synchronize(time);
driver.Advance(step_size);

到这里已经介绍了,轨迹跟踪的控制器是如何工作的。但还没有介绍上面跟踪的轨迹是怎么来。接下来进行介绍。

3、轨迹

轨迹本质上是一个贝塞尔曲线BezierCurve,即:ChBezierCurve
https://api.projectchrono.org/classchrono_1_1_ch_bezier_curve.html

通过:

auto path = ChBezierCurve::read(vehicle::GetDataFile(path_file), closed_loop);

从文件读取一个轨迹,closed_loop表示,这个轨迹是否是一个闭环,即首尾相连?

3.1 轨迹文件

轨迹文件内包含的就是节点,第一行有两个数字,N和数字3或9,表示共有N个节点点,3或9表示两种不同的节点类型。从第二行开始,就是每个节点的具体坐标。例如,下图是一个200x200米的正方形环形的轨迹。贝塞尔曲线采用3次插值。
在这里插入图片描述

上面的是3列,即需要经过这写节点。如果是9列,则分别是:节点、进入控制点、离开控制点。更多关于样条曲线的内容参考之前我在知乎整理的一篇文章:【学习总结】连续时间SLAM(二)——B样条曲线

3.2 轨迹读取与传递给控制器

// 读取轨迹文件
auto path = ChBezierCurve::read(vehicle::GetDataFile(path_file), closed_loop);
// 将轨迹给轨迹跟踪控制器
ChPathFollowerDriver driver(hmmwv.GetVehicle(), path, "my_path", target_speed);
// ...
// 在仿真循环中
DriverInputs driver_inputs = driver.GetInputs();	// 获取沿轨迹运行时的控制量
hmmwv.Synchronize(time, driver_inputs, terrain);	// 将控制量同步给悍马车系统
hmmwv.Advance(step_size);			// 悍马车仿真一步。

4、完整代码

#include "chrono/utils/ChFilters.h"
#include "chrono_vehicle/ChVehicleModelData.h"
#include "chrono_vehicle/terrain/RigidTerrain.h"
#include "chrono_vehicle/driver/ChPathFollowerDriver.h"
#include "chrono_vehicle/utils/ChVehiclePath.h"
#include "chrono_vehicle/wheeled_vehicle/ChWheeledVehicleVisualSystemIrrlicht.h"
#include "chrono_models/vehicle/hmmwv/HMMWV.h"
#include "chrono_thirdparty/filesystem/path.h"

using namespace chrono;
using namespace chrono::geometry;
using namespace chrono::vehicle;
using namespace chrono::vehicle::hmmwv;

// 设定一些车辆参数
// Contact method type
ChContactMethod contact_method = ChContactMethod::SMC;
// Type of tire model (RIGID, FIALA, PAC89, PAC02, or TMEASY)
TireModelType tire_model = TireModelType::TMEASY;
// Type of engine model (SHAFTS, SIMPLE, SIMPLE_MAP)
EngineModelType engine_model = EngineModelType::SHAFTS;
// Type of transmission model (SHAFTS, SIMPLE_MAP)
TransmissionModelType transmission_model = TransmissionModelType::SHAFTS;
// Drive type (FWD, RWD, or AWD)
DrivelineTypeWV drive_type = DrivelineTypeWV::RWD;
// Steering type (PITMAN_ARM or PITMAN_ARM_SHAFTS)
// Note: Compliant steering requires higher PID gains.
SteeringTypeWV steering_type = SteeringTypeWV::PITMAN_ARM;
// Visualization type for vehicle parts (PRIMITIVES, MESH, or NONE)
VisualizationType chassis_vis_type = VisualizationType::PRIMITIVES;
VisualizationType suspension_vis_type = VisualizationType::PRIMITIVES;
VisualizationType steering_vis_type = VisualizationType::PRIMITIVES;
VisualizationType wheel_vis_type = VisualizationType::MESH;
VisualizationType tire_vis_type = VisualizationType::MESH;

// 车辆跟踪轨迹、速度的设定
// Input file names for the path-follower driver model
std::string path_file("paths/my_path.txt");
// Set to true for a closed-loop path and false for an open-loop
bool closed_loop = false;
// Desired vehicle speed (m/s)
double target_speed = 12;

// 地型设置
// Rigid terrain dimensions
double terrainHeight = 0;
double terrainLength = 300.0;  // size in X direction
double terrainWidth = 300.0;   // size in Y direction

// 可视化点,跟踪车辆底盘
// Point on chassis tracked by the chase camera
ChVector<> trackPoint(0.0, 0.0, 1.75);

// Simulation step size 仿真参数
double step_size = 2e-3;
double tire_step_size = 1e-3;
double t_end = 100;
// Render FPS
double fps = 60;


// =============================================================================

int main(int argc, char* argv[]) {
    GetLog() << "Copyright (c) 2017 projectchrono.org\nChrono version: " << CHRONO_VERSION << "\n\n";
    chrono::SetChronoDataPath("E:/codeGit/chrono/chrono/build/data/");              // change the default data loading path.
    chrono::vehicle::SetDataPath("E:/codeGit/chrono/chrono/build/data/vehicle/");              // change the vehicle data path

    // ----------------------
    // Create the Bezier path
    // ----------------------
    // From data file
    auto path = ChBezierCurve::read(vehicle::GetDataFile(path_file), closed_loop);
    // Bezier曲线文件:x行 y列,y=3/9. 3:节点坐标;9:节点,incoming控制点,outcoming控制点
    // read是一个静态公有成员函数。即使没有创建类的对象,也可以调用这些函数。
	
		// 计算初始车头朝向
    auto point0 = path->getPoint(0);
    auto point1 = path->getPoint(1);
    ChVector<> initLoc = point0;
    initLoc.z() = 0.5;
    ChQuaternion<> initRot = Q_from_AngZ(std::atan2(point1.y() - point0.y(), point1.x() - point0.x()));

    // ------------------------------
    // Create the vehicle and terrain
    // ------------------------------
    // Create the HMMWV vehicle, set parameters, and initialize
    HMMWV_Full hmmwv;
    hmmwv.SetCollisionSystemType(ChCollisionSystem::Type::BULLET);
    hmmwv.SetContactMethod(contact_method);
    hmmwv.SetChassisFixed(false);
    hmmwv.SetInitPosition(ChCoordsys<>(initLoc, initRot));
    hmmwv.SetEngineType(engine_model);
    hmmwv.SetTransmissionType(transmission_model);
    hmmwv.SetDriveType(drive_type);
    hmmwv.SetSteeringType(steering_type);
    hmmwv.SetTireType(tire_model);
    hmmwv.SetTireStepSize(tire_step_size);
    hmmwv.Initialize();

    hmmwv.SetChassisVisualizationType(chassis_vis_type);
    hmmwv.SetSuspensionVisualizationType(suspension_vis_type);
    hmmwv.SetSteeringVisualizationType(steering_vis_type);
    hmmwv.SetWheelVisualizationType(wheel_vis_type);
    hmmwv.SetTireVisualizationType(tire_vis_type);
	
		// 创建地形。
    // Create the terrain
    RigidTerrain terrain(hmmwv.GetSystem());
    ChContactMaterialData minfo;
    minfo.mu = 0.8f;
    minfo.cr = 0.01f;
    minfo.Y = 2e7f;
    auto patch_mat = minfo.CreateMaterial(contact_method);
    auto patch = terrain.AddPatch(patch_mat, CSYSNORM, terrainLength, terrainWidth);    // thinkness默认1.0
    patch->SetColor(ChColor(1, 0.5, 0.5));
    patch->SetTexture(vehicle::GetDataFile("terrain/textures/tile4.jpg"), 200, 200);
    terrain.Initialize();

    // ------------------------
    // Create the driver system
    // ------------------------
    ChPathFollowerDriver driver(hmmwv.GetVehicle(), path, "my_path", target_speed);     // ChDriver->ChClosedLoopDriver->ChPathFollowerDriver
    driver.SetColor(ChColor(0.0f, 0.0f, 0.8f));
    driver.GetSteeringController().SetLookAheadDistance(5);
    driver.GetSteeringController().SetGains(0.8, 0, 0);     // SetGains (double Kp, double Ki, double Kd)
    driver.GetSpeedController().SetGains(0.4, 0, 0);
    driver.Initialize();
		
		// 创建车辆可视化内容
    // ---------------------------------------
    // Create the vehicle Irrlicht application
    // ---------------------------------------
    auto vis = chrono_types::make_shared<ChWheeledVehicleVisualSystemIrrlicht>();
    vis->SetLogLevel(irr::ELL_NONE);
    vis->AttachVehicle(&hmmwv.GetVehicle());
    vis->SetWindowTitle("Steering PID Controller Demo");
    vis->SetHUDLocation(500, 20);       // HUD: 平视显示系统
    vis->SetChaseCamera(trackPoint, 6.0, 0.5);
    vis->Initialize();
    vis->AddSkyBox();
    vis->AddLogo();
    vis->AddLight(ChVector<>(-150, -150, 200), 300, ChColor(0.7f, 0.7f, 0.7f));
    vis->AddLight(ChVector<>(-150, +150, 200), 300, ChColor(0.7f, 0.7f, 0.7f));
    vis->AddLight(ChVector<>(+150, -150, 200), 300, ChColor(0.7f, 0.7f, 0.7f));
    vis->AddLight(ChVector<>(+150, +150, 200), 300, ChColor(0.7f, 0.7f, 0.7f));

		// 可视化哨兵点和目标点
    auto ballS = chrono_types::make_shared<ChVisualShapeSphere>(0.1);           // sentinel 哨兵
    auto ballT = chrono_types::make_shared<ChVisualShapeSphere>(0.1);
    ballS->SetColor(ChColor(1, 0, 0));
    ballT->SetColor(ChColor(0, 1, 0));
    int iballS = vis->AddVisualModel(ballS, ChFrame<>());
    int iballT = vis->AddVisualModel(ballT, ChFrame<>());
		
		// 记录地盘和驾驶员位置的加速度参数?
    // GC: gravity center,质心/底盘的加速度;  driver:驾驶员位置的加速度
    utils::ChRunningAverage fwd_acc_GC_filter(filter_window_size);      // fwd: forward,
    utils::ChRunningAverage lat_acc_GC_filter(filter_window_size);      // lat: latitute
    utils::ChRunningAverage fwd_acc_driver_filter(filter_window_size);
    utils::ChRunningAverage lat_acc_driver_filter(filter_window_size);

    // ---------------
    // Simulation loop
    // ---------------
    // Driver location in vehicle local frame
    ChVector<> driver_pos = hmmwv.GetChassis()->GetLocalDriverCoordsys().pos;

    // Number of simulation steps between miscellaneous events
    double render_step_size = 1 / fps;
    int render_steps = (int)std::ceil(render_step_size / step_size);

    // Initialize simulation frame counter and simulation time
    int sim_frame = 0;
    int render_frame = 0;

    hmmwv.GetVehicle().EnableRealtime(true);
    while (vis->Run()) {
        // Extract system state
        double time = hmmwv.GetSystem()->GetChTime();
        ChVector<> acc_CG = hmmwv.GetVehicle().GetChassisBody()->GetPos_dtdt();         // 获取车体地盘质心的加速度
        ChVector<> acc_driver = hmmwv.GetVehicle().GetPointAcceleration(driver_pos);    // 获取驾驶员所在位置点的加速度
        double fwd_acc_CG = fwd_acc_GC_filter.Add(acc_CG.x());          // 这是一步滤波,获取窗口范围内的平均加速度
        double lat_acc_CG = lat_acc_GC_filter.Add(acc_CG.y());
        double fwd_acc_driver = fwd_acc_driver_filter.Add(acc_driver.x());
        double lat_acc_driver = lat_acc_driver_filter.Add(acc_driver.y());

        // End simulation
        if (time >= t_end)
            vis->Quit();

        // Driver inputs
        DriverInputs driver_inputs = driver.GetInputs();

        // Update sentinel and target location markers for the path-follower controller.
        vis->UpdateVisualModel(iballS, ChFrame<>(driver.GetSteeringController().GetSentinelLocation()));
        vis->UpdateVisualModel(iballT, ChFrame<>(driver.GetSteeringController().GetTargetLocation()));

        vis->BeginScene();
        vis->Render();
        vis->EndScene();


        // Update modules (process inputs from other modules)
        driver.Synchronize(time);
        terrain.Synchronize(time);
        hmmwv.Synchronize(time, driver_inputs, terrain);
        vis->Synchronize(time, driver_inputs);

        // Advance simulation for one timestep for all modules
        driver.Advance(step_size);
        terrain.Advance(step_size);
        hmmwv.Advance(step_size);
        vis->Advance(step_size);

        // Increment simulation frame number
        sim_frame++;
    }
    return 0;
}

搞清楚之前的可视化、地型、vehicle后,这部分控制的内容好像并不复杂。

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

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

相关文章

C++ //练习 6.6 说明形参、局部变量以及局部静态变量的区别。编写一个函数,同时用到这三种形式。

C Primer&#xff08;第5版&#xff09; 练习 6.6 练习 6.6 说明形参、局部变量以及局部静态变量的区别。编写一个函数&#xff0c;同时用到这三种形式。 环境&#xff1a;Linux Ubuntu&#xff08;云服务器&#xff09; 工具&#xff1a;vim 代码块 /********************…

C语言—数组(2)

在不知道数组类型的情况下&#xff0c;如何确定数组元素的个数? 一维数组:sizeof(a) /sizeof(a[0]) 二维数组:sizeof(a[0])/sizeof(a[0][0]) 当然此次我做的题没体现出来我在末尾写一段演示了一下 因为二维数组也可以看成是一个一维数组 25⬆2.131. 一个二维数组赋了初值&…

Github 2024-02-13 开源项目日报 Top9

根据Github Trendings的统计&#xff0c;今日(2024-02-13统计)共有9个项目上榜。根据开发语言中项目的数量&#xff0c;汇总情况如下&#xff1a; 开发语言项目数量JavaScript项目2Python项目2C项目2TypeScript项目2Rust项目1Go项目1Dart项目1Java项目1C项目1 系统设计指南 …

彻底改变单词嵌入和文本分类

目录 一、介绍二、起源与发展三、技术基础四、FastText 的优点五、代码六、结论 一、介绍 2016 年由 Facebook 的 AI Research &#xff08;FAIR&#xff09; 团队推出的 FastText 已迅速成为自然语言处理 &#xff08;NLP&#xff09; 领域的基石。这种创新的词嵌入和文本分类…

【MySQL】:分组查询、排序查询、分页查询、以及执行顺序

&#x1f3a5; 屿小夏 &#xff1a; 个人主页 &#x1f525;个人专栏 &#xff1a; MySQL从入门到进阶 &#x1f304; 莫道桑榆晚&#xff0c;为霞尚满天&#xff01; 文章目录 &#x1f4d1;前言一. 分组查询1.1 语法1.2 where与having区别1.3 注意事项:1.4 案例: 二. 排序查询…

力扣精选算法100道——【模板】前缀和 (二维)

目录 &#x1f388;题目解析 &#x1f388;算法原理 &#x1f388;实现代码 二维前缀和【模板】 &#x1f388;题目解析 上一题我们讲述了一维的前缀和求法。 第一行三个参数&#xff0c;n是行数3&#xff0c;m是列数4&#xff0c;q3代表查询次数 接下来就是n行m列的矩阵…

剪辑视频衔接怎么操作 剪辑视频衔接过渡自然方法 剪辑视频教程新手入门 抖音剪辑短视频 会声会影视频制作教程

视频剪辑在现代社交媒体和数字媒体时代中变得越来越重要。它广泛应用于各种领域&#xff0c;包括电影制作、广告宣传、教育培训、社交媒体内容创作等。 一、剪辑视频衔接怎么操作 会声会影是一款功能强大、易于使用的视频编辑软件。接下来我们拿会声会影为例讲解剪辑视频如何…

探索设计模式的魅力:捕捉变化的风-用观察者模式提升用户体验

设计模式专栏&#xff1a;http://t.csdnimg.cn/U54zu 目录 一、引言 核心概念 应用场景 可以解决的问题 二、场景案例 2.1 不用设计模式实现 2.2 存在问题 2.3 使用设计模式实现 2.4 成功克服 三、工作原理 3.1 结构图和说明 3.2 工作原理详解 3.3 实现步骤 四、 优…

2024-02-13 Unity 编辑器开发之编辑器拓展4 —— EditorGUIUtility

文章目录 1 EditorGUIUtility 介绍2 加载资源2.1 Eidtor Default Resources2.2 不存在返回 null2.3 不存在则报错2.4 代码示例 3 搜索框查询、对象选中提示3.1 ShowObjectPicker3.2 PingObject3.3 代码示例 4 窗口事件传递、坐标转换4.1 CommandEvent4.2 GUIPoint 和 ScreenPoi…

关于在分布式环境中RVN和使用场景的介绍3

简介 在《关于在分布式环境中RVN和使用场景的介绍2》和《关于在分布式环境中RVN和使用场景的介绍1》中我们介绍了RVN的概念和在一些具体用例中的使用。在本文中我们讨论一下在分布式环境中使用RVN需要注意的问题。 问题 我们在收到一条待处理的事件时&#xff0c;需要检查该…

代码随想录算法训练营Day56|583. 两个字符串的删除操作、72. 编辑距离

目录 583. 两个字符串的删除操作 前言 思路 算法实现 法二 72. 编辑距离 前言 思路 算法实现 总结 583. 两个字符串的删除操作 题目链接 文章链接 前言 本题与上一题不同的子序列相比&#xff0c;变化就是两个字符串都可以进行删除操作了。 思路 利用动规五部曲进…

Ocr之TesseractOcr的安装及使用

目录 一、安装环境 二、安装内容 三、安装过程及识别测试 1. 安装过程 2. 程序编写 总结 1. 安装复杂度较低 2. 国外开源Ocr 3. 可设置识别参数 4. 工具类 一、 系统环境windows 10 linux环境也可安装, 可借鉴此篇文章>> | 二、安装内容 Tesseract exe 程序安…

《金融人工智能:用python实现ai量化交易》

融合了数学、python、深度学习以及金融知识&#xff0c;是本推荐的好书。请收藏本文&#xff0c;读后再给大学总结。

React18原理: 核心包结构与两大工作循环

React核心包结构 1 ) react react基础包&#xff0c;只提供定义 react组件(ReactElement)的必要函数一般来说需要和渲染器(react-dom,react-native)一同使用在编写react应用的代码时, 大部分都是调用此包的api比如, 我们定义组件的时候&#xff0c;就是它提供的class Demo ext…

Elasticsearch:适用于 iOS 和 Android 本机应用程序的 Elastic APM

作者&#xff1a;来自 Elastic Akhilesh Pokhariyal, Cesar Munoz, Bryce Buchanan 适用于本机应用程序的 Elastic APM 提供传出 HTTP 请求和视图加载的自动检测&#xff0c;捕获自定义事件、错误和崩溃&#xff0c;并包括用于数据分析和故障排除目的的预构建仪表板。 适用于 …

LeetCode:83和82.删除排序链表中的重复元素I,II

这两题算是链表的基础题&#xff0c;就遍历删除没啥特点&#xff0c; 83甚至不需要考虑第一个结点的特殊情况&#xff0c;属实是名副其实的easy了 LeetCode&#xff1a;21.合并两个有序链表之第一次的特殊情况-CSDN博客 83. 删除排序链表中的重复元素 - 力扣&#xff08;Lee…

[NSSCTF]-Web:[SWPUCTF 2021 新生赛]easyrce解析

先看网页 代码审计&#xff1a; error_reporting(0); &#xff1a;关闭报错&#xff0c;代码的错误将不会显示 highlight_file(__FILE__); &#xff1a;将当前文件的源代码显示出来 eval($_GET[url]); &#xff1a;将url的值作为php代码执行 解题&#xff1a; 题目既然允许…

备战蓝桥杯---动态规划(入门1)

先补充一下背包问题&#xff1a; 于是&#xff0c;我们把每一组当成一个物品&#xff0c;f[k][v]表示前k组花费v的最大值。 转移方程还是max(f[k-1][v],f[k-1][v-c[i]]w[i]) 伪代码&#xff08;注意循环顺序&#xff09;&#xff1a; for 所有组&#xff1a; for vmax.....0…

wayland(xdg_wm_base) + egl + opengles 纹理贴图进阶实例(四)

文章目录 前言一、使用gstreamer 获取 pattern 图片二、代码实例1. pattern 图片作为纹理数据源的代码实例1.1 基于opengles2.0 接口的 egl_wayland_texture2_1.c1.2 基于opengles3.0 接口的 egl_wayland_texture3_1.c2. xdg-shell-client-protocol.h 和 xdg-shell-protocol.c3…

算法学习——LeetCode力扣二叉树篇8

算法学习——LeetCode力扣二叉树篇8 669. 修剪二叉搜索树 669. 修剪二叉搜索树 - 力扣&#xff08;LeetCode&#xff09; 描述 给你二叉搜索树的根节点 root &#xff0c;同时给定最小边界low 和最大边界 high。通过修剪二叉搜索树&#xff0c;使得所有节点的值在[low, high…