Понимание радарных данных

искусственный интеллект

В предыдущей статье мы изучили различные свойства данных радара путем экспериментов, но как данные радара отражаются в коде?

В этой статье вы узнаете, как просматривать данные радара и как обрабатывать данные радара, создавая новый пакет ros.

Во-первых, позвольте мне объяснить среду кода, которую я использую:

Версия Ubuntu: 16.04.01 ROS: кинетическая версия
Язык программирования: С++ Рекомендация IDE: в настоящее время я использую код VS, как его настроить, будет объяснено в следующей статье.

1 Формат сообщения лидарных данных в ros

Формат сообщения данных лидара в ros можно распечатать, введя следующую команду в терминале

rosmsg show sensor_msgs/LaserScan

Результат показан ниже

std_msgs/Header header	// 数据的消息头
  uint32 seq			// 数据的序号
  time stamp			// 数据的时间戳
  string frame_id		// 数据的坐标系
float32 angle_min		// 雷达数据的起始角度(最小角度)
float32 angle_max		// 雷达数据的终止角度(最大角度)
float32 angle_increment	// 雷达数据的角度分辨率(角度增量)
float32 time_increment	// 雷达数据每个数据点的时间间隔
float32 scan_time		// 当前帧数据与下一帧数据的时间间隔
float32 range_min		// 雷达数据的最小值
float32 range_max		// 雷达数据的最大值
float32[] ranges		// 雷达数据每个点对应的在极坐标系下的距离值
float32[] intensities	// 雷达数据每个点对应的强度值

2 Создайте новый пакет ros

Зная структуру данных радара, мы будем использовать код для более глубокого понимания данных радара.

Сначала создайте новую рабочую область и новый пакет со следующими командами.

mkdir -p ~/catkin_ws/src
cd ~/catkin_ws/src/
catkin_create_pkg lesson1 roscpp sensor_msgs

Поскольку для записи мы используем C++, первая зависимость — roscpp, а поскольку тип данных радара — sensor_msgs/LaserScan, вторая зависимость — sensor_msgs.

2.1 lesson1/src/laser_scan_node.cc

Сначала создайте новый файл в папке урока 1/src и назовите его laser_scan_node.cc. Скопируйте в него следующий код, смысл кода подробно объяснен в комментариях.

#include <ros/ros.h>
#include <sensor_msgs/LaserScan.h>

// 声明一个类
class LaserScan
{
private:
    ros::NodeHandle node_handle_;           // ros中的句柄
    ros::NodeHandle private_node_;          // ros中的私有句柄
    ros::Subscriber laser_scan_subscriber_; // 声明一个Subscriber

public:
    LaserScan();
    ~LaserScan();
    void ScanCallback(const sensor_msgs::LaserScan::ConstPtr &scan_msg);
};

// 构造函数
LaserScan::LaserScan() : private_node_("~")
{
    ROS_INFO_STREAM("LaserScan initial.");
    // 将雷达的回调函数与订阅的topic进行绑定
    laser_scan_subscriber_ = node_handle_.subscribe("laser_scan", 1, &LaserScan::ScanCallback, this);
}

LaserScan::~LaserScan()
{
}

// 回调函数
void LaserScan::ScanCallback(const sensor_msgs::LaserScan::ConstPtr &scan_msg)
{
    ROS_INFO_STREAM(
        "seqence: " << scan_msg->header.seq << 
        ", time stamp: " << scan_msg->header.stamp << 
        ", frame_id: " << scan_msg->header.frame_id << 
        ", angle_min: " << scan_msg->angle_min << 
        ", angle_max: " << scan_msg->angle_max << 
        ", angle_increment: " << scan_msg->angle_increment << 
        ", time_increment: " << scan_msg->time_increment << 
        ", scan_time: " << scan_msg->scan_time << 
        ", range_min: " << scan_msg->range_min << 
        ", range_max: " << scan_msg->range_max << 
        ", range size: " << scan_msg->ranges.size() << 
        ", intensities size: " << scan_msg->intensities.size());

    // 第5个点的欧式坐标为
    double range = scan_msg->ranges[4];
    double angle = scan_msg->angle_min + scan_msg->angle_increment * 4;
    double x = range * cos(angle);
    double y = range * sin(angle);

    ROS_INFO_STREAM(
        // 第5个数据点对应的极坐标为: 
        "range = " << range << ", angle = " << angle << 
        // 第5个数据点对应的欧式坐标为: 
        ", x = " << x << ", y = " << y
    );

    // 通过ranges中数据的个数进行雷达数据的遍历
    // for (int i = 0; i < scan_msg->ranges.size(); i++)
    // {

    // }

}

int main(int argc, char **argv)
{
    ros::init(argc, argv, "lesson1_laser_scan_node"); // 节点的名字
    LaserScan laser_scan;

    ros::spin();    // 程序执行到此处时开始进行等待,每次订阅的消息到来都会执行一次ScanCallback()
    return 0;
}

2.2 CMakeLists.txt

Поскольку мы добавили файл .cc, нам нужно добавить параметры компиляции в этот файл в CMakeLists.txt и добавить следующее в конец файла:

# 为指定的文件生成可执行文件
add_executable(${PROJECT_NAME}_laser_scan_node src/laser_scan_node.cc)

# 为生成的可执行文件添加依赖
add_dependencies(${PROJECT_NAME}_laser_scan_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})

# 为生成的可执行文件添加库的链接
target_link_libraries(${PROJECT_NAME}_laser_scan_node
  ${catkin_LIBRARIES}
)

2.3 package.xml

Поскольку мы используемcatkin_create_pkgПакет, сгенерированный командой, уже был настроен с помощью package.xml при создании пакета, поэтому нам не нужно изменять этот файл здесь, а только перечислить содержимое сгенерированного файла.

<?xml version="1.0"?>
<package format="2">
  <name>lesson1</name>
  <version>0.0.0</version>
  <description>The lesson1 package</description>

  <maintainer email="lx@todo.todo">lx</maintainer>

  <license>TODO</license>

  <buildtool_depend>catkin</buildtool_depend>
  <build_depend>roscpp</build_depend>
  <build_depend>sensor_msgs</build_depend>
  <build_export_depend>roscpp</build_export_depend>
  <build_export_depend>sensor_msgs</build_export_depend>
  <exec_depend>roscpp</exec_depend>
  <exec_depend>sensor_msgs</exec_depend>
  
  <export>
  </export>
</package>

2.4 Компиляция

После изменения файла CMakeLists.txt код можно скомпилировать. Конкретные инструкции следующие:

cd ~/catkin_ws
catkin_make

2.5 Бег

Если ничего другого, не должно быть никаких ошибок компиляции.

После завершения компиляции в папке ~/catkin_ws/devel/lib/lesson1 будет сгенерирован исполняемый файл с именем Lesson1_laser_scan_node.

Мы можем выполнить его с помощью следующей команды

首先,开一个终端,在终端中输入 roscore
再新建一个终端,在终端中输入 
cd ~/catkin_ws/devel/lib/lesson1 
./lesson1_laser_scan_node

Будет напечатан следующий журнал,

[ INFO] [1606545572.752075473]: LaserScan initial.

В это время никакое другое сообщение не распечатывается. Это связано с тем, что наш код не получил сообщение данных лидара, поэтому мы воспроизводим сумку с помощью следующей команды. После загрузки данных сумки щелкните правой кнопкой мыши, чтобы распаковать ее, и поместите его в папку ~/bagfiles.

(соответствует этомуданные сумкиможешь пойти к моемуОфициальный аккаунт: Создайте SLAM с нуляОтветить вlesson1Получить ссылку для скачивания,)

再次新开一个终端,输入如下命令
cd ~/bagfiles
rosbag play lesson1.bag

В это время в окне терминала, выполняющем ./lesson1_laser_scan_node, должно непрерывно выводиться следующее сообщение.


[ INFO] [1606545575.110606737]: seqence: 4131, time stamp: 1606455444.278184417, frame_id: front_laser_link, angle_min: -3.14159, angle_max: 3.14159, angle_increment: 0.00436332, time_increment: 7.15627e-05, scan_time: 0.102979, range_min: 0.01, range_max: 25, range size: 1440, intensities size: 1440
[ INFO] [1606545575.110772238]: range = 2.6, angle = -3.12414, x = -2.5996, y = -0.0453758

2.6 Анализ результатов

Из этой информации мы видим, что:

  • Система координат радара — front_laser_link.

  • Минимальный и максимальный углы данных радара составляют -3,14159 и 3,14159 соответственно.Видно, что это радар с горизонтальным углом обзора 360 градусов.

  • Ближайшее и дальнее расстояние данных радара составляет 0,01 м и 25 м соответственно.Видно, что слепая зона этого радара составляет 1 см.

  • Неделя сканирования радара вернет 1440 точек данных.

2.7 Описание

2.7.1

Из данных радара мы можем получить самую основную информацию о данных радара, но эта информация не обязательно верна и надежна, потому что эти данные записываются в пакете драйвера радара, а коды некоторых производителей радаров не стандартизированы. быть неверным. Например, слепая зона радара редко бывает меньше 1 см, а обычно превышает 10 см.

2.7.2 Преобразование координат

Кроме того, поле диапазонов в данных радара хранит только значения расстояний в полярной системе координат.Если мы хотим узнать евклидовы координаты каждой точки данных, нам также необходимо преобразовать полярные координаты.

Метод преобразования заключается в том, чтобы получить значение в диапазонах через индекс, а затем вычислить угол, соответствующий этому значению, через индекс

Значение расстояния i-й точки данных равно ranges[i] Угол i-й точки данных равен angle = angle_min + angle_increment * i Таким образом, координата x, соответствующая этой точке, равна ranges[i] * cos(angle) Таким образом, координата y, соответствующая этой точке, равна ranges[i] * sin(angle)

2.7.3 Обход данных радара

Обход данных двумерного лидара осуществляется только через цикл for по полям количества диапазонов, а значение расстояния получается через индекс.

2.8 файл запуска

2.8.1 файл запуска

В настоящее время, если мы хотим запустить этот узел, нам нужно открыть 3 терминала, чтобы запустить его.Есть ли более удобный способ запустить его?

Конечно, ROS использует файл запуска для реализации этой функции.

Прежде всего, сначала закройте все открытые терминалы, и команда для завершения того, что выполняется в ubuntu,Ctrl+C.

# 新建一个launch文件夹
mkdir -p ~/catkin_ws/src/lesson1/launch 

Создайте новый файл с именем demo.launch во вновь созданной папке запуска и заполните следующее содержимое.

<launch>

    <!-- bag的地址与名称,需要改成自己电脑的对应的地址 -->
    <arg name="bag_filename" default="/home/lx/bagfiles/lesson1.bag"/>

    <!-- 使用bag的时间戳 -->
    <param name="use_sim_time" value="true" />

    <!-- 启动节点 -->
    <node name="lesson1_laser_scan_node" pkg="lesson1" type="lesson1_laser_scan_node" output="screen" />

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

</launch>

Далее, пока файл запуска запущен, он поможет нам запустить roscore, нужную ноду и воспроизведение мешка.

2.8.2 Настройка среды

Поскольку мы являемся новой рабочей областью, нам сначала нужно выполнить следующую команду, чтобы зарегистрировать индекс нашего нового пакета в терминале, чтобы терминал мог найти наш пакет.

rospack profile
source ~/catkin_ws/devel/setup.bash

Исходную команду необходимо выполнять повторно каждый раз, когда открывается новый терминал, и ее также можно записать в .bashrc с помощью следующей команды, чтобы каждый раз при открытии нового терминала исходную команду больше не нужно было выполнять. .

echo "source ~/catkin_ws/devel/setup.bash" >> ~/.bashrc 

Окружение готово, далее запускаем файл запуска через roslaunch

roslaunch lesson1 demo.launch

Если все пойдет хорошо, мы можем получить тот же результат, что и выше.

3 Резюме

В этой статье мы создали новый пакет в ROS с нуля на примере получения лидарных данных.

Мы объяснили, как создать новый пакет с помощью команд и как добавить зависимости при создании нового пакета.

После этого мы создали новый файл .cc.Содержимое в файле записано в стандартном формате ROS.В дальнейшем наши программы будут писаться в соответствии с этим режимом. В программе мы знаем содержание сообщения данных радара, как преобразовывать полярные координаты в евклидовы координаты и как перемещаться по данным радара.

После этого мы изменили файл CMakeLists.txt, и он успешно компилируется и запускается.

Наконец, мы рассмотрели файл запуска и то, как настроить среду для кода.

4 Next

В следующей статье мы не будем так подробно объяснять окружение, а уделим больше внимания реализации функций и реализации кода.

В следующей статье мы расскажем, как обрабатывать и фильтровать данные радара, как идентифицировать телят-людей в данных радара и отфильтровывать телят-людей.


Статья будет вОфициальный аккаунт: Создайте SLAM с нуляСинхронизированные обновления, каждый может обратить внимание, чтобы уведомить вас, как только статья будет обновлена.

В то же время я также надеюсь, что вы порекомендуете этот официальный аккаунт окружающим вас людям, которые занимаются лазерным SLAM, чтобы все вместе могли добиться прогресса.

существуетпубликаОтветить вlesson1доступно в этой статьеданные сумкиссылка для скачивания существуетпубликаОтветить вадрес с открытым исходным кодомВы можете получить адрес github кода в этой статье

在这里插入图片描述