<librarypath="lib/libcostmap_prohibition_layer"> <classtype="costmap_prohibition_layer_namespace::CostmapProhibitionLayer"base_class_type="costmap_2d::Layer"> <description>ROS-Package that implements a costmap layer to add prohibited areas to the costmap-2D by a user configuration.</description> </class> </library>
以上估计线速度和角速度所用的两次scan mathch的位姿的处理都在UpdateVelocitiesFromPoses。如果出现了报警: Queue too short for velocity estimation,可以尝试降低odometry_sampling_ratio 和 imu_sampling_ratio,先从1降到0.5
voidSensorBridge::HandleLaserScan( const std::string& sensor_id, const carto::common::Time time, const std::string& frame_id, const carto::sensor::PointCloudWithIntensities& points) { if (points.points.empty()) return; CHECK_LE(points.points.back()[3], 0); //最后一个点云数据的时间小于等于0 for (int i = 0; i != num_subdivisions_per_laser_scan_; ++i) { constsize_t start_index = points.points.size() * i / num_subdivisions_per_laser_scan_; constsize_t end_index = points.points.size() * (i + 1) / num_subdivisions_per_laser_scan_; // 每一小段 carto::sensor::TimedPointCloud subdivision( points.points.begin() + start_index, points.points.begin() + end_index); if (start_index == end_index) { continue; } // 参考分段中最后一个数据的时间,调整其他数据的时间 constdouble time_to_subdivision_end = subdivision.back()[3]; // subdivision_time is the end of the measurement so sensor::Collator will // send all other sensor data first. // 先确认当前的数据没有过时,如果分段的时间落后于记录值,将抛弃所对应的数据 const carto::common::Time subdivision_time = time + carto::common::FromSeconds(time_to_subdivision_end); auto it = sensor_to_previous_subdivision_time_.find(sensor_id); if (it != sensor_to_previous_subdivision_time_.end() && it->second >= subdivision_time) { LOG(WARNING) << "Ignored subdivision of a LaserScan message from sensor " << sensor_id << " because previous subdivision time " << it->second << " is not before current subdivision time " << subdivision_time; continue; } sensor_to_previous_subdivision_time_[sensor_id] = subdivision_time; for (Eigen::Vector4f& point : subdivision) { point[3] -= time_to_subdivision_end; } CHECK_EQ(subdivision.back()[3], 0); // 将分段数据喂给Cartographer HandleRangefinder(sensor_id, subdivision_time, frame_id, subdivision); } }
// 如果小于min_num_points,点云太稀疏,用于扫描匹配就不准了 // 说明上面的 max_length太大了,现在要使用二分法找一个合适的参数 // Search for a 'low_length' that is known to result in a sufficiently // dense point cloud. We give up and use the full 'point_cloud' if reducing // the edge length by a factor of 1e-2 is not enough. for (float high_length = options.max_length(); high_length > 1e-2f * options.max_length(); high_length /= 2.f) { float low_length = high_length / 2.f; result = VoxelFilter(low_length).Filter(point_cloud); if (result.size() >= options.min_num_points()) { // 二分查找法找到合适的过滤器 // low_length给出足够稠密的结果 // 当 edge length is at most 10% off 时停止 while ((high_length - low_length) / low_length > 1e-1f) { constfloat mid_length = (low_length + high_length) / 2.f; const PointCloud candidate = VoxelFilter(mid_length).Filter(point_cloud); // 点数又多了,增加边长,让 low_length 变大 if (candidate.size() >= options.min_num_points()) { low_length = mid_length; result = candidate; } // 点数偏少,让high_length变小 else { high_length = mid_length; } } return result; } } return result; }