Localization pure

https://blog.csdn.net/weixin_43259286/article/details/105143605

4-25 导航定位测试(盛)

发现问题

1、导航过程中地图漂移,说明地图还在更新。
2、全局规划,穿越障碍物、和未知区域,以及反复更新方向完全不同的全局规划。
无障碍物时,全局规划不成功。
3、全局规划成功,但车辆不运动。
4、导航过程中,回原点,偏差很大(发现导航运行时,位置已经不准,也不能自动校准恢复)
改进:导航过程中开启ODOM,是否会有改善。
5、掉网问题。
6、压脚问题(下部无传感器)。
7、陀螺仪损坏一个,导致单片机看门狗动作,反复复位。
8、激光雷达在特定角度,发现大片不存在的障碍物。

改进测试方案

1、增加手推建图模式,平板操作车辆不方便。
2、查看ctrl_buff 模块CPU占用率,如果过大,删除模块。
3、增加导航时,ODOM 模块信息,看导航定位效果是否提升。
4、改进纯定位模式,修改cartographer源程序,进行测试,是否在导航时,地图不再更新。
5、建立完整地图,并录制数据,进行回放分析。
6、导航时也录制数据,进行回放仿真分析。
7、查找充电模块的BUG,避免因通讯丢包无法退出充电模式的问题。
8、搭载M1M1 进行建图对比测试。
9、修改配置文件,雷达最远距离。将回环检测由90,改为20,提高建图精度。

改为amcl

1、cpu下降至20-30左右,定位比较迅速,定位精度也不差,感觉socket_node通信也变好了。
2、修改cartographer 的pure 源文件,不发布SUB子图了,但导航地图也不发了。
与原文代码版本不一样。

另一篇文章,解决纯定位问题
<launch>
  <!-- <param name="/use_sim_time" value="true" /> -->
  <param name="/use_sim_time" value="false" />  <!--//1.仿真为true-->
 
  <param name="robot_description"
    textfile="$(find cartographer_ros)/urdf/my_backpack_2d.urdf" />  <!--//2.修改机器人模型-->
 
  <node name="robot_state_publisher" pkg="robot_state_publisher"
    type="robot_state_publisher" />
 
  <node name="cartographer_node" pkg="cartographer_ros"
      type="cartographer_node" args="
          -configuration_directory $(find cartographer_ros)/configuration_files
          -configuration_basename my_backpack_2d_localization.lua  //3.纯定位接口参数设置 
          <!-- -load_state_filename $(arg load_state_filename)" -->
          -load_state_filename /home/yourname/Map/map.pbstream" <!--//4.纯定位使用的地图,我是直接用固定路径,这里按照自己的路径修改即可-->
      output="screen">
    <!-- <remap from="echoes" to="horizontal_laser_2d" /> --> <!--//这个好像没啥用,我们一般用的都是 scan-->
  </node>
 
  <node name="cartographer_occupancy_grid_node" pkg="cartographer_ros"
      type="cartographer_occupancy_grid_node" args="-resolution 0.05
                                                    -pure_localization 1" /> <!--//5.修改文件occupancy_node_main.cc  增加是否纯定位模式参数pure_localization(如果选择直接注释就不需要增加这个参数了)-->
 
  <node name="rviz" pkg="rviz" type="rviz" required="true"
      args="-d $(find cartographer_ros)/configuration_files/demo_2d.rviz" />
   <!--<node name="playbag" pkg="rosbag" type="play"
      args="--clock $(arg bag_filename)" /> --> <!--//6.不需要跑数据集,直接打开自己的雷达-->
</launch>
————————————————
版权声明:本文为CSDN博主「梦凝小筑」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_36976685/article/details/103834608在这里插入代码片

Cartographer纯定位接口:

文件:backpack_2d_localization.lua:

TRAJECTORY_BUILDER.pure_localization_trimmer = {
  max_submaps_to_keep = 3, //最大保存子图数,存定位模式通过子图进行定位,但只需要当前和上一个子图即可,我这里设置的是2
}
POSE_GRAPH.optimize_every_n_nodes = 20 //每20个有效帧一个子图,子图构建完成要闭环检测一次,这个数越小,闭环检测越频繁,当然CPU爆炸

修改说明:

  1. 仿真为true,实际测试false

2.修改机器人模型 这里建议新建一个 my_backpack_2d.urdf

里面设置自己的机器人模型,下面是我的

<robot name="cartographer_backpack_2d">
  <material name="orange">
    <color rgba="1.0 0.5 0.2 1" />
  </material>
  <material name="gray">
    <color rgba="0.2 0.2 0.2 1" />
  </material>
 
  <link name="imu_link">
    <visual>
      <origin xyz="0 0 0" />
      <geometry>
        <box size="0.06 0.04 0.02" />
      </geometry>
      <material name="orange" />
    </visual>
  </link>
 
  <link name="base_scan">
    <visual>
      <origin xyz="0 0 0" />
      <geometry>
        <cylinder length="0.05" radius="0.03" />
      </geometry>
      <material name="gray" />
    </visual>
  </link>
  
  <link name="base_footprint" />
 
  <joint name="imu_link_joint" type="fixed">
    <parent link="base_footprint" />
    <child link="imu_link" />
    <origin xyz="0 0 0" />
  </joint>
 
  <joint name="base_scan_joint" type="fixed">
    <parent link="base_footprint" />
    <child link="base_scan" />
    <origin xyz="0.160 0 0.0558" />
  </joint>
 
</robot>

3.纯定位接口参数设置 同样建议新建一个 my_backpack_2d_localization.lua
设置如下:
include “my_backpack_2d.lua”

TRAJECTORY_BUILDER.pure_localization_trimmer = {
  max_submaps_to_keep = 3, //最大保存子图数,存定位模式通过子图进行定位,但只需要当前和上一个子图即可,我这里设置的是2
}
POSE_GRAPH.optimize_every_n_nodes = 20 //每20个有效帧一个子图,子图构建完成要闭环检测一次,这个数越小,闭环检测越频繁,当然CPU爆炸

上面第一行引用的文件是 my_backpack_2d.lua,这个文件是backpack_2d.lua修改过来的,配置Cartographer在定位过程中的其它参数的,这里也建议新建一个my_backpack_2d.lua,用于区分建图时用的参数。

4.纯定位使用的地图,我是直接用固定路径,这里按照自己的路径修改即可

5.修改文件occupancy_node_main.cc
这个文件在路径cartographer_ros-master\cartographer_ros\cartographer_ros\occupancy_grid_node_main.cc
第171行或者直接搜索下面这行代码:
//occupancy_grid_publisher_.publish(*msg_ptr);
注释掉这行代码,不然你纯定位过程建立的子图会覆盖在之前建好的地图上。
但是这行代码在建图的时候又肯定的是需要的,我的解决方法是引入外部参数进行切换。
修改文件在https://github.com/lllray/file/blob/master/occupancy_grid_node_main.cc

6.不需要跑数据集,直接打开自己的雷达
因为是用在自己的机器人上,所以不需要数据集
一般的步骤是:
先开雷达驱动
再开机器人驱动
最后打开我们修改的demo_backpack_2d_localization.launch文件

补充说明:
如果上述步骤失败的,检查下自己的TF变换是否正确,TOPIC是否对上了。
ROS用在机器人导航上就这些问题,只要TOPIC对上了,TF变换正确,基本都没啥问题,这也正是ROS的强大之处。

三、定位结果
我觉的很好,比AMCL好多了,哈哈哈,你们可以试试。
有一个很强大之处,由于Cartographer定位是是当前帧和子图进行匹配,所以对于机器人周围被新物体遮挡的情况完全没有影响。
唯一影响就是没法重定位了,因为地图上没有这些新物体,如下面那一圈障碍。
但是就算长时间被遮挡,存在累积定位误差,只要机器人离开了遮挡区域,回到了之前的环境,就可以重定位回来。
因此Cartographer定位十分稳定,特别是一大堆领导来检查的时候(一般都会把可怜的机器人团团围住),完全没怕的,哈哈哈。

结语:好久没更新了,多了好多粉丝,为了感谢大家的关注,写一篇粉丝可见的文章。
————————————————
版权声明:本文为CSDN博主「梦凝小筑」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_36976685/article/details/103834608

/*
 * Copyright 2016 The Cartographer Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <cmath>
#include <string>
#include <vector>

#include "Eigen/Core"
#include "Eigen/Geometry"
#include "absl/synchronization/mutex.h"
#include "cairo/cairo.h"
#include "cartographer/common/port.h"
#include "cartographer/io/image.h"
#include "cartographer/io/submap_painter.h"
#include "cartographer/mapping/id.h"
#include "cartographer/transform/rigid_transform.h"
#include "cartographer_ros/msg_conversion.h"
#include "cartographer_ros/node_constants.h"
#include "cartographer_ros/ros_log_sink.h"
#include "cartographer_ros/submap.h"
#include "cartographer_ros_msgs/SubmapList.h"
#include "cartographer_ros_msgs/SubmapQuery.h"
#include "gflags/gflags.h"
#include "nav_msgs/OccupancyGrid.h"
#include "ros/ros.h"

//LX ADD 0412
DEFINE_int32(pure_localization,0,"Pure localization !");
//END 0412
DEFINE_double(resolution, 0.05,
              "Resolution of a grid cell in the published occupancy grid.");
DEFINE_double(publish_period_sec, 1.0, "OccupancyGrid publishing period.");
DEFINE_bool(include_frozen_submaps, true,
            "Include frozen submaps in the occupancy grid.");
DEFINE_bool(include_unfrozen_submaps, true,
            "Include unfrozen submaps in the occupancy grid.");
DEFINE_string(occupancy_grid_topic, cartographer_ros::kOccupancyGridTopic,
              "Name of the topic on which the occupancy grid is published.");

namespace cartographer_ros {
namespace {

using ::cartographer::io::PaintSubmapSlicesResult;
using ::cartographer::io::SubmapSlice;
using ::cartographer::mapping::SubmapId;

class Node {
 public:
  //LX CHANGE 0412
  //explicit Node(double resolution, double publish_period_sec);
  explicit Node(int pure_localization, double resolution, double publish_period_sec);
  //END 0412

  ~Node() {}

  Node(const Node&) = delete;
  Node& operator=(const Node&) = delete;

 private:
  void HandleSubmapList(const cartographer_ros_msgs::SubmapList::ConstPtr& msg);
  void DrawAndPublish(const ::ros::WallTimerEvent& timer_event);

  ::ros::NodeHandle node_handle_;
  const double resolution_;

  //LX ADD 0412
  const int pure_localization_;
  //END 0412

  absl::Mutex mutex_;
  ::ros::ServiceClient client_ GUARDED_BY(mutex_);
  ::ros::Subscriber submap_list_subscriber_ GUARDED_BY(mutex_);
  ::ros::Publisher occupancy_grid_publisher_ GUARDED_BY(mutex_);
  std::map<SubmapId, SubmapSlice> submap_slices_ GUARDED_BY(mutex_);
  ::ros::WallTimer occupancy_grid_publisher_timer_;
  std::string last_frame_id_;
  ros::Time last_timestamp_;
};

    //LX CHANGE 0412
    //Node::Node(const double resolution, const double publish_period_sec)
 Node::Node(const int pure_localization, const double resolution, const double publish_period_sec)
 //: pure_localization_(pure_localization), //END 0412
  :  resolution_(resolution),
     pure_localization_(pure_localization),
      client_(node_handle_.serviceClient<::cartographer_ros_msgs::SubmapQuery>(
          kSubmapQueryServiceName)),
      submap_list_subscriber_(node_handle_.subscribe(
          kSubmapListTopic, kLatestOnlyPublisherQueueSize,
          boost::function<void(
              const cartographer_ros_msgs::SubmapList::ConstPtr&)>(
              [this](const cartographer_ros_msgs::SubmapList::ConstPtr& msg) {
                HandleSubmapList(msg);
              }))),
      occupancy_grid_publisher_(
          node_handle_.advertise<::nav_msgs::OccupancyGrid>(
              FLAGS_occupancy_grid_topic, kLatestOnlyPublisherQueueSize,
              true /* latched */)),
      occupancy_grid_publisher_timer_(
          node_handle_.createWallTimer(::ros::WallDuration(publish_period_sec),
                                       &Node::DrawAndPublish, this)) {}

void Node::HandleSubmapList(
    const cartographer_ros_msgs::SubmapList::ConstPtr& msg) {
  absl::MutexLock locker(&mutex_);

  // We do not do any work if nobody listens.
  if (occupancy_grid_publisher_.getNumSubscribers() == 0) {
    return;
  }

  // Keep track of submap IDs that don't appear in the message anymore.
  std::set<SubmapId> submap_ids_to_delete;
  for (const auto& pair : submap_slices_) {
    submap_ids_to_delete.insert(pair.first);
  }

  for (const auto& submap_msg : msg->submap) {
    const SubmapId id{submap_msg.trajectory_id, submap_msg.submap_index};
    submap_ids_to_delete.erase(id);
    if ((submap_msg.is_frozen && !FLAGS_include_frozen_submaps) ||
        (!submap_msg.is_frozen && !FLAGS_include_unfrozen_submaps)) {
      continue;
    }
    SubmapSlice& submap_slice = submap_slices_[id];
    submap_slice.pose = ToRigid3d(submap_msg.pose);
    submap_slice.metadata_version = submap_msg.submap_version;
    if (submap_slice.surface != nullptr &&
        submap_slice.version == submap_msg.submap_version) {
      continue;
    }

    auto fetched_textures =
        ::cartographer_ros::FetchSubmapTextures(id, &client_);
    if (fetched_textures == nullptr) {
      continue;
    }
    CHECK(!fetched_textures->textures.empty());
    submap_slice.version = fetched_textures->version;

    // We use the first texture only. By convention this is the highest
    // resolution texture and that is the one we want to use to construct the
    // map for ROS.
    const auto fetched_texture = fetched_textures->textures.begin();
    submap_slice.width = fetched_texture->width;
    submap_slice.height = fetched_texture->height;
    submap_slice.slice_pose = fetched_texture->slice_pose;
    submap_slice.resolution = fetched_texture->resolution;
    submap_slice.cairo_data.clear();
    submap_slice.surface = ::cartographer::io::DrawTexture(
        fetched_texture->pixels.intensity, fetched_texture->pixels.alpha,
        fetched_texture->width, fetched_texture->height,
        &submap_slice.cairo_data);
  }

  // Delete all submaps that didn't appear in the message.
  for (const auto& id : submap_ids_to_delete) {
    submap_slices_.erase(id);
  }

  last_timestamp_ = msg->header.stamp;
  last_frame_id_ = msg->header.frame_id;
}

void Node::DrawAndPublish(const ::ros::WallTimerEvent& unused_timer_event) {
  absl::MutexLock locker(&mutex_);
  if (submap_slices_.empty() || last_frame_id_.empty()) {
    return;
  }
  auto painted_slices = PaintSubmapSlices(submap_slices_, resolution_);
  std::unique_ptr<nav_msgs::OccupancyGrid> msg_ptr = CreateOccupancyGridMsg(
      painted_slices, resolution_, last_frame_id_, last_timestamp_);
  //LX CHANGE 0412
  //occupancy_grid_publisher_.publish(*msg_ptr);
  if(pure_localization_ != 1 )occupancy_grid_publisher_.publish(*msg_ptr);
  //END 0412
}

}  // namespace
}  // namespace cartographer_ros

int main(int argc, char** argv) {
  google::InitGoogleLogging(argv[0]);
  google::ParseCommandLineFlags(&argc, &argv, true);

  CHECK(FLAGS_include_frozen_submaps || FLAGS_include_unfrozen_submaps)
      << "Ignoring both frozen and unfrozen submaps makes no sense.";

  ::ros::init(argc, argv, "cartographer_occupancy_grid_node");
  ::ros::start();

  cartographer_ros::ScopedRosLogSink ros_log_sink;
  ::cartographer_ros::Node node(FLAGS_pure_localization, FLAGS_resolution, FLAGS_publish_period_sec);

  ::ros::spin();
  ::ros::shutdown();
}
更早的文章1

上车测试:
测试:发现车辆位置轻微快速漂移,后关闭了提供ODOM帧,TF树上无ODOM了,并将MOVE_BASE的
参数都改为 /map 和 /base_link , 别的参数不用改,主要改地代价地图,将ODOM 改为MAP 后,定位
很准,无漂移。

后将车子凌空搬动1米,还是出现位置漂移,未达到预期效果,关闭use_odometry,单独使用IMU还是
不正常,原因待查,怀疑是IMU 数据不对。
观察到车辆轻微打滑,定位几乎不受影响。

1)修改了SCAN 的 num_accumulated_range_data 参数后,在单独SCAN/ IMU+SCAN /IMU+ODOM+SCAN
感觉定位效果都可以,CPU 占用率差不不大。平均30%-40%, 偶尔到120%。i3 - 6100U。

1、Localization launch

 <param name="/use_sim_time" value="true" />

  <param name="robot_description"
    textfile="$(find cartographer_ros)/urdf/backpack_2d.urdf" />

  <node name="robot_state_publisher" pkg="robot_state_publisher"
    type="robot_state_publisher" />

  <node name="cartographer_node" pkg="cartographer_ros"
      type="cartographer_node" args="
          -configuration_directory $(find cartographer_ros)/configuration_files
          -configuration_basename backpack_2d_localization.lua
          -load_state_filename $(arg load_state_filename)"
      output="screen">
    <remap from="echoes" to="horizontal_laser_2d" />
  </node>

  <node name="cartographer_occupancy_grid_node" pkg="cartographer_ros"
      type="cartographer_occupancy_grid_node" args="-resolution 0.05" />

  <node name="playbag" pkg="rosbag" type="play"
      args="--clock $(arg bag_filename)" />

2、仿真启动命令
roslaunch t3_l.launch load_state_filename:= H O M E / m a p s / m y m a p . p b s t r e a m b a g f i l e n a m e : = {HOME}/maps/mymap.pbstream bag_filename:= HOME/maps/mymap.pbstreambagfilename:={HOME}/bag/rdata_1.bag

3、backpack_2d_localization.lua 文件内容
在这里插入图片描述
4、屏幕信息截图
在这里插入图片描述
在这里插入图片描述
5、TF树
提供:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
不提供ODOM 帧:
在这里插入图片描述

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值