Apollo星火计划学习笔记——Control 专项讲解(PID)

news2025/1/17 6:07:31

文章目录

  • 1. PID算法介绍
    • 1.1 时间连续与时间离散
    • 1.2 位置式与增量式
    • 1.3 PID算法扩展
  • 2. PID调试方法
  • 3. APOLLO代码介绍
    • 3.1 PID算法
    • 3.2 积分饱和问题
    • 3.3 纵向控制代码
      • 3.3.1 构造函数
      • 3.3.2 加载各种纵向控制的配置参数
      • 3.3.3 二阶巴特沃斯低通滤波器《数字信号处理》
      • 3.3.4 插值出油门开度
      • 3.3.5 根据定位、底盘、规划信息计算输出指令cmd
  • 4. PID算法实践

1. PID算法介绍

PID算法在先前自动驾驶之PID原理简述(简单易懂)中已经有所讲述,在此部分对一些关键性的内容进行介绍,其余部分就不展开介绍了(可以参考胡寿松的《自动控制原理》)。

1.1 时间连续与时间离散

在这里插入图片描述
时间离散的PID公式
u ( k ) = K p e ( k ) + K I ∑ i = 0 e ( i ) + K D [ e ( k ) − e ( k − 1 ) ] u(k) = {K_p}e(k) + {K_I}\sum\limits_{i = 0} {e(i) + {K_D}[e(k) - e(k - 1)]} u(k)=Kpe(k)+KIi=0e(i)+KD[e(k)e(k1)]
时间连续的PID公式
u ( k ) = K p [ e ( t ) + 1 T i ∫ 0 t e ( t ) d t + T d d e ( t ) d t ] u(k) = {K_p}[e(t) + \frac{1}{{{T_i}}}\int_0^t {e(t)dt + Td\frac{{de(t)}}{{dt}}} ] u(k)=Kp[e(t)+Ti10te(t)dt+Tddtde(t)]

1.2 位置式与增量式

位置式:对当前位置与目标状态的偏差进行控制 u ( k ) = K p e ( k ) + K I ∑ i = 0 e ( i ) + K D [ e ( k ) − e ( k − 1 ) ] u(k) = {K_p}e(k) + {K_I}\sum\limits_{i = 0} {e(i) + {K_D}[e(k) - e(k - 1)]} u(k)=Kpe(k)+KIi=0e(i)+KD[e(k)e(k1)]
常见应用: 直立小车涉及角度、速度、转向多个PID控制;通过判断液位高度控制阀门开度
增量式: 以当前的控制量与前一个时刻的控制量作为偏差进行控制。 Δ u ( k ) = u ( k ) − u ( k − 1 ) = K p [ e ( k ) − e ( k − 1 ) ] + K I e ( k ) + K D [ e ( k ) − 2 e ( k − 1 ) + e ( k − 2 ) ] \begin{array}{c}\Delta u(k) = u(k) - u(k - 1)\\ = {K_p}[e(k) - e(k - 1)] + {K_I}e(k) + {K_D}[e(k) - 2e(k - 1) + e(k - 2)]\end{array} Δu(k)=u(k)u(k1)=Kp[e(k)e(k1)]+KIe(k)+KD[e(k)2e(k1)+e(k2)]

增量式PID控制的主要优点为:
①控制增量 Δ u ( k ) Δu(k) Δu(k)的确定仅与最近3次的采样值有关,容易通过加权处理获得比较好的控制效果;
②计算机每次只输出控制增量,即对应执行机构位置的变化量,故机器发生故障时影响范围小、不会严重影响生产过程;
③对于一些工业控制上的机器,手动到自动切换时冲击小。当控制从手动向自动切换时,可以作到无扰动切换。

1.3 PID算法扩展

串级PID控制、模糊pid、自适应pid…
在这里插入图片描述

2. PID调试方法

PID参数快速整定
参数整定找最佳,从小到大顺序查,
先是比例后积分,最后再把微分加,
曲线振荡很频繁,比例度盘要放大,
曲线漂浮绕大湾,比例度盘往小扳,
曲线偏离回复慢,积分时间往下降,
曲线波动周期长,积分时间再加长,
曲线振荡频率快,先把微分降下来,
动差大来波动慢,微分时间应加长,
理想曲线两个波,前高后低四比一,
一看二调多分析,调节质量不会低。

3. APOLLO代码介绍

3.1 PID算法

在这里插入图片描述
Input:当前偏差error及采样时间ts
output:pid求解结果

3.2 积分饱和问题

针对积分饱和问题
在这里插入图片描述在这里插入图片描述

根据当前偏差量进行计算.判断目标输出是否与偏差大小同方向且数值是否超限,若超限,则积分作用无意义。
在这里插入图片描述
当系统处于饱和状态时,对积分项加入负反馈。将 u u u限幅后与原来的 u u u作差。

3.3 纵向控制代码

3.3.1 构造函数

LonController::LonController()
    : name_(ControlConf_ControllerType_Name(ControlConf::LON_CONTROLLER)) {
  if (FLAGS_enable_csv_debug) {
    time_t rawtime;
    char name_buffer[80];
    std::time(&rawtime);
    std::tm time_tm;
    localtime_r(&rawtime, &time_tm);
    strftime(name_buffer, 80, "/tmp/speed_log__%F_%H%M%S.csv", &time_tm);
    speed_log_file_ = fopen(name_buffer, "w");
    if (speed_log_file_ == nullptr) {
      AERROR << "Fail to open file:" << name_buffer;
      FLAGS_enable_csv_debug = false;
    }
    if (speed_log_file_ != nullptr) {
      fprintf(speed_log_file_,
              "station_reference,"
              "station_error,"
              "station_error_limited,"
              "preview_station_error,"
              "speed_reference,"
              "speed_error,"
              "speed_error_limited,,"
              "preview_speed_reference,"
              "preview_speed_error,"
              "preview_acceleration_reference,"
              "acceleration_cmd_closeloop,"
              "acceleration_cmd,"
              "acceleration_lookup,"
              "acceleration_lookup_limit,"
              "speed_lookup,"
              "calibration_value,"
              "throttle_cmd,"
              "brake_cmd,"
              "is_full_stop,"
              "\r\n");

      fflush(speed_log_file_);
    }
    AINFO << name_ << " used.";
  }
}

/tmp/speed_log__%F_%H%M%S.csv中记录了不同的变量,LonController::LonController()将这些变量的标题放入文件中。

3.3.2 加载各种纵向控制的配置参数

Status LonController::Init(std::shared_ptr<DependencyInjector> injector,
                           const ControlConf *control_conf) {
  control_conf_ = control_conf;
  if (control_conf_ == nullptr) {
    controller_initialized_ = false;
    AERROR << "get_longitudinal_param() nullptr";
    return Status(ErrorCode::CONTROL_INIT_ERROR,
                  "Failed to load LonController conf");
  }
  injector_ = injector;
  const LonControllerConf &lon_controller_conf =
      control_conf_->lon_controller_conf();
  double ts = lon_controller_conf.ts();//0.01
  // 反向超前滞后补偿
  bool enable_leadlag =
      lon_controller_conf.enable_reverse_leadlag_compensation();//false
// 位置偏差pid参数 低速pid参数
  station_pid_controller_.Init(lon_controller_conf.station_pid_conf());
  speed_pid_controller_.Init(lon_controller_conf.low_speed_pid_conf());

  if (enable_leadlag) {
    station_leadlag_controller_.Init(
        lon_controller_conf.reverse_station_leadlag_conf(), ts);
    speed_leadlag_controller_.Init(
        lon_controller_conf.reverse_speed_leadlag_conf(), ts);
  }

  vehicle_param_.CopyFrom(
      common::VehicleConfigHelper::Instance()->GetConfig().vehicle_param());
// 数字滤波器
  SetDigitalFilterPitchAngle(lon_controller_conf);
//标定表
  LoadControlCalibrationTable(lon_controller_conf);
  controller_initialized_ = true;

  return Status::OK();
}

首先会加载纵向控制的配置文件 control_conf_ = control_conf;再进行一些安全性的检查。在获取纵向控制的配置信息之后,会将配置文件里的一些数值读取出来,比如控制频率double ts = lon_controller_conf.ts();//0.01,以及进行超前滞后补偿 bool enable_leadlag = lon_controller_conf.enable_reverse_leadlag_compensation();.

对位置pid的初始参数以及低速状态下的pid参数进行初始化
station_pid_controller_.Init(lon_controller_conf.station_pid_conf()); speed_pid_controller_.Init(lon_controller_conf.low_speed_pid_conf());

利用数字滤波器对俯仰角进行补偿
SetDigitalFilterPitchAngle(lon_controller_conf);

利用标定表来进行控制量的输出
LoadControlCalibrationTable(lon_controller_conf);

3.3.3 二阶巴特沃斯低通滤波器《数字信号处理》

void LonController::SetDigitalFilterPitchAngle(
    const LonControllerConf &lon_controller_conf) {
  double cutoff_freq =
      lon_controller_conf.pitch_angle_filter_conf().cutoff_freq();
  double ts = lon_controller_conf.ts();
  SetDigitalFilter(ts, cutoff_freq, &digital_filter_pitch_angle_);
}

3.3.4 插值出油门开度

void LonController::LoadControlCalibrationTable(
    const LonControllerConf &lon_controller_conf) {
  const auto &control_table = lon_controller_conf.calibration_table();
  AINFO << "Control calibration table loaded";
  AINFO << "Control calibration table size is "
        << control_table.calibration_size();
  Interpolation2D::DataType xyz;
  for (const auto &calibration : control_table.calibration()) {
    xyz.push_back(std::make_tuple(calibration.speed(),
                                  calibration.acceleration(),
                                  calibration.command()));
  }
  //后面计算结果会在这里插值出油门开度
  control_interpolation_.reset(new Interpolation2D);
  ACHECK(control_interpolation_->Init(xyz))
      << "Fail to load control calibration table";
}

3.3.5 根据定位、底盘、规划信息计算输出指令cmd

// 根据定位、底盘、规划信息计算输出指令cmd
Status LonController::ComputeControlCommand(
    const localization::LocalizationEstimate *localization,
    const canbus::Chassis *chassis,
    const planning::ADCTrajectory *planning_published_trajectory,
    control::ControlCommand *cmd) {
  localization_ = localization;
  chassis_ = chassis;

  trajectory_message_ = planning_published_trajectory;
  if (!control_interpolation_) {
    AERROR << "Fail to initialize calibration table.";
    return Status(ErrorCode::CONTROL_COMPUTE_ERROR,
                  "Fail to initialize calibration table.");
  }

  if (trajectory_analyzer_ == nullptr ||
      trajectory_analyzer_->seq_num() !=
          trajectory_message_->header().sequence_num()) {
    trajectory_analyzer_.reset(new TrajectoryAnalyzer(trajectory_message_));
  }
  const LonControllerConf &lon_controller_conf =
      control_conf_->lon_controller_conf();

  auto debug = cmd->mutable_debug()->mutable_simple_lon_debug();
  debug->Clear();

  double brake_cmd = 0.0;
  double throttle_cmd = 0.0;
  double ts = lon_controller_conf.ts();
  double preview_time = lon_controller_conf.preview_window() * ts;//考虑预瞄 参数为20
  bool enable_leadlag =
      lon_controller_conf.enable_reverse_leadlag_compensation();

  if (preview_time < 0.0) {
    const auto error_msg =
        absl::StrCat("Preview time set as: ", preview_time, " less than 0");
    AERROR << error_msg;
    return Status(ErrorCode::CONTROL_COMPUTE_ERROR, error_msg);
  }
  //根据当前车(x,y)转化到sl坐标系
  //对比匹配点s s' d d'等多个车辆状态数据
  //将数据保存在debug中,方便日志查询
  ComputeLongitudinalErrors(trajectory_analyzer_.get(), preview_time, ts,
                            debug);

  double station_error_limit = lon_controller_conf.station_error_limit();
  double station_error_limited = 0.0;

//考虑预瞄时纵向位置偏差的上下限不同
  if (FLAGS_enable_speed_station_preview) {
    station_error_limited =
        common::math::Clamp(debug->preview_station_error(),
                            -station_error_limit, station_error_limit);
  } else {
    station_error_limited = common::math::Clamp(
        debug->station_error(), -station_error_limit, station_error_limit);
  }
// 考虑挡位车速情况的参数设置
  if (trajectory_message_->gear() == canbus::Chassis::GEAR_REVERSE) {
    station_pid_controller_.SetPID(
        lon_controller_conf.reverse_station_pid_conf());
    speed_pid_controller_.SetPID(lon_controller_conf.reverse_speed_pid_conf());
    if (enable_leadlag) {
      station_leadlag_controller_.SetLeadlag(
          lon_controller_conf.reverse_station_leadlag_conf());
      speed_leadlag_controller_.SetLeadlag(
          lon_controller_conf.reverse_speed_leadlag_conf());
    }
  } else if (injector_->vehicle_state()->linear_velocity() <=
             lon_controller_conf.switch_speed()) {
    station_pid_controller_.SetPID(lon_controller_conf.station_pid_conf());
    speed_pid_controller_.SetPID(lon_controller_conf.low_speed_pid_conf());
  } else {
    station_pid_controller_.SetPID(lon_controller_conf.station_pid_conf());
    speed_pid_controller_.SetPID(lon_controller_conf.high_speed_pid_conf());
  }
//位置环输出到速度环,速度环为内环
//s=vt 在当前纵向偏差下的速度补偿
  double speed_offset =
      station_pid_controller_.Control(station_error_limited, ts);
  if (enable_leadlag) {
    speed_offset = station_leadlag_controller_.Control(speed_offset, ts);
  }

  debug->set_station_output_kp(station_pid_controller_.Output_Kp());
  debug->set_station_output_ki(station_pid_controller_.Output_Ki());
  debug->set_station_output_kd(station_pid_controller_.Output_Kd()); 

  double speed_controller_input = 0.0;
  double speed_controller_input_limit =
      lon_controller_conf.speed_controller_input_limit();
 // 根据预瞄计算速度环输入
  double speed_controller_input_limited = 0.0;
  if (FLAGS_enable_speed_station_preview) {
    speed_controller_input = speed_offset + debug->preview_speed_error();
  } else {
  // 跟匹配点的速度误差以及位置偏差求出的速度补偿
    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);
//求解速度环输出,给出加速度结果
//v=at
  double acceleration_cmd_closeloop = 0.0;

  acceleration_cmd_closeloop =
      speed_pid_controller_.Control(speed_controller_input_limited, ts);
  debug->set_pid_saturation_status(
      speed_pid_controller_.IntegratorSaturationStatus());
  if (enable_leadlag) {
    acceleration_cmd_closeloop =
        speed_leadlag_controller_.Control(acceleration_cmd_closeloop, ts);
    debug->set_leadlag_saturation_status(
        speed_leadlag_controller_.InnerstateSaturationStatus());
  }
  debug->set_speed_output_kp(speed_pid_controller_.Output_Kp());
  debug->set_speed_output_ki(speed_pid_controller_.Output_Ki());
  debug->set_speed_output_kd(speed_pid_controller_.Output_Kd()); 

  if (chassis->gear_location() == canbus::Chassis::GEAR_NEUTRAL) {
    speed_pid_controller_.Reset_integral();
    station_pid_controller_.Reset_integral();
  }
//数字滤波器的俯仰角补偿
  double slope_offset_compensation = digital_filter_pitch_angle_.Filter(
      GRA_ACC * std::sin(injector_->vehicle_state()->pitch()));

  if (std::isnan(slope_offset_compensation)) {
    slope_offset_compensation = 0;
  }

  debug->set_slope_offset_compensation(slope_offset_compensation);
//控制结果u(k)
  double acceleration_cmd =
      acceleration_cmd_closeloop + debug->preview_acceleration_reference() +
      FLAGS_enable_slope_offset * debug->slope_offset_compensation();
  debug->set_is_full_stop(false);
  //计算当前轨迹剩余距离
  GetPathRemain(debug);

  if ((trajectory_message_->trajectory_type() ==
       apollo::planning::ADCTrajectory::UNKNOWN) &&
      std::abs(cmd->steering_target() - chassis->steering_percentage()) > 20) {
    acceleration_cmd = 0;
    ADEBUG << "Steering not reached";
    debug->set_is_full_stop(true);
    speed_pid_controller_.Reset_integral();
    station_pid_controller_.Reset_integral();
  }

  // At near-stop stage, replace the brake control command with the standstill
  // acceleration if the former is even softer than the latter
  if (((trajectory_message_->trajectory_type() ==
        apollo::planning::ADCTrajectory::NORMAL) ||
       (trajectory_message_->trajectory_type() ==
        apollo::planning::ADCTrajectory::SPEED_FALLBACK)) &&
      ((std::fabs(debug->preview_acceleration_reference()) <=
            control_conf_->max_acceleration_when_stopped() &&
        std::fabs(debug->preview_speed_reference()) <=
            vehicle_param_.max_abs_speed_when_stopped()) ||
       std::abs(debug->path_remain()) <
           control_conf_->max_path_remain_when_stopped())) {
    acceleration_cmd =
        (chassis->gear_location() == canbus::Chassis::GEAR_REVERSE)
            ? std::max(acceleration_cmd,
                       -lon_controller_conf.standstill_acceleration())
            : std::min(acceleration_cmd,
                       lon_controller_conf.standstill_acceleration());
    ADEBUG << "Stop location reached";
    debug->set_is_full_stop(true);
    speed_pid_controller_.Reset_integral();
    station_pid_controller_.Reset_integral();
  }

  double throttle_lowerbound =
      std::max(vehicle_param_.throttle_deadzone(),
               lon_controller_conf.throttle_minimum_action());
  double brake_lowerbound =
      std::max(vehicle_param_.brake_deadzone(),
               lon_controller_conf.brake_minimum_action());
  double calibration_value = 0.0;
  // u(k)分前进倒车两种情况
  double acceleration_lookup =
      (chassis->gear_location() == canbus::Chassis::GEAR_REVERSE)
          ? -acceleration_cmd
          : acceleration_cmd;

  double acceleration_lookup_limited =
      vehicle_param_.max_acceleration() +
      FLAGS_enable_slope_offset * debug->slope_offset_compensation();
  double acceleration_lookup_limit = 0.0;
// 根据计算出的加速度与车速查找标定表,插值出当前油门开度
  if (FLAGS_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 (FLAGS_use_acceleration_lookup_limit) {
      calibration_value = control_interpolation_->Interpolate(std::make_pair(
          debug->preview_speed_reference(), acceleration_lookup_limit));
    } else {
      calibration_value = control_interpolation_->Interpolate(std::make_pair(
          debug->preview_speed_reference(), acceleration_lookup));
    }
  } else {
    if (FLAGS_use_acceleration_lookup_limit) {
      calibration_value = control_interpolation_->Interpolate(
          std::make_pair(chassis_->speed_mps(), acceleration_lookup_limit));
    } else {
      calibration_value = control_interpolation_->Interpolate(
          std::make_pair(chassis_->speed_mps(), 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);
    }
  }

  debug->set_station_error_limited(station_error_limited);
  debug->set_speed_offset(speed_offset);
  debug->set_speed_controller_input_limited(speed_controller_input_limited);
  debug->set_acceleration_cmd(acceleration_cmd);
  debug->set_throttle_cmd(throttle_cmd);
  debug->set_brake_cmd(brake_cmd);
  debug->set_acceleration_lookup(acceleration_lookup);
  debug->set_acceleration_lookup_limit(acceleration_lookup_limit);
  debug->set_speed_lookup(chassis_->speed_mps());
  debug->set_calibration_value(calibration_value);
  debug->set_acceleration_cmd_closeloop(acceleration_cmd_closeloop);

  if (FLAGS_enable_csv_debug && speed_log_file_ != nullptr) {
    fprintf(speed_log_file_,
            "%.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f,"
            "%.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %d,\r\n",
            debug->station_reference(), debug->station_error(),
            station_error_limited, debug->preview_station_error(),
            debug->speed_reference(), debug->speed_error(),
            speed_controller_input_limited, debug->preview_speed_reference(),
            debug->preview_speed_error(),
            debug->preview_acceleration_reference(), acceleration_cmd_closeloop,
            acceleration_cmd, debug->acceleration_lookup(),
            debug->acceleration_lookup_limit(), debug->speed_lookup(),
            calibration_value, throttle_cmd, brake_cmd, debug->is_full_stop());
  }

  // if the car is driven by acceleration, disgard the cmd->throttle and brake
  cmd->set_throttle(throttle_cmd);
  cmd->set_brake(brake_cmd);
  if (FLAGS_use_acceleration_lookup_limit) {
    cmd->set_acceleration(acceleration_lookup_limit);
  } else {
    cmd->set_acceleration(acceleration_cmd);
  }

  if (std::fabs(injector_->vehicle_state()->linear_velocity()) <=
          vehicle_param_.max_abs_speed_when_stopped() ||
      chassis->gear_location() == trajectory_message_->gear() ||
      chassis->gear_location() == canbus::Chassis::GEAR_NEUTRAL) {
    cmd->set_gear_location(trajectory_message_->gear());
  } else {
    cmd->set_gear_location(chassis->gear_location());
  }

  return Status::OK();
}

if (!control_interpolation_) {
首先检测初始化后的标定表是否是有效的。
if (trajectory_analyzer_ == nullptr ||
再判断planning模块传过来的指针是否是空的( trajectory_analyzer_是一种轨迹分析的工具,计算当前车辆的状态偏差,例如横纵向偏差)。

auto debug = cmd->mutable_debug()->mutable_simple_lon_debug(); debug->Clear();
debug中存储了一些控制量的信息
double brake_cmd = 0.0;
初始化刹车
double throttle_cmd = 0.0;
初始化油门
double ts = lon_controller_conf.ts();
获取配置文件中模块执行频率
double preview_time = lon_controller_conf.preview_window() * ts;//考虑预瞄 参数为20
考虑预瞄的问题

ComputeLongitudinalErrors(trajectory_analyzer_.get(), preview_time, ts, debug);
根据当前车(x,y)转化到sl坐标系;
对比匹配点s s’ d d’等多个车辆状态数据;
将数据保存在debug中,方便日志查询.

if (FLAGS_enable_speed_station_preview) {
考虑预瞄时纵向位置偏差的上下限不同

if (trajectory_message_->gear() == canbus::Chassis::GEAR_REVERSE) {
考虑挡位车速情况的参数设置,根据不同车辆行驶状况设置不同的pid参数。

4. PID算法实践

Apollo控制之控制仿真实践
在终端中输入以下指令,启动dreamview

aem bootstrap start

在这里插入图片描述
运行成功后,点击左上角dreamview按钮。当网页中出现apollo后, 即表示dreamview启动成功了, 为了便于调试,在该页面上,我们选择车辆(vehicle) 为MKZ,关闭mute,选择地图Apollo Virutal Map。
在这里插入图片描述
点击Sim Control
在这里插入图片描述
点击Profile, 下载动力学模型,Mkz Model (lincolnmkz动力学模型),Point Mass Model (惯性模型) 。然后选择Dynamic Model,选择Mkz Model.

在这里插入图片描述
启动Planning, Routing, Control,
在这里插入图片描述
在Route Editing页面,选择起点,终点,选择SendRouting Request。发送前点开recorder

在这里插入图片描述
查看车辆前方能够正常生成规划线,此时切换到Tasks页面,点击StartAuto。
在这里插入图片描述
点击Dreamview左侧菜单栏Tasks按钮,关闭LockTask Panel,打开PNC monitor功能按钮,点击右侧Control按钮,可以查看控制相关的数据。
在这里插入图片描述
通过下拉右边栏,可查看控制相关参数的变化,比如右侧第二个图表speed,蓝色曲线表示车辆的实际车速,青绿色的表示规划的参考车速,可看到实际车速与规划速度的跟随情况,从而可以进行控制效果。

查看纵向控制参数配置点击在线编辑,打开控制参数配置文件/apollo workspace/modules/control/conf/control co nf.pb.txt,可查看apollo默认的控制参数。

从配置文件内,可查看纵向PID控制参数如下,纵向PID主要包含2层串联pid控制器,位置PID和速度PID, PID调节参数:位置PID参数kp, ki, kd, 速度PID参数kp, ki, kd。 在速度PID参数中,根据不同当前车速做了PID参数选择,switch speed表示速度限,速度小于该值时,速度PID执行low_ speed pid conf,反之,执行high speed pid conf。

(1)将所有pid参数置零

lon_controller_conf {
 station_pid_conf {
  integrator_enable: false
  integrator_saturation_level: 0.3
  kp: 0.0
  ki: 0.0
  kd: 0.0
 }
 low_speed_pid_conf {
  integrator_enable: true
  integrator_saturation_level: 0.3
  kp: 0.0
  ki: 0.0
  kd: 0.0
 }
  high_speed_pid_conf {
   integrator_enable: true
   integrator_saturation_level: 0.3
   kp: 0.0
   ki: 0.0
   kd: 0.0
 }
  switch_speed: 3.0

然后重复5.3步骤并点击recorder按钮,进行录制数据包。可以通过PNC monitor对控制效果进行简单分析。
(2)然后将low speed pid conf中kp设置为3.0,high_ speed pid. conf设置为3.0,达到猛加急减的效果

lon_controller_conf {
 station_pid_conf {
  integrator_enable: false
  integrator_saturation_level: 0.3
  kp: 0.0
  ki: 0.0
  kd: 0.0
 }
 low_speed_pid_conf {
  integrator_enable: true
  integrator_saturation_level: 0.3
  kp: 3.0
  ki: 0.0
  kd: 0.0
 }
  high_speed_pid_conf {
   integrator_enable: true
   integrator_saturation_level: 0.3
   kp: 3    .0
   ki: 0.0
   kd: 0.0
 }
  switch_speed: 3.0

打开notebook脚本进行数据分析

% matplotlib notebook
run control_info.py --path /apollo/data/bag/******

在这里插入图片描述

左上图,蓝色曲线为车辆实时速度曲线,绿色线为规划出的参考速度

在这里插入图片描述
在这里插入图片描述

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

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

相关文章

PMP考试是什么?适合哪些人来学呢?

PMP&#xff0c;根据PMI的解释&#xff0c;就是项目管理专业人士资格认证&#xff0c;全称如下图&#xff1a;PMP考试是由PMI发起、组织和出题&#xff0c;严格评估项目管理专业人士知识技能是否具有高品质的资格认证考试。PMI&#xff1a;美国项目管理协会&#xff08;Project…

【小米路由器3】breed刷机救砖-nand flash硬改SPI flash-编程器救砖(解决ttl无法救砖问题)

大家好&#xff0c;我是老子姓李&#xff01;&#xff08;gzh&#xff1a;楠瘦&#xff09; 本博文带来【小米路由器3】变砖&#xff0c;ttl无法救砖&#xff0c;硬改焊接一块SPI flash&#xff0c;使用编程器刷入小米路由器mini的breed最终成功救砖。 目录1.引言1.1 背景1.2回…

07MEMS传感器技术 讲座

把同步现象应用于传感器设计。 什么是MEMS&#xff1f; 1.mems芯片是什么意思 MEMS是Micro-Electro-Mechanical System的缩写&#xff0c;中文名称是微机电系统。MEMS芯片简而言之&#xff0c;就是用半导体技术在硅片上制造电子机械系统&#xff0c;再形象一点说就是做一个微…

Vue3——第十一章(内置组件:KeepAlive、Transition、TransitionGroup)

一、KeepAlive <KeepAlive> 是一个内置组件&#xff0c;它的功能是在多个组件间动态切换时缓存被移除的组件实例。 1、基本使用 默认情况下&#xff0c;一个组件实例在被替换掉后会被销毁。这会导致它丢失其中所有已变化的状态——当这个组件再一次被显示时&#xff0…

elementui el-table表格实现翻页和搜索均保持勾选状态(后端分页)

需求&#xff1a;不管是页面切换还是通过搜索获取数据&#xff0c;都要保持已选中的行保持勾选状态&#xff0c;同时将选中行的内容以标签的形式显示出来&#xff0c;当点击关闭标签时可以对应取消选中状态&#xff0c;点击行中的任意位置也可以切换选中状态&#xff0c;单独勾…

柳叶刀重磅:30年来首个基于新机制的降压药,可持续降压近一年

全球范围内高血压患者约有13亿&#xff0c;其中10%的患者&#xff08;超过1亿&#xff09;为难治性高血压&#xff0c;即接受了3种以上不同种类的降压药治疗后&#xff0c;血压仍然控制不佳。长期不受控的高血压可能对心脏和血管均会造成损伤&#xff0c;进而增加患者发生心脏病…

Learning Saliency Propagation for Semi-Supervised Instance Segmentation

Abstract 实例分割对于建模和注释来说都是一项具有挑战性的任务。由于注释成本高&#xff0c;建模变得更加困难&#xff0c;因为监督的数量有限。我们的目标是利用大量的检测监督来提高现有实例分割模型的准确性。我们提出了ShapeProp&#xff0c;它学习激活对象检测中的显著区…

【CocosCreator入门】CocosCreator下载安装 | 使用Cocos DashBoard下载各个版本的CocosCreator

Cocos Creator 从 v2.3.2 开始接入了全新的 Dashboard 系统&#xff0c;能够同时对多版本引擎和项目进行统一升级和管理&#xff01;Cocos Dashboard 将做为 Creator 各引擎统一的下载器和启动入口&#xff0c;方便大家升级和管理多个版本的 Creator。此外还集成了统一的项目管…

进程间通信的方式(附代码分析)

进程间通信的方式 1. 进程间通信的几种方式 管道 比如 ls | grep 1;也就是将 进程 ls 拿到的结果作为 grep 1 这个进程的输入。实现了进程间的通信。 消息队列 消息队列就是我们的内核给我们创建的一种消息队列。我们可以往其中发送消息&#xff0c;也可以从其中接收消息。 …

C语言实现有序序列判断

一个数组&#xff0c;判断是否有序看上去很简单&#xff0c;有很多种方法。但实际上有一个很严重的问题&#xff0c;就是重复数会影响判断结果。 我这里提供的思路是取连续的三个数进行比较&#xff0c;a, b, c&#xff0c;假设一共n个元素&#xff0c;数组名是arr&#xff0c…

阿里云Imagine Computing创新技术大赛决赛启幕!

2023年1月&#xff0c;由阿里云与英特尔主办&#xff0c;阿里云天池平台、边缘云、视频云共同承办的“新算力 新体验”Imagine Computing创新技术大赛复赛圆满落幕。经过两个多月的激烈角逐&#xff0c;12支入围队伍&#xff0c;从海内外8个国家和地区的6900余支参赛队伍中脱颖…

转到结构化写作后的几点变化

或许是随着公司产品越来越多&#xff0c;公司的手册越来越复杂&#xff0c;用户越来越难找到需要的信息&#xff1b;或许是因为公司管理手册的使用者不满足于长篇大论的文字&#xff0c;希望能够获得只跟他相关的政策、程序等信息。 总之&#xff0c;公司决定从MS Word、非结构…

Pipeline机器学习模型串联

机器学习模型训练时使用 Pipeline 是一个加快效率的串联方法。Pipeline 处理机制就像是把所有模型塞到一个管子里&#xff0c;然后依次对数据进行处理&#xff0c;得到最终的分类结果。 # 模型串联 pipPipeline( [ # 所有模型写…

Matlab Spreadsheet Link安装(早期叫excllink)

我们在Matlab和Excel之间进行数据交互&#xff0c;需要用到Excel link这个组件&#xff08;这是早期的叫法&#xff09;&#xff0c;现在这个组件的名称叫做Spreadsheet Link&#xff0c;这个在我们安装Matlab的时候&#xff0c;要选择相应的组件来安装&#xff08;有可能我们刚…

find命令的常见用法

1.find 命令的常见用法 1.1 基础的打印操作 find命令默认接的命令是-print&#xff0c;它默认以\n将找到的文件分隔。可以使用-print0来使用\0分隔&#xff0c;这样就不会分行了。但是一定要注意&#xff0c;-print0针对的是\n转\0&#xff0c;如果查找的文件名本身就含有空格…

高一物理题整理

1 船过河问题 【分析及解答】 这个题的关键是如何理解船的速度&#xff0c;题目假设船的速度是不变的&#xff0c;也就是一直是v2v_2v2​。 列方程如下&#xff1a; {120v1∗10dv2∗10dv2sin⁡θ∗12.5v1v2cos⁡θ\left\{\begin{array}{l} 120 v_1 * 10 \\ d v_2 * 10 \\ d …

【我的渲染技术进阶之旅】解决Cinema 4D制作的3D模型无法导入Blender的问题

文章目录一、问题描述二、分析问题2.1 查看material材质的mtl文件2.2 mtl文件介绍2.3 对比mtl文件和mtl语法并修改2.3.1 norm不对2.3.2 map_Ka、map_Kd 、map_Ks、map_Bump 的格式不对2.5 重新导出obj格式和mtl文件三、总结一、问题描述 今天UI输出了个3D模型给我&#xff0c;…

Spring是如何解决循环依赖的?

一、什么是循环依赖&#xff1f; 循环依赖&#xff1a;说白了就是一个或多个对象实例之间存在直接或间接的依赖关系&#xff0c;这种依赖关系构成了一个环形调用。 第一种情况&#xff1a;自己依赖自己的直接依赖 第二种情况&#xff1a;两个对象之间的直接依赖 第三种情况…

Android 深入系统完全讲解(11)

9 framework 内容组成 狭义的 framework&#xff0c;主要讲的就是 SystemServer 里面的所有服务&#xff0c;这些是在 framework&#xff0c; 而广义的就是包含了 rec&#xff0c;native 服务&#xff0c;系统 app 等一切分不出去的模块&#xff0c;所以 framework 要能做好&a…

睿尔曼 RM65-B 机械臂 WIN 示教软件测试

大家好&#xff0c;我是虎哥&#xff0c;最近开始接触机械臂&#xff0c;尤其是协作机械臂&#xff0c;小&#xff0c;轻、还价格便宜一点&#xff0c;由于我师兄弟强烈推荐的睿尔曼 RM65-B机械臂&#xff0c;所以总结一下自己的开箱测试经验&#xff0c;主要是在WIN下 示教器软…