css做网站/百度电商平台app

css做网站,百度电商平台app,长沙php网站建设,wordpress字体目录下文章目录 1. 纵向控制算法1.1 算法结构1.1.1 外环:位置环1.1.2 内环:速度环 1.2 参数整定 2. 代码解析2.1 控制器初始化 LonController::Init()2.1.1 PID控制参数和标定表参数加载2.1.2 PID控制器初始化2.1.3 超前/滞后控制器初始化2.1.4 俯仰角滤波器初…

文章目录

  • 1. 纵向控制算法
    • 1.1 算法结构
      • 1.1.1 外环:位置环
      • 1.1.2 内环:速度环
    • 1.2 参数整定
  • 2. 代码解析
    • 2.1 控制器初始化 LonController::Init()
      • 2.1.1 PID控制参数和标定表参数加载
      • 2.1.2 PID控制器初始化
      • 2.1.3 超前/滞后控制器初始化
      • 2.1.4 俯仰角滤波器初始化
      • 2.1.5 标定表插值查表器初始化
    • 2.2 加速度命令计算 LonController::ComputeControlCommand()
      • 2.2.1 纵向误差计算
      • 2.2.2 加速度控制命令计算
      • 2.2.3 油门控制命令计算


本章将详细讲解Apollo纵向控制器LonController - lon_based_pid_controller。

1. 纵向控制算法

Apollo 自动驾驶平台的纵向控制算法采用位置-速度双环 PID 控制器,用于实现车辆在纵向运动中的精确控制。该算法通过分层控制结构,将目标位置和速度的控制任务分解为外环(位置环)和内环(速度环),从而实现高精度的跟踪和稳定的动态响应。
在这里插入图片描述

1.1 算法结构

1.1.1 外环:位置环

输入:

  • 目标位置(来自规划模块)。
  • 当前车辆位置(来自定位模块)。

输出:

  • 目标速度(作为内环的设定值)。

控制逻辑:

  • 计算位置误差:
    e p o s i t i o n = t a r g e t _ p o s i t i o n − c u r r e n t _ p o s i t i o n e e_{position}=target\_position − current\_positione eposition=target_positioncurrent_positione
  • 使用 PID 控制器计算目标速度:
    t a r g e t _ v e l o c i t y = K p _ p o s ⋅ e p o s i t i o n + K i _ p o s ⋅ ∫ e p o s i t i o n d t + K d _ p o s ⋅ d e p o s i t i o n d t target\_velocity =K_{p\_pos} \cdot e_{position}+K_{i\_pos} \cdot \int e_{position} dt+K_{d\_pos} \cdot \frac{d e_{position}}{dt} target_velocity=Kp_poseposition+Ki_posepositiondt+Kd_posdtdeposition
  • 对目标速度进行限幅,确保其在合理范围内。

1.1.2 内环:速度环

输入:

  • 目标速度(来自外环)。
  • 当前车辆速度(来自车辆状态反馈)。

输出:

  • 控制量(如油门或刹车指令)。

控制逻辑:

  • 计算速度误差:
    e v e l o c i t y = t a r g e t _ v e l o c i t y − c u r r e n t _ v e l o c i t y e_{velocity}=target\_velocity−current\_velocity evelocity=target_velocitycurrent_velocity

  • 使用 PID 控制器计算控制量:
    c o n t r o l _ o u t p u t = K p _ v e l ⋅ e v e l o c i t y + K i _ v e l ⋅ ∫ e v e l o c i t y d t + K d _ v e l ⋅ d e v e l o c i t y d t control\_output =K_{p\_vel} \cdot e_{velocity}+K_{i\_vel} \cdot \int e_{velocity} dt+K_{d\_vel} \cdot \frac{d e_{velocity}}{dt} control_output=Kp_velevelocity+Ki_velevelocitydt+Kd_veldtdevelocity

  • 对控制量进行限幅,确保其在执行器的可操作范围内。

1.2 参数整定

PID 控制器的性能依赖于参数的合理整定。以下是参数整定的基本原则:

  • Kp:调整系统对目标的响应速度,但过大的Kp可 能会导致明显的超调和振荡,降低系统的动态性能。
  • Ki:有利于减小响应的超调量,减小系统的稳态误 差,提高控制精度。
  • Kd:有利于减小系统超调量,提高系统稳定性

在这里插入图片描述

总结一句话就是:先调Kp,再调Ki,先调速度闭环,再调位置闭环。

2. 代码解析

其实官方已经给出了一个比较详细的图(/apollo/modules/control/controllers/lon_based_pid_controller/docs/images/control-controller-lon-based-pid-controller.png)来展示LonController 的代码框架,主要包含两部分:

  • 控制器初始化 LonController::Init(),完成控制参数和标定表参数的加载,初始化位置\速度PID控制器,初始化位置\速度超前/滞后控制器等等准备工作;
  • 加速度命令计算 LonController::ComputeControlCommand(),这是纵向控制命令计算的整个流程,大体上也可以分为3步:
    • 首先,根据参考轨迹和Frenet坐标系,计算出纵向误差;
    • 然后,根据位置PID控制器和速度PID控制器计算出了参考加速度;
    • 最后,根据车辆当前的速度和所需的加速度并且参照标定表计算出油门控制命令。

在这里插入图片描述

2.1 控制器初始化 LonController::Init()

2.1.1 PID控制参数和标定表参数加载

Status LonController::Init(std::shared_ptr<DependencyInjector> injector) {if (!ControlTask::LoadConfig<LonBasedPidControllerConf>(&lon_based_pidcontroller_conf_)) {AERROR << "failed to load control conf";return Status(ErrorCode::CONTROL_INIT_ERROR,"failed to load lon control_conf");}if (!ControlTask::LoadCalibrationTable(&calibration_table_)) {AERROR << "failed to load calibration table";return Status(ErrorCode::CONTROL_INIT_ERROR,"lon failed to load calibration table");}...
}

PID控制参数位于"/apollo/modules/control/controllers/lon_based_pid_controller/conf/controller_conf.pb.txt",这里使用ProtoBuf,将该文件里面的所有数据保存到lon_based_pidcontroller_conf_对象里面。

在这里插入图片描述

标定表参数位于"/apollo/modules/control/control_component/conf/calibration_table.pb.txt",这里同样使用ProtoBuf,将该文件里面的所有数据保存到calibration_table_对象里面。

在这里插入图片描述

上述关于如何ProtoBuf加载配置参数,在Planning的初始化部分已经详细介绍过,如果还有不懂的,大家可以往前看一看。关于什么是标定表,2.1.5节会详细介绍。

2.1.2 PID控制器初始化

Status LonController::Init(std::shared_ptr<DependencyInjector> injector) {...// 位置、速度PID控制器初始化station_pid_controller_.Init(lon_based_pidcontroller_conf_.station_pid_conf());speed_pid_controller_.Init(lon_based_pidcontroller_conf_.low_speed_pid_conf());...
}

Apollo官方提供了3个PID控制器,默认使用PIDController:
[图片]

PIDBCController和PIDICController主要针对积分饱和问题做了优化:

  • IC -> 积分遇限消弱法
  • BC -> 反馈抑制抗饱和
  • 设定阈值,偏差大时才启用积分 , 即积分分离

这里对PIDController的初始化也比较简单:

[图片]

2.1.3 超前/滞后控制器初始化

超前/滞后控制器默认关闭,通过配置enable_reverse_leadlag_compensation可以打开。

Status LonController::Init(std::shared_ptr<DependencyInjector> injector) {...// 位置、速度超前/滞后控制器初始化if (enable_leadlag) {station_leadlag_controller_.Init(lon_based_pidcontroller_conf_.reverse_station_leadlag_conf(), ts);speed_leadlag_controller_.Init(lon_based_pidcontroller_conf_.reverse_speed_leadlag_conf(), ts);}...
}

[图片]

2.1.4 俯仰角滤波器初始化

初始化俯仰角滤波器 digital_filter_pitch_angle_,主要是设置滤波器的周期和滤波系数。俯仰角滤波器用于车辆俯仰角的过滤,而车辆俯仰角用于计算坡度加速度补偿。

Status LonController::Init(std::shared_ptr<DependencyInjector> injector) {...// 俯仰角低通滤波处理,考虑坡度产生的纵向加速度SetDigitalFilterPitchAngle(lon_controller_conf);...
}

LonController::SetDigitalFilterPitchAngle

void LonController::SetDigitalFilterPitchAngle(const LonControllerConf &lon_controller_conf) {//配置中读到的参数滤波器的截止频率存到变量cutoff_freq中double cutoff_freq = lon_controller_conf.pitch_angle_filter_conf().cutoff_freq();//配置中读到的参数滤波器的采样周期存到变量ts中double ts = lon_controller_conf.ts();SetDigitalFilter(ts, cutoff_freq, &digital_filter_pitch_angle_);
}

LonController::SetDigitalFilter

void LonController::SetDigitalFilter(double ts, double cutoff_freq,common::DigitalFilter *digital_filter) {std::vector<double> denominators;std::vector<double> numerators;common::LpfCoefficients(ts, cutoff_freq, &denominators, &numerators);digital_filter->set_coefficients(denominators, numerators);
}

2.1.5 标定表插值查表器初始化

Status LonController::Init(std::shared_ptr<DependencyInjector> injector) {...InitControlCalibrationTable();...
}

(1)为什么使用标定表?

  • 纵向动力学包括发动机/电动机、变速器等传动机构,建模难度大,计算复杂度高
  • 不同车辆的动力学模型不相同
  • 同一车辆的动力学模型会随着轮胎磨损等影响而变化

因此,Apollo采用标定表的方式进行纵向控制,从而避免了对于纵向动力学的建模过程。

上面其实是一些比较专业的说法,Apollo官方给出了以下的解释,其实更简单明了:Apollo使用的车辆底盘控制接口是油门、刹车,所以要使用油门、刹车标定表!换而言之,如果底盘控制接口不是油门、刹车,就不要这两个表。

其实现在自动驾驶,大多数都使用纵向加速度作为纵向控制接口。所以大家忘了这两个表吧!!!

[图片]

(2)标定表介绍

参考论文:1808.10134 Baidu Apollo Auto-Calibration System - An
Industry-Level Data-Driven and Learning based Vehicle Longitude
Dynamic Calibrating Algorithm (arxiv.org)

这篇论文是Apollo发表的一种基于离线模型和在线学习的(对于纵向动力学)自动校准系统。首先从人类驾驶数据中生成离线标定表。离线表作为后期使用的初始猜测,只需要二十分钟的数据收集和处理。然后,基于实时性能分析,采用在线学习算法适当更新初始表(离线表)。
基于人体驾驶数据,生成标定表,将油门、刹车、车速作为输入,加速度作为输出。简单来说,就是我们有了标定表之后,可以根据当前速度和所需加速度确定油门/刹车控制量。
在这里插入图片描述

其中,T为标定表,acc为期望加速度,v为当前车速,cmd为控制指令
在这里插入图片描述

论文中提到了离线模型和在线模型这两种调整标定表的过程:

  • 离线模型:离线模型从人工驾驶数据中生成最能反映车辆行驶时纵向性能的初始标定表。
    离线算法的工作流程包括:( 1 )采集人类驾驶数据;( 2 )对数据进行预处理并选择输入特征;( 3 )通过机器学习模型生成标定表

  • 在线学习:自动驾驶模式下,在线算法根据实时反馈即时调整离线表格。其目的是基于人工驾驶数据建立的离线模型,以最佳匹配当前车辆动力学。该算法需要处理的几个挑战包括车辆载荷的频繁变化和机械部件的长期疲劳。
    在线算法的工作流程包括:( 1 )实时采集车辆状态和反馈;( 2 )预处理和筛选数据;( 3 )相应调整标定表。

(3)标定表插值查表器
在2.1.1节就已经从配置文件中载入了标定表的参数,并存到calibration_table_对象里面。这里使用该对象里面的数据,创建一个二维插值查表器control_interpolation_,由于加速度和加速度被合成了一张表,所以后续只需要通过车速和目标加速度就可以查表插值计算得到目标油门/刹车开度。
在这里插入图片描述

2.2 加速度命令计算 LonController::ComputeControlCommand()

2.2.1 纵向误差计算

纵向误差计算在一个单独的成员函数ComputeLongitudinalErrors中。
注:这个函数其实计算了横纵向所有的误差。

Status LonController::ComputeControlCommand(const localization::LocalizationEstimate *localization,const canbus::Chassis *chassis,const planning::ADCTrajectory *planning_published_trajectory,control::ControlCommand *cmd) {...ComputeLongitudinalErrors(trajectory_analyzer_.get(), preview_time, ts, debug);...                                           
}

在讲解误差计算之前,先给出一些基本概念。如下图,Planning给出的轨迹为虚线所示,自车当前的位置 ( x , y ) (x,y) (x,y)。Planning参考轨迹起始点为全局时间戳,其他点采用相对时间戳表示,即相对于起始点的时间戳。

在这里插入图片描述

为了计算车辆纵向的位置误差和速度误差,我们需要知道车辆在轨迹上的实际位置点–匹配点,以及目标位置点–参考点或预瞄点

  • 匹配点( x m a t c h {{x}}{}_{{match}} xmatch , y m a t c h {{y}}{}_{{match}} ymatch ):参考路径上,与自车当前位置距离最近点。由位置寻找,与相对时间戳无关。
void LonController::ComputeLongitudinalErrors(const TrajectoryAnalyzer *trajectory_analyzer, const double preview_time,const double ts, SimpleLongitudinalDebug *debug) {...// 找到距离车辆位置最近的参考路径点// 匹配最近点时:插值法+优选法(黄金分割法)来找到最近的点auto matched_point = trajectory_analyzer->QueryMatchedPathPoint(vehicle_state->x(), vehicle_state->y());// 根据匹配点建立Frenet坐标系,并计算横/纵向坐标trajectory_analyzer->ToTrajectoryFrame(vehicle_state->x(), vehicle_state->y(), vehicle_state->heading(),vehicle_state->linear_velocity(), matched_point, &s_matched,&s_dot_matched, &d_matched, &d_dot_matched);...
}

匹配点的计算使用了黄金分隔法来加快求解速度,可以参考 https://en.wikipedia.org/wiki/Golden-section_search 。

得到匹配点后,就是计算该点的Frenet坐标 ( s , s ˙ , d , d ˙ ) (s,\dot{s} ,d,\dot{d} ) (s,s˙,d,d˙)
车辆在Frenet坐标系下的相对坐标表示:
[图片]

车辆的全局坐标需考虑参考点的纵向里程距离 s m a t c h {{s}}{}_{{match}} smatch
[图片]

车辆的纵向速度和横向速度如下:
[图片]

  • 参考点( x r e f {{x}}{}_{{ref}} xref , y r e f {{y}}{}_{{ref}} yref):参考轨迹上,当前时刻车辆应该处于的位置。
  • 预瞄点( x p r e {{x}}{}_{{pre}} xpre, y p r e {{y}}{}_{{pre}} ypre):参考轨迹上,预瞄绝对时间处车辆应该处于的位置。

预瞄绝对时间戳 = 参考绝对时间戳 + 预瞄时间。

void LonController::ComputeLongitudinalErrors(const TrajectoryAnalyzer *trajectory_analyzer, const double preview_time,const double ts, SimpleLongitudinalDebug *debug) {...double preview_time = lon_controller_conf.preview_window() * ts;// 当前时间确定参考点,预瞄时间确定预瞄点// 预瞄时间 = 预瞄窗口数目 * 预瞄窗口时间 (此例为 20 * 0.01 = 0.2s)double current_control_time = ::apollo::cyber::Clock::NowInSeconds();double preview_control_time = current_control_time + preview_time;// 根据绝对时间戳匹配参考点和预瞄点TrajectoryPoint reference_point =trajectory_analyzer->QueryNearestPointByAbsoluteTime(current_control_time);TrajectoryPoint preview_point =trajectory_analyzer->QueryNearestPointByAbsoluteTime(preview_control_time);...
}
// header_time_为参考轨迹的全局时间戳
// 相对路径时间戳 = 绝对时间戳 - 参考轨迹全局时间戳
// 最后根据相对路径时间戳找到参考轨迹对应点
TrajectoryPoint TrajectoryAnalyzer::QueryNearestPointByAbsoluteTime(const double t) const {return QueryNearestPointByRelativeTime(t - header_time_);
}

最后根据匹配点和参考点/预瞄点计算位置误差和速度误差:
根据参考点计算出的位置和速度误差如式(5)所示:
[图片]

根据预瞄点计算出的位置和速度误差如式(6)所示:
[图片]

在之后的加速度控制命令计算中,可以自由选择使用参考点还是预瞄点的位置/速度误差,取决于参数配置文件。

void LonController::ComputeLongitudinalErrors(const TrajectoryAnalyzer *trajectory_analyzer, const double preview_time,const double ts, SimpleLongitudinalDebug *debug) {...//纵向位置误差debug.station_error=参考点路径点的累积弧长-匹配点的累积弧长(匹配点就是路径最近点)debug->set_station_error(reference_point.path_point().s() - s_matched);debug->set_speed_error(reference_point.v() - s_dot_matched);  // 速度误差 = 参考点速度 - 匹配点速度 // 预览点位置误差 = 预览点的纵向位置s - 匹配点纵向位置sdebug->set_preview_station_error(preview_point.path_point().s() - s_matched);// 预览点速度误差 = 预览点的纵向速度v - 匹配点纵向速度debug->set_preview_speed_error(preview_point.v() - s_dot_matched);...
}

2.2.2 加速度控制命令计算

这部分对照第一张图,更容易理解。其实也就是计算好相应的误差后带入到PID控制器即可。

1)位置PID控制器

输入:位置偏差 = 规划位置 - 实际位置
输出:速度补偿

Status LonController::ComputeControlCommand(const localization::LocalizationEstimate *localization,const canbus::Chassis *chassis,const planning::ADCTrajectory *planning_published_trajectory,control::ControlCommand *cmd) {...double station_error_limit = lon_based_pidcontroller_conf_.station_error_limit();double station_error_limited = 0.0; // 限幅后的纵向位置误差// 考虑预瞄时纵向位置偏差的上下限不同if (lon_based_pidcontroller_conf_.enable_speed_station_preview()) {// preview_station_error = 预览点纵向位置 - 匹配点纵向位置station_error_limited = common::math::Clamp(debug->preview_station_error(),-station_error_limit, station_error_limit);} else {// station_error = 参考点纵向位置-匹配点纵向位置station_error_limited = common::math::Clamp(debug->station_error(), -station_error_limit,station_error_limit);}if (trajectory_message_->gear() == canbus::Chassis::GEAR_REVERSE) {if (CheckPit::CheckInPit(debug, &lon_based_pidcontroller_conf_,injector_->vehicle_state()->linear_velocity(),trajectory_message_->is_replan())) {ADEBUG << "in pit";station_pid_controller_.SetPID(lon_based_pidcontroller_conf_.pit_station_pid_conf());speed_pid_controller_.SetPID(lon_based_pidcontroller_conf_.pit_speed_pid_conf());} else {station_pid_controller_.SetPID(lon_based_pidcontroller_conf_.reverse_station_pid_conf());speed_pid_controller_.SetPID(lon_based_pidcontroller_conf_.reverse_speed_pid_conf());}if (enable_leadlag) {station_leadlag_controller_.SetLeadlag(lon_based_pidcontroller_conf_.reverse_station_leadlag_conf());speed_leadlag_controller_.SetLeadlag(lon_based_pidcontroller_conf_.reverse_speed_leadlag_conf());}} else if (injector_->vehicle_state()->linear_velocity() <= lon_based_pidcontroller_conf_.switch_speed()) {if (CheckPit::CheckInPit(debug, &lon_based_pidcontroller_conf_,injector_->vehicle_state()->linear_velocity(),trajectory_message_->is_replan())) {ADEBUG << "in pit";//速度PID控制器对象speed_pid_controller_加载控制配置文件中低速PID参数station_pid_controller_.SetPID(lon_based_pidcontroller_conf_.pit_station_pid_conf());speed_pid_controller_.SetPID(lon_based_pidcontroller_conf_.pit_speed_pid_conf());} else {station_pid_controller_.SetPID(lon_based_pidcontroller_conf_.station_pid_conf());speed_pid_controller_.SetPID(lon_based_pidcontroller_conf_.low_speed_pid_conf());}} else {//速度PID控制器对象加载控制配置文件中高速PID参数,通常低速PID参数要更大些station_pid_controller_.SetPID(lon_based_pidcontroller_conf_.station_pid_conf());speed_pid_controller_.SetPID(lon_based_pidcontroller_conf_.high_speed_pid_conf());}// 位置环输出到速度环输入补偿,也就是速度环为内环// delta_s =vt 我们期望在当前纵向偏差下的速度补偿//速度偏差 = 位置PID控制器根据(限幅后位置误差,采样周期)计算出控制量即速度double speed_offset = station_pid_controller_.Control(station_error_limited, ts);if (enable_leadlag) {speed_offset = station_leadlag_controller_.Control(speed_offset, ts);}...
}

2)速度PID控制器

输入:速度偏差 = 速度误差(规划速度 - 实际速度) + 速度补偿
输出:加速度补偿

Status LonController::ComputeControlCommand(const localization::LocalizationEstimate *localization,const canbus::Chassis *chassis,const planning::ADCTrajectory *planning_published_trajectory,control::ControlCommand *cmd) {...double speed_controller_input = 0.0;double speed_controller_input_limit = lon_based_pidcontroller_conf_.speed_controller_input_limit();double speed_controller_input_limited = 0.0;if (lon_based_pidcontroller_conf_.enable_speed_station_preview()) {// 速度控制器的输入 = 位置控制器计算出的speed_offset + 当前时间向前加上预览时间在轨迹上的对应点的速度和当前车速的偏差speed_controller_input = speed_offset + debug->preview_speed_error();} else {// 速度控制器的输入 = 位置控制器计算出的speed_offset + 参考点车速和当前车速的偏差speed_controller_input = speed_offset + debug->speed_error();}speed_controller_input_limited = common::math::Clamp(speed_controller_input, -speed_controller_input_limit,speed_controller_input_limit);double acceleration_cmd_closeloop = 0.0;// 求解速度环输出,给出加速度结果   v = at//闭环的加速度指令就等于速度PID控制器根据速度控制器的输入,以及采样周期去计算acceleration_cmd_closeloop = speed_pid_controller_.Control(speed_controller_input_limited, ts);...
}

3)期望加速度

期望加速度 = 加速度补偿 + 预瞄点参考加速度 + 坡度加速度补偿

  Status LonController::ComputeControlCommand(const localization::LocalizationEstimate *localization,const canbus::Chassis *chassis,const planning::ADCTrajectory *planning_published_trajectory,control::ControlCommand *cmd) {...//定义斜坡补偿加速度 = (重力加速度 * 车辆俯仰角的正弦值)再经过数字滤波器滤波得到斜坡加速度补偿double slope_offset_compensation = lon_based_pidcontroller_conf_.use_opposite_slope_compensation() *GRA_ACC * std::sin(vehicle_pitch_rad + FLAGS_pitch_offset_deg * M_PI / 180);//判断坡道补偿加速度是否为非数NaN,当浮点数过小下溢就可能出现NaN非数if (std::isnan(slope_offset_compensation)) {slope_offset_compensation = 0;}debug->set_slope_offset_compensation(slope_offset_compensation);//总的加速度指令 = 闭环加速度指令 + 预览参考加速度 + 坡道补偿加速度double acceleration_cmd = acceleration_cmd_closeloop + debug->preview_acceleration_reference() +lon_based_pidcontroller_conf_.enable_slope_offset() * debug->slope_offset_compensation();...
}

不同车辆的纵向控制大致分为两种:

  • 加速度命令:对于加速度命令控制的车辆,到这里已经计算完成,限幅后可直接发给底层控制器
  • 油门/刹车命令:需根据加速度命令参照标定表继续出计算油门/刹车

2.2.3 油门控制命令计算

根据标定表插值查表,计算油门/刹车控制命令。这部分很简单,唯一需要说一下的是,最后根据acceleration_lookup正负,决定将查表值calibration_value赋值给油门还是刹车。

标定表输入:速度、加速度
标定表输出:油门/刹车命令

   Status LonController::ComputeControlCommand(const localization::LocalizationEstimate *localization,const canbus::Chassis *chassis,const planning::ADCTrajectory *planning_published_trajectory,control::ControlCommand *cmd) {...//定义油门指令的下边界,为 车辆配置里的throttle_deadzone 和 lon_controller_conf配置里的throttle_minimum_action 两者中的较大值double throttle_lowerbound = std::max(vehicle_param_.throttle_deadzone(),lon_based_pidcontroller_conf_.throttle_minimum_action());double brake_lowerbound = std::max(vehicle_param_.brake_deadzone(),lon_based_pidcontroller_conf_.brake_minimum_action());double calibration_value = 0.0;//要用来查表加速度,若R档为加速度控制指令取反,非R档保持加速度控制指令double acceleration_lookup = (chassis->gear_location() == canbus::Chassis::GEAR_REVERSE)? -acceleration_cmd: acceleration_cmd;double acceleration_lookup_limited = vehicle_param_.max_acceleration() +lon_based_pidcontroller_conf_.enable_slope_offset() * debug->slope_offset_compensation();double acceleration_lookup_limit = 0.0;if (lon_based_pidcontroller_conf_.use_acceleration_lookup_limit()) {acceleration_lookup_limit = (acceleration_lookup > acceleration_lookup_limited)? acceleration_lookup_limited: acceleration_lookup;}//是否用预览点速度来查标定表(车速-加速度-控制指令百分数)if (FLAGS_use_preview_speed_for_table) {if (lon_based_pidcontroller_conf_.use_acceleration_lookup_limit()) {calibration_value = control_interpolation_->Interpolate(std::make_pair(std::fabs(debug->preview_speed_reference()),acceleration_lookup_limit));} else {// 用chassis里反馈的实际速度 加速度 根据标定表线性插值得到控制量百分数calibration_valuecalibration_value = control_interpolation_->Interpolate(std::make_pair(std::fabs(debug->preview_speed_reference()), acceleration_lookup));}} else {if (lon_based_pidcontroller_conf_.use_acceleration_lookup_limit()) {calibration_value = control_interpolation_->Interpolate(std::make_pair(std::fabs(injector_->vehicle_state()->linear_velocity()),acceleration_lookup_limit));} else {calibration_value = control_interpolation_->Interpolate(std::make_pair(std::fabs(injector_->vehicle_state()->linear_velocity()),acceleration_lookup));}}// 油门/刹车命令处理if (acceleration_lookup >= 0) {if (calibration_value >= 0) {//设置油门控制百分数,为油门下边界和查表得到的控制百分数之间的较大值throttle_cmd = std::max(calibration_value, throttle_lowerbound);} else {throttle_cmd = throttle_lowerbound;}brake_cmd = 0.0;} else {throttle_cmd = 0.0;if (calibration_value >= 0) {brake_cmd = brake_lowerbound;} else {brake_cmd = std::max(-calibration_value, brake_lowerbound);}}...
}

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

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

相关文章

Qt信号槽调用出错:Qt: Dead lock detected while activating a BlockingQueuedConnection

目录 1.现象和原因分析 2. 总结 1.现象和原因分析 就在最近的开发过程中&#xff0c;程序一运行在控制台就打印&#xff1a; Qt: Dead lock detected while activating a BlockingQueuedConnection&#xff1a; 咋一看&#xff0c;怎么出现死锁了呢&#xff1f;仔细看下…

Jenkins项目CICD流程

Jenkins项目流程:1.配置git环境 git config --...2.把前后端的目录初始化位本地工作目录 #git init3.提交到本地git #git add ./ git commit -m "" git tag v14.然后提交到远程git(通过,用户,群组,项目,管理项目)git remote add origin http://...git push -…

Springboot_实战

项目开发 lombok使用 自动为实体类提供get、set、toString方法 引入依赖 实体类上添加注解 统一响应结果 注意要写get、set方法&#xff1b;下面是错误的&#xff0c;因此要加上Data注解 一个注册的接口的示例 Controller层 Service层 Mapper层 参数校验 但是同样存在一…

Spring框架中都用到了哪些设计模式?

大家好&#xff0c;我是锋哥。今天分享关于【Spring框架中都用到了哪些设计模式&#xff1f;】面试题。希望对大家有帮助&#xff1b; Spring框架中都用到了哪些设计模式&#xff1f; 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 Spring框架中使用了大量的设计模…

Day1 25/2/14 FRI

【一周刷爆LeetCode&#xff0c;算法大神左神&#xff08;左程云&#xff09;耗时100天打造算法与数据结构基础到高级全家桶教程&#xff0c;直击BTAJ等一线大厂必问算法面试题真题详解&#xff08;马士兵&#xff09;】https://www.bilibili.com/video/BV13g41157hK?p3&v…

软考高级《系统架构设计师》知识点(一)

计算机硬件 校验码 码距&#xff1a;就单个编码A:00而言&#xff0c;其码距为1&#xff0c;因为其只需要改变一位就变成另一个编码。在两个编码中&#xff0c;从A码到B码转换所需要改变的位数称为码距&#xff0c;如A:00要转换为B:11&#xff0c;码距为2。一般来说&#xff0c;…

基于vue3实现的课堂点名程序

设计思路 采用vue3实现的课堂点名程序&#xff0c;模拟课堂座位布局&#xff0c;点击开始点名按钮后&#xff0c;一朵鲜花在座位间传递&#xff0c;直到点击结束点名按钮&#xff0c;鲜花停留的座位被点名。 课堂点名 座位组件 seat.vue <script setup>//组合式APIimpo…

数论补充 之 前后缀分解问题

文章目录 [0,i-1] 和 [i1,n-1] 共同作用3334,数组的最大因子得分238.除自身以外数组的乘积 对于前缀分解问题&#xff0c;我愿把它分为几个大问题&#xff1a;[0,i] 或 [i,n-1] 或 [l,r],或 [0,i-1] 和 [i1,n-1] 共同作用的问题 一般都是求解区间的和&#xff0c;乘积&#xff…

Winform禁止高分辨下缩放布局成功方法

Windows自动缩放布局会导致窗体上的按钮和文本挤在一起根本看不清楚。 那么该如何解决呢&#xff1f; 具体操作步骤如下&#xff1a; 1、在项目属性上切换到【安全性】菜单&#xff0c;勾选【启用ClickOnce安全设置】&#xff0c;然后立刻取消勾选&#xff1b; 为了生成app.…

分享 UniApp 中超好看的卡片阴影样式

在 UniApp 开发中&#xff0c;页面的视觉效果对于提升用户体验至关重要。一个设计精美的卡片样式往往能让页面更加美观和吸引人&#xff0c;而阴影效果则是为卡片增添立体感和层次感的关键元素。今天&#xff0c;我就来和大家分享一个在 UniApp 中实现的卡片阴影样式&#xff0…

教程 | 从零部署到业务融合:DeepSeek R1 私有化部署实战指南

文章目录 1. 什么是 DeepSeek R1&#xff1f;a. 主要介绍a. 版本区别 2. 部署资源要求a. 硬件资源要求 3. 本地安装DeepSeek-R1a. 为什么选择本地部署&#xff1f;b. 部署工具对比c. 演示环境配置d. Ollama安装流程 4. 可视化工具a. 工具对比b. Open-WebUI部署 5. AI API应用a.…

数据结构——队列、哈希存储(2025.2.11)

目录 一、队列 1.定义 2.应用 3.分类 &#xff08;1&#xff09;逻辑结构 &#xff08;2&#xff09;物理结构 顺序队列 链式队列 二、哈希存储 1.定义 2.哈希冲突 &#xff08;1&#xff09;开放定址法 &#xff08;2&#xff09;再哈希法 &#xff08;3&#xf…

【做一个微信小程序】校园地图页面实现

前言 上一个教程我们实现了小程序的一些的功能&#xff0c;有背景渐变色&#xff0c;发布功能有的呢&#xff0c;已支持图片上传功能&#xff0c;表情和投票功能开发中&#xff08;请期待&#xff09;。下面是一个更高级的微信小程序实现&#xff0c;包含以下功能&#xff1a;…

npm安装时无法访问github域名的解决方法

个人博客地址&#xff1a;npm安装时无法访问github域名的解决方法 | 一张假钞的真实世界 今天在用npm install的时候出现了github项目访问不了的异常&#xff1a; npm ERR! Error while executing: npm ERR! /bin/git ls-remote -h -t https://github.com/nhn/raphael.git np…

J Exp Clin Cancer Res (IF:11.4)|上海九院张建军团队发现SPP1+巨噬细胞在头颈癌中的促肿瘤机制

巨噬细胞是肿瘤免疫微环境&#xff08;TIME&#xff09;的重要组成部分&#xff0c;在不同癌症类型中表现出功能的多样性以及与预后的紧密联系。在多种癌症中&#xff0c;SPP1巨噬细胞已被发现是一种常见的肿瘤相关巨噬细胞&#xff08;TAM&#xff09;亚群&#xff0c;且与不良…

盛铂科技 SCP4006/4018/4040:国产袖珍式功率计 射频微波功率探头 平均功率计

在通信、电子测量等领域&#xff0c;功率计是确保信号稳定、系统高效运行的关键设备。盛铂科技自主研发的 SCP4000 系列自带 USB 接口的袖珍式 CW 信号平均功率计&#xff0c;以其卓越的性能、高性价比和便捷的操作&#xff0c;在众多同类产品中脱颖而出&#xff0c;成为行业内…

Docker+Jenkins自动化部署SpringBoot项目【详解git,jdk,maven,ssh配置等各种配置,附有示例+代码】

文章目录 DockerJenkins部署SpringBoot项目一.准备工作1.1安装jdk111.2安装Maven 二.Docker安装Jenkins2.1安装Docker2.2 安装Jenkins2.3进入jenkins 三.Jenkins设置3.1安装jenkins插件3.2全局工具配置全局配置jdk全局配置maven全局配置git 3.3 系统配置安装 Publish Over SSH …

基于角色访问控制的UML 表示

Michael E. Shin、Gail-Joon Ahn 著&#xff0c;UMLChina 译 摘要 在基于角色访问控制&#xff08;role-based access control&#xff0c;RBAC&#xff09;中&#xff0c;权限和角色相关&#xff0c;用户被当作相应角色的成员而获得角色的权限。RBAC 背后的首要动机是为了简…

大数据SQL调优专题——Hive执行原理

引入 Apache Hive 是基于Hadoop的数据仓库工具&#xff0c;它可以使用SQL来读取、写入和管理存在分布式文件系统中的海量数据。在Hive中&#xff0c;HQL默认转换成MapReduce程序运行到Yarn集群中&#xff0c;大大降低了非Java开发者数据分析的门槛&#xff0c;并且Hive提供命令…

计算机网络(1)基础篇

目录 1.TCP/IP 网络模型 2.键入网址--->网页显示 2.1 生成HTTP数据包 2.2 DNS服务器进行域名与IP转换 2.3 建立TCP连接 2.4 生成IP头部和MAC头部 2.5 网卡、交换机、路由器 3 Linux系统收发网络包 1.TCP/IP 网络模型 首先&#xff0c;为什么要有 TCP/IP 网络模型&a…