Navigation源码阅读之robot_pose_ekf

本文深入解析了navigation源码中利用扩展卡尔曼滤波器(EKF)进行小车定位的方法,详细介绍了OdomEstimationNode类的构造函数、参数设置、传感器数据处理流程及EKF更新机制。通过对源码的逐行解读,揭示了如何将里程计、IMU等传感器数据融合,实现精确的小车位置估计。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

卡尔曼滤波器是传感器融合的利器,而navigation源码中的对于小车感知这一块的处理也是依靠EKF来实现,我们来阅读一下这个包的实现方法,以及网上的贝叶斯滤波的官方API,在实际使用时,可以更快地定位错误与改写。

一、首先看看cmakelists,这个包只生成一个节点,主函数在odom_estimation_node.cpp中,定位到OdomEstimationNode类的构造函数,这里有一溜的param,我们在做小车时一般用里程计、IMU、视觉里程计进行定位,这三个默认是true,另外滤波器的刷新频率设为30Hz,也绰绰有余了,一般传感器的信息频率在100~1000Hz左右。

my_filter_.setOutputFrame(output_frame_);
my_filter_.setBaseFootprintFrame(base_footprint_frame_);

timer_ = nh_private.createTimer(ros::Duration(1.0/max(freq,1.0)),&OdomEstimationNode::spin, this);

我们一般将这两个frame设为odom与base_link,这样就可以通过EKF代替base_controller发送odom的tf变换。另外,用手写一个函数OdomEstimationNode::spin而不是一般见到的ros自带的spin函数,用来检查各个传感器的使用状态,以及发布我们需要的topic和tf,这个函数将以30Hz的频率运行。

二、OdomEstimationNode::odomCallback,这一系列的传感器回调函数,不同的传感器的数据维度与协方差矩阵尺寸不同,就拿里程计来说,协方差矩阵为6*6。

Quaternion q;
tf::quaternionMsgToTF(odom->pose.pose.orientation, q);
odom_meas_  = Transform(q, Vector3(odom->pose.pose.position.x, odom->pose.pose.position.y, 0));
for (unsigned int i=0; i<6; i++)
 for (unsigned int j=0; j<6; j++)
   odom_covariance_(i+1, j+1) = odom->pose.covariance[6*i+j];

my_filter_.addMeasurement(StampedTransform(odom_meas_.inverse(), odom_stamp_, base_footprint_frame_, "wheelodom"), odom_covariance_);

在这个代码块它调用了OdomEstimation::addMeasurement函数,它位于odom_estimation.cpp中: 

1.OdomEstimation::addMeasurement这个函数其实就是把组装好的transform发出去,它将在之后被OdomEstimation::update捕获并进行下一次的状态估计。

三、OdomEstimationNode::spin函数,这是整个包的输出信息的函数,一开始需要对时间戳进行检查:

if ( (odom_initializing_ || odom_active_) && (imu_initializing_ || imu_active_) )
{
  double diff = fabs( Duration(odom_stamp_ - imu_stamp_).toSec() );
  if (diff > 1.0) ROS_ERROR("Timestamps of odometry and imu are %f seconds apart.", diff);
}

这个错误的出现概率不算太大,除非把传感器频率设得太低,或者直接断开连接了。接着直接对小车的状态进行估计并发送tf变换:

if ( my_filter_.isInitialized() )
{
  bool diagnostics = true;
  if (my_filter_.update(odom_active_, imu_active_,gps_active_, vo_active_,  filter_stamp_, diagnostics))
  {
    my_filter_.getEstimate(output_);
    pose_pub_.publish(output_);
    ekf_sent_counter_++;

    StampedTransform tmp;
    my_filter_.getEstimate(ros::Time(), tmp);
    if(!vo_active_ && !gps_active_)
      tmp.getOrigin().setZ(0.0);
    odom_broadcaster_.sendTransform(StampedTransform(tmp, tmp.stamp_,output_frame_, base_footprint_frame_));

...

 上面的代码段调用了OdomEstimation类的多个函数,我们依次进行分析:

1.先看看OdomEstimation的构造函数,下面的代码段是系统的概率模型。各变量的意义是:pdf是条件概率密度函数,即probability density function,model是概率密度模型,sysNoise_Mu是系统的噪声均值,sysNoise_Cov是协方差矩阵。在这里将协方差矩阵的对角线都赋成10^-6。

ColumnVector sysNoise_Mu(6);  sysNoise_Mu = 0;
SymmetricMatrix sysNoise_Cov(6); sysNoise_Cov = 0;
for (unsigned int i=1; i<=6; i++) sysNoise_Cov(i,i) = pow(1000.0,2);
Gaussian system_Uncertainty(sysNoise_Mu, sysNoise_Cov);
sys_pdf_   = new NonLinearAnalyticConditionalGaussianOdo(system_Uncertainty);
sys_model_ = new AnalyticSystemModelGaussianUncertainty(sys_pdf_);

相比系统模型,传感器模型直接使用线性模型进行估计, 首先创建一个高斯分布的观测噪声,再加入到里程计的概率密度函数中,在这里的噪声协方差比系统初始值要大很多。另外,Hodom指的是里程计自身的噪声。接下来在各个传感器模型中流程均相同。

ColumnVector measNoiseOdom_Mu(6);  measNoiseOdom_Mu = 0;
SymmetricMatrix measNoiseOdom_Cov(6);  measNoiseOdom_Cov = 0;
for (unsigned int i=1; i<=6; i++) measNoiseOdom_Cov(i,i) = 1;
Gaussian measurement_Uncertainty_Odom(measNoiseOdom_Mu, measNoiseOdom_Cov);
Matrix Hodom(6,6);  Hodom = 0;
Hodom(1,1) = 1;    Hodom(2,2) = 1;    Hodom(6,6) = 1;
odom_meas_pdf_   = new LinearAnalyticConditionalGaussian(Hodom, measurement_Uncertainty_Odom);
odom_meas_model_ = new LinearAnalyticMeasurementModelGaussianUncertainty(odom_meas_pdf_);

2.OdomEstimation::initialize函数建立了先验概率模型。prior_Mu是先验概率的均值,prior_Cov是协方差矩阵,那么一开始的先验概率均值由odom_meas_提供。

ColumnVector prior_Mu(6);
decomposeTransform(prior, prior_Mu(1), prior_Mu(2), prior_Mu(3), prior_Mu(4), prior_Mu(5), prior_Mu(6));

 用这个先验概率新初始化一个EKF模型,将先验概率记下来,在update函数中会用于下一次的更新。

prior_  = new Gaussian(prior_Mu,prior_Cov);
filter_ = new ExtendedKalmanFilter(prior_);

addMeasurement(StampedTransform(prior, time, output_frame_, base_footprint_frame_));
filter_estimate_old_vec_ = prior_Mu;
filter_estimate_old_ = prior;
filter_time_old_     = time;

 3.OdomEstimation::update函数用于滤波器的实际更新。首先加上系统噪声,再依次将传感器的数据传入滤波器中予以状态估计。下面这一段指的是将里程计的数据转化为在水平面上的相对数据,加入传感器噪声之后更新协方差矩阵,最终给里程计模型更新这次的测量值。

if (odom_initialized_)
{
  Transform odom_rel_frame =  Transform(tf::createQuaternionFromYaw(filter_estimate_old_vec_(6)),filter_estimate_old_.getOrigin()) * odom_meas_old_.inverse() * odom_meas_;
  ColumnVector odom_rel(6);
  decomposeTransform(odom_rel_frame, odom_rel(1), odom_rel(2), odom_rel(3), odom_rel(4), odom_rel(5), odom_rel(6));
  angleOverflowCorrect(odom_rel(6), filter_estimate_old_vec_(6));
      	
  odom_meas_pdf_->AdditiveNoiseSigmaSet(odom_covariance_ * pow(dt,2));

  ROS_DEBUG("Update filter with odom measurement %f %f %f %f %f %f",
  odom_rel(1), odom_rel(2), odom_rel(3), odom_rel(4), odom_rel(5), odom_rel(6));
  filter_->Update(odom_meas_model_, odom_rel);
  diagnostics_odom_rot_rel_ = odom_rel(6);
}

在这里有一句 filter_->Update(odom_meas_model_, odom_rel);查看头文件就可以知道这是EKF提供的接口,我们跳到贝叶斯滤波库的BFL::ExtendedKalmanFilter中看看程序是怎么写的。网页版链接http://docs.ros.org/jade/api/bfl/html/annotated.html

 (1)在这里对sysmodel进行了强制转换,转到AnalyticSystemModelGaussianUncertainty这个类就可以知道,我们用AnalyticSystemModelGaussianUncertainty的成员函数把扩展卡尔曼滤波模型在当前状态下进行线性化:

\[ F = \frac{df}{dx} \mid_{u,x} \]

 那么接下来就是KF模型的估计了。

void ExtendedKalmanFilter::SysUpdate(SystemModel<ColumnVector>* const sysmodel,const ColumnVector& u)
{
   _x = _post->ExpectedValueGet();
   _J = ((AnalyticSys*)sysmodel)->PredictionGet(u,_x);
   _F = ((AnalyticSys*)sysmodel)->df_dxGet(u,_x);
   _Q = ((AnalyticSys*)sysmodel)->CovarianceGet(u,_x);
 
   CalculateSysUpdate(_J, _F, _Q);
}

(2)这一段实际上就是用状态转移矩阵F,后验估计的协方差矩阵,系统噪声的协方差矩阵Q计算得到预测值和真实值之间误差的协方差矩阵。

void KalmanFilter::CalculateSysUpdate(const ColumnVector& J, const Matrix& F, const SymmetricMatrix& Q)
{
  _Sigma_temp = F * ( (Matrix)_post->CovarianceGet() * F.transpose());
  _Sigma_temp += (Matrix)Q;
  _Sigma_temp.convertToSymmetricMatrix(_Sigma_new);

  PostMuSet   ( J );
  PostSigmaSet( _Sigma_new );
}

4.再回到OdomEstimation::update,当各传感器的数据均在滤波器内更新后,开始获取本轮的状态估计。

filter_estimate_old_vec_ = filter_->PostGet()->ExpectedValueGet();
tf::Quaternion q;
q.setRPY(filter_estimate_old_vec_(4), filter_estimate_old_vec_(5),filter_estimate_old_vec_(6));
filter_estimate_old_ = Transform(q,Vector3(filter_estimate_old_vec_(1), filter_estimate_old_vec_(2), filter_estimate_old_vec_(3)));
filter_time_old_ = filter_time;
addMeasurement(StampedTransform(filter_estimate_old_, filter_time,output_frame_, base_footprint_frame_));

重新覆盖filter_estimate_old_vec_作为下一次的先验,并且把估计的系统状态用transform的形式传给getEstimate,那么OdomEstimationNode::spin函数便可接收到并发出本次估计的tf变换。

用robot_pose_ekf包进行融合之后,tf树应该是由robot_pose_ekf发出的odom指向base_link。

 

EPRobot@EPRobot:~/robot_ws$ cd ~/robot_ws # 在每次打开新终端时运行 EPRobot@EPRobot:~/robot_ws$ catkin_make Base path: /home/EPRobot/robot_ws Source space: /home/EPRobot/robot_ws/src Build space: /home/EPRobot/robot_ws/build Devel space: /home/EPRobot/robot_ws/devel Install space: /home/EPRobot/robot_ws/install #### #### Running command: "make cmake_check_build_system" in "/home/EPRobot/robot_ws/build" #### -- Using CATKIN_DEVEL_PREFIX: /home/EPRobot/robot_ws/devel -- Using CMAKE_PREFIX_PATH: /home/EPRobot/robot_ws/devel;/opt/ros/melodic -- This workspace overlays: /home/EPRobot/robot_ws/devel;/opt/ros/melodic -- Found PythonInterp: /usr/bin/python2 (found suitable version "2.7.17", minimum required is "2") -- Using PYTHON_EXECUTABLE: /usr/bin/python2 -- Using Debian Python package layout -- Using empy: /usr/bin/empy -- Using CATKIN_ENABLE_TESTING: ON -- Call enable_testing() -- Using CATKIN_TEST_RESULTS_DIR: /home/EPRobot/robot_ws/build/test_results -- Found gtest sources under '/usr/src/googletest': gtests will be built -- Found gmock sources under '/usr/src/googletest': gmock will be built -- Found PythonInterp: /usr/bin/python2 (found version "2.7.17") -- Using Python nosetests: /usr/bin/nosetests-2.7 -- catkin 0.7.29 -- BUILD_SHARED_LIBS is on -- BUILD_SHARED_LIBS is on -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- ~~ traversing 62 packages in topological order: -- ~~ - astra_launch -- ~~ - base_control -- ~~ - hibot_follower -- ~~ - lslidar (metapackage) -- ~~ - navigation (metapackage) -- ~~ - robot_navigation -- ~~ - robot_upstart -- ~~ - simple_navigation_goals -- ~~ - lslidar_msgs -- ~~ - rospy_message_converter -- ~~ - eprobot_auto_home -- ~~ - eprobot_start -- ~~ - ls01d -- ~~ - map_server -- ~~ - hls_lfcd_lds_driver -- ~~ - iiiroboticslidar2 -- ~~ - astra_camera -- ~~ - rplidar_ros -- ~~ - eprobot_joy -- ~~ - lslidar_driver -- ~~ - robot_pose_ekf -- ~~ - sc_mini -- ~~ - amcl -- ~~ - fake_localization -- ~~ - laser_filters -- ~~ - robot_localization -- ~~ - track_detection -- ~~ - voxel_grid -- ~~ - costmap_2d -- ~~ - nav_core -- ~~ - base_local_planner -- ~~ - carrot_planner -- ~~ - clear_costmap_recovery -- ~~ - dwa_local_planner -- ~~ - move_slow_and_clear -- ~~ - navfn -- ~~ - global_planner -- ~~ - rotate_recovery -- ~~ - move_base -- ~~ - teb_local_planner -- ~~ - eprobot_description -- ~~ - xf_mic_asr_offline -- ~~ - ydlidar -- ~~ - yocs_ar_pair_approach -- ~~ - yocs_cmd_vel_mux -- ~~ - yocs_controllers -- ~~ - yocs_keyop -- ~~ - yocs_localization_manager -- ~~ - yocs_math_toolkit -- ~~ - yocs_ar_marker_tracking -- ~~ - yocs_diff_drive_pose_controller -- ~~ - yocs_ar_pair_tracking -- ~~ - yocs_joyop -- ~~ - yocs_navi_toolkit -- ~~ - yocs_navigator -- ~~ - yocs_rapps -- ~~ - yocs_safety_controller -- ~~ - yocs_velocity_smoother -- ~~ - yocs_virtual_sensor -- ~~ - yocs_waypoint_provider -- ~~ - yocs_waypoints_navi -- ~~ - yujin_ocs (metapackage) -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- +++ processing catkin package: 'astra_launch' -- ==> add_subdirectory(ros_astra_launch) -- +++ processing catkin package: 'base_control' -- ==> add_subdirectory(base_control) -- +++ processing catkin package: 'hibot_follower' -- ==> add_subdirectory(hibot_follower) -- Using these message generators: gencpp;geneus;genlisp;gennodejs;genpy CMake Warning at /opt/ros/melodic/share/catkin/cmake/catkin_package.cmake:166 (message): catkin_package() DEPENDS on 'system_lib' but neither 'system_lib_INCLUDE_DIRS' nor 'system_lib_LIBRARIES' is defined. Call Stack (most recent call first): /opt/ros/melodic/share/catkin/cmake/catkin_package.cmake:102 (_catkin_package) hibot_follower/CMakeLists.txt:24 (catkin_package) -- +++ processing catkin metapackage: 'lslidar' -- ==> add_subdirectory(lslidar) -- +++ processing catkin metapackage: 'navigation' -- ==> add_subdirectory(navigation-melodic/navigation) -- +++ processing catkin package: 'robot_navigation' -- ==> add_subdirectory(robot_navigation) -- +++ processing catkin package: 'robot_upstart' -- ==> add_subdirectory(robot_upstart) -- +++ processing catkin package: 'simple_navigation_goals' -- ==> add_subdirectory(simple_navigation_goals) -- Using these message generators: gencpp;geneus;genlisp;gennodejs;genpy -- +++ processing catkin package: 'lslidar_msgs' -- ==> add_subdirectory(lslidar_msgs) -- Using these message generators: gencpp;geneus;genlisp;gennodejs;genpy -- lslidar_msgs: 5 messages, 0 services -- +++ processing catkin package: 'rospy_message_converter' -- ==> add_subdirectory(rospy_message_converter) -- Using these message generators: gencpp;geneus;genlisp;gennodejs;genpy -- rospy_message_converter: 4 messages, 1 services -- +++ processing catkin package: 'eprobot_auto_home' -- ==> add_subdirectory(eprobot_auto_home) -- +++ processing catkin package: 'eprobot_start' -- ==> add_subdirectory(eprobot_start) -- Using these message generators: gencpp;geneus;genlisp;gennodejs;genpy CMake Warning at /opt/ros/melodic/share/catkin/cmake/catkin_package.cmake:166 (message): catkin_package() DEPENDS on 'system_lib' but neither 'system_lib_INCLUDE_DIRS' nor 'system_lib_LIBRARIES' is defined. Call Stack (most recent call first): /opt/ros/melodic/share/catkin/cmake/catkin_package.cmake:102 (_catkin_package) eprobot_start/CMakeLists.txt:24 (catkin_package) -- +++ processing catkin package: 'ls01d' -- ==> add_subdirectory(lidar/ls01d) -- +++ processing catkin package: 'map_server' -- ==> add_subdirectory(navigation-melodic/map_server) -- Using these message generators: gencpp;geneus;genlisp;gennodejs;genpy -- Boost version: 1.65.1 -- Found the following Boost libraries: -- filesystem -- system -- +++ processing catkin package: 'hls_lfcd_lds_driver' -- ==> add_subdirectory(lidar/hls_lfcd_lds_driver) -- Boost version: 1.65.1 -- +++ processing catkin package: 'iiiroboticslidar2' -- ==> add_subdirectory(lidar/iiiroboticslidar2_ros) -- +++ processing catkin package: 'astra_camera' -- ==> add_subdirectory(ros_astra_camera) -- Using these message generators: gencpp;geneus;genlisp;gennodejs;genpy -- Boost version: 1.65.1 -- Found the following Boost libraries: -- system -- thread -- chrono -- date_time -- atomic -- ORRBEC Machine : aarch64 -- ORRBEC Machine Bits : 64 -- ORRBEC : arm64 -- libuvc 0.0.6 -- astra_camera: 0 messages, 19 services -- +++ processing catkin package: 'rplidar_ros' -- ==> add_subdirectory(lidar/rplidar_ros) -- +++ processing catkin package: 'eprobot_joy' -- ==> add_subdirectory(eprobot_joy) -- Using these message generators: gencpp;geneus;genlisp;gennodejs;genpy CMake Warning at /opt/ros/melodic/share/catkin/cmake/catkin_package.cmake:166 (message): catkin_package() DEPENDS on 'system_lib' but neither 'system_lib_INCLUDE_DIRS' nor 'system_lib_LIBRARIES' is defined. Call Stack (most recent call first): /opt/ros/melodic/share/catkin/cmake/catkin_package.cmake:102 (_catkin_package) eprobot_joy/CMakeLists.txt:39 (catkin_package) -- +++ processing catkin package: 'lslidar_driver' -- ==> add_subdirectory(lslidar_driver) -- Using these message generators: gencpp;geneus;genlisp;gennodejs;genpy -- Boost version: 1.65.1 CMake Warning at /opt/ros/melodic/share/catkin/cmake/catkin_package.cmake:166 (message): catkin_package() DEPENDS on 'boost' but neither 'boost_INCLUDE_DIRS' nor 'boost_LIBRARIES' is defined. Call Stack (most recent call first): /opt/ros/melodic/share/catkin/cmake/catkin_package.cmake:102 (_catkin_package) lslidar_driver/CMakeLists.txt:22 (catkin_package) -- +++ processing catkin package: 'robot_pose_ekf' -- ==> add_subdirectory(robot_pose_ekf) -- Using these message generators: gencpp;geneus;genlisp;gennodejs;genpy -- Boost version: 1.65.1 -- Found the following Boost libraries: -- thread -- chrono -- system -- date_time -- atomic -- robot_pose_ekf: 0 messages, 1 services -- +++ processing catkin package: 'sc_mini' -- ==> add_subdirectory(lidar/sc_mini) -- Using these message generators: gencpp;geneus;genlisp;gennodejs;genpy -- Boost version: 1.65.1 -- +++ processing catkin package: 'amcl' -- ==> add_subdirectory(navigation-melodic/amcl) -- Using these message generators: gencpp;geneus;genlisp;gennodejs;genpy -- Boost version: 1.65.1 -- +++ processing catkin package: 'fake_localization' -- ==> add_subdirectory(navigation-melodic/fake_localization) -- Using these message generators: gencpp;geneus;genlisp;gennodejs;genpy -- Boost version: 1.65.1 -- +++ processing catkin package: 'laser_filters' -- ==> add_subdirectory(laser_filters) -- Using these message generators: gencpp;geneus;genlisp;gennodejs;genpy -- Boost version: 1.65.1 -- Found the following Boost libraries: -- system -- +++ processing catkin package: 'robot_localization' -- ==> add_subdirectory(robot_localization) robot_localization: You did not request a specific build type: selecting 'RelWithDebInfo'. -- Using these message generators: gencpp;geneus;genlisp;gennodejs;genpy -- robot_localization: 0 messages, 7 services -- +++ processing catkin package: 'track_detection' -- ==> add_subdirectory(track_detection) -- +++ processing catkin package: 'voxel_grid' -- ==> add_subdirectory(navigation-melodic/voxel_grid) -- +++ processing catkin package: 'costmap_2d' -- ==> add_subdirectory(navigation-melodic/costmap_2d) -- Using these message generators: gencpp;geneus;genlisp;gennodejs;genpy -- Boost version: 1.65.1 -- Found the following Boost libraries: -- system -- thread -- chrono -- date_time -- atomic -- costmap_2d: 1 messages, 0 services -- +++ processing catkin package: 'nav_core' -- ==> add_subdirectory(navigation-melodic/nav_core) -- Using these message generators: gencpp;geneus;genlisp;gennodejs;genpy -- +++ processing catkin package: 'base_local_planner' -- ==> add_subdirectory(navigation-melodic/base_local_planner) -- Using these message generators: gencpp;geneus;genlisp;gennodejs;genpy -- Boost version: 1.65.1 -- Found the following Boost libraries: -- thread -- chrono -- system -- date_time -- atomic -- base_local_planner: 1 messages, 0 services -- +++ processing catkin package: 'carrot_planner' -- ==> add_subdirectory(navigation-melodic/carrot_planner) -- Using these message generators: gencpp;geneus;genlisp;gennodejs;genpy -- +++ processing catkin package: 'clear_costmap_recovery' -- ==> add_subdirectory(navigation-melodic/clear_costmap_recovery) -- Using these message generators: gencpp;geneus;genlisp;gennodejs;genpy -- +++ processing catkin package: 'dwa_local_planner' -- ==> add_subdirectory(navigation-melodic/dwa_local_planner) -- Using these message generators: gencpp;geneus;genlisp;gennodejs;genpy -- +++ processing catkin package: 'move_slow_and_clear' -- ==> add_subdirectory(navigation-melodic/move_slow_and_clear) -- Using these message generators: gencpp;geneus;genlisp;gennodejs;genpy -- Boost version: 1.65.1 -- Found the following Boost libraries: -- thread -- chrono -- system -- date_time -- atomic -- +++ processing catkin package: 'navfn' -- ==> add_subdirectory(navigation-melodic/navfn) -- Using these message generators: gencpp;geneus;genlisp;gennodejs;genpy -- navfn: 0 messages, 2 services -- NAVFN_HAVE_FLTK: , NETPBM: 1 -- FLTK orf NETPBM not found: cannot build navtest -- +++ processing catkin package: 'global_planner' -- ==> add_subdirectory(navigation-melodic/global_planner) -- Using these message generators: gencpp;geneus;genlisp;gennodejs;genpy -- +++ processing catkin package: 'rotate_recovery' -- ==> add_subdirectory(navigation-melodic/rotate_recovery) -- Using these message generators: gencpp;geneus;genlisp;gennodejs;genpy -- +++ processing catkin package: 'move_base' -- ==> add_subdirectory(navigation-melodic/move_base) -- Using these message generators: gencpp;geneus;genlisp;gennodejs;genpy -- +++ processing catkin package: 'teb_local_planner' -- ==> add_subdirectory(teb_local_planner-melodic) -- Using these message generators: gencpp;geneus;genlisp;gennodejs;genpy -- System: Linux-5.3.0-1030-raspi2 -- /opt/ros/melodic/share/cmake_modules/cmake/../../../share/cmake_modules/cmake/Modules;/home/EPRobot/robot_ws/src/teb_local_planner-melodic/cmake_modules -- Boost version: 1.65.1 -- Found the following Boost libraries: -- system -- thread -- graph -- chrono -- date_time -- atomic -- Found SuiteSparse -- Searching for g2o ... -- Found g2o headers in: /opt/ros/melodic/include/g2o -- Found libg2o: /opt/ros/melodic/lib/libg2o_csparse_extension.so;/opt/ros/melodic/lib/libg2o_core.so;/opt/ros/melodic/lib/libg2o_stuff.so;/opt/ros/melodic/lib/libg2o_types_slam2d.so;/opt/ros/melodic/lib/libg2o_types_slam3d.so;/opt/ros/melodic/lib/libg2o_solver_cholmod.so;/opt/ros/melodic/lib/libg2o_solver_pcg.so;/opt/ros/melodic/lib/libg2o_solver_csparse.so;/opt/ros/melodic/lib/libg2o_incremental.so -- teb_local_planner: 3 messages, 0 services -- +++ processing catkin package: 'eprobot_description' -- ==> add_subdirectory(eprobot_description) -- +++ processing catkin package: 'xf_mic_asr_offline' -- ==> add_subdirectory(xf_mic_asr_offline) -- Using these message generators: gencpp;geneus;genlisp;gennodejs;genpy -- xf_mic_asr_offline: 2 messages, 7 services -- +++ processing catkin package: 'ydlidar' -- ==> add_subdirectory(ydlidar) -- +++ processing catkin package: 'yocs_ar_pair_approach' -- ==> add_subdirectory(yujin_ocs/yocs_ar_pair_approach) -- +++ processing catkin package: 'yocs_cmd_vel_mux' -- ==> add_subdirectory(yujin_ocs/yocs_cmd_vel_mux) -- +++ processing catkin package: 'yocs_controllers' -- ==> add_subdirectory(yujin_ocs/yocs_controllers) -- +++ processing catkin package: 'yocs_keyop' -- ==> add_subdirectory(yujin_ocs/yocs_keyop) -- Could NOT find ecl_threads (missing: ecl_threads_DIR) -- Could not find the required component 'ecl_threads'. The following CMake error indicates that you either need to install the package with the same name or change your environment so that it can be found. CMake Error at /opt/ros/melodic/share/catkin/cmake/catkinConfig.cmake:83 (find_package): Could not find a package configuration file provided by "ecl_threads" with any of the following names: ecl_threadsConfig.cmake ecl_threads-config.cmake Add the installation prefix of "ecl_threads" to CMAKE_PREFIX_PATH or set "ecl_threads_DIR" to a directory containing one of the above files. If "ecl_threads" provides a separate development package or SDK, be sure it has been installed. Call Stack (most recent call first): yujin_ocs/yocs_keyop/CMakeLists.txt:3 (find_package) -- Configuring incomplete, errors occurred! See also "/home/EPRobot/robot_ws/build/CMakeFiles/CMakeOutput.log". See also "/home/EPRobot/robot_ws/build/CMakeFiles/CMakeError.log". Makefile:9560: recipe for target 'cmake_check_build_system' failed make: *** [cmake_check_build_system] Error 1 Invoking "make cmake_check_build_system" failed EPRobot@EPRobot:~/robot_ws$ source devel/setup.bash # 在每次打开新终端时运行
最新发布
07-17
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值