Rplidar A1使用并改为ROS中3D点云输出(PointCloud2)

2023-05-16

这里写自定义目录标题

  • Rplidar A1使用并改为ROS中3D点云输出
    • Rplidar安装
    • 测试
    • 修改后完整代码
    • 测试

Rplidar A1使用并改为ROS中3D点云输出

3D激光雷达价格不菲,在研究过程中,可以尝试将2D激光雷达的点云输出改为3D的点云输出,以进行3D激光雷达的部分试验。本文将安装Rplidar的依赖项并且在ROS的Rviz上可视化。并将Rplidar的/scan信息改为/PointCloud2信息进行输出,以通过2D激光雷达实现3D激光雷达的模拟应用。

Rplidar安装

建立工作空间(也可以利用现有的),编译包

$ mkdir -p  ~/turtlebot_ws/src
$ cd   ~/turtlebot_ws/src
$ git clone https://github.com/ncnynl/rplidar_ros.git#这部分要到思岚科技的github去找具体链接,到目前克隆链接是https://github.com/robopeak/rplidar_ros.git

添加环境变量

source /home/ubu/turtlebot_ws/devel/setup.bash 
source ~/.bashrc

检查、设置端口权限

ls -l /dev |grep ttyUSB
sudo chmod 666 /dev/ttyUSB0

在此Rplidar应该已经可以使用

测试

在工作空间下运行rplidar和打开rviz查看

roslaunch rplidar_ros rplidar.launch
rosrun rviz rviz

设置相关配置后可以看见2D雷达的输出图像
在这里插入图片描述

修改后完整代码

从“LaserScan”和“PointCloud2”参数对比可以看出,“PointCloud2”可以满足三维显示的需求,因此修改rplidar_ros。其中“client.cpp”不需要修改,“node.cpp”修改如下:

/*
 *  RPLIDAR ROS NODE
 *
 *  Copyright (c) 2009 - 2014 RoboPeak Team
 *  http://www.robopeak.com
 *  Copyright (c) 2014 - 2016 Shanghai Slamtec Co., Ltd.
 *  http://www.slamtec.com
 *
 */
/*
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include "ros/ros.h"
#include "sensor_msgs/LaserScan.h"
#include "std_srvs/Empty.h"
#include "rplidar.h"

#include <pcl_ros/point_cloud.h>
#include <pcl/point_types.h>
#include <boost/foreach.hpp>

#ifndef _countof
#define _countof(_Array) (int)(sizeof(_Array) / sizeof(_Array[0]))
#endif

#ifndef DEG2RAD
#define DEG2RAD(x) ((x)*M_PI/180.)
#endif


using namespace rp::standalone::rplidar;
typedef pcl::PointCloud<pcl::PointXYZ> PointCloud;
pcl::PointCloud<pcl::PointXYZ> cloud_msg;
RPlidarDriver * drv = NULL;

void publish_scan(ros::Publisher *pub,ros::Publisher *cloud_pub, 
                  rplidar_response_measurement_node_t *nodes,
                  size_t node_count, ros::Time start,
                  double scan_time, bool inverted,
                  float angle_min, float angle_max,
                  float max_distance,
                  std::string frame_id)
{
    static int scan_count = 0;
    sensor_msgs::LaserScan scan_msg;

    scan_msg.header.stamp = start;
    scan_msg.header.frame_id = frame_id;
    scan_count++;

    bool reversed = (angle_max > angle_min);
    if ( reversed ) {
      scan_msg.angle_min =  M_PI - angle_max;
      scan_msg.angle_max =  M_PI - angle_min;
    } else {
      scan_msg.angle_min =  M_PI - angle_min;
      scan_msg.angle_max =  M_PI - angle_max;
    }
    scan_msg.angle_increment =
        (scan_msg.angle_max - scan_msg.angle_min) / (double)(node_count-1);

    scan_msg.scan_time = scan_time;
    scan_msg.time_increment = scan_time / (double)(node_count-1);
    scan_msg.range_min = 0.15;
    scan_msg.range_max = max_distance;//8.0;

    scan_msg.intensities.resize(node_count);
    scan_msg.ranges.resize(node_count);
    bool reverse_data = (!inverted && reversed) || (inverted && !reversed);
    if (!reverse_data) {
        for (size_t i = 0; i < node_count; i++) {
            float read_value = (float) nodes[i].distance_q2/4.0f/1000;
            if (read_value == 0.0)
                scan_msg.ranges[i] = std::numeric_limits<float>::infinity();
            else
                scan_msg.ranges[i] = read_value;
            scan_msg.intensities[i] = (float) (nodes[i].sync_quality >> 2);
        }
    } else {
        for (size_t i = 0; i < node_count; i++) {
            float read_value = (float)nodes[i].distance_q2/4.0f/1000;
            if (read_value == 0.0)
                scan_msg.ranges[node_count-1-i] = std::numeric_limits<float>::infinity();
            else
                scan_msg.ranges[node_count-1-i] = read_value;
            scan_msg.intensities[node_count-1-i] = (float) (nodes[i].sync_quality >> 2);
        }
    }
    cloud_msg.header.frame_id = "laser";

    cloud_msg.height = 16;

    int count = scan_msg.scan_time / scan_msg.time_increment;
    cloud_msg.width  = count;
    cloud_msg.points.resize(cloud_msg.width * cloud_msg.height);
  for(int j = 0; j < cloud_msg.height; j++) {
    for(int i = count*j; i < count+count*j; i++) {
        float degree = RAD2DEG(scan_msg.angle_min + scan_msg.angle_increment * (i-count*j));
        float k=j;
        if(scan_msg.ranges[(i-count*j)])
        {
            cloud_msg.points[i].x = scan_msg.ranges[(i-count*j)]*cos(DEG2RAD(degree));
            cloud_msg.points[i].y = scan_msg.ranges[(i-count*j)]*sin(DEG2RAD(degree));
            cloud_msg.points[i].z = k/10-0.8;
        }
        else
        {
            cloud_msg.points[i].x = 6*cos(DEG2RAD(degree));
            cloud_msg.points[i].y = 6*sin(DEG2RAD(degree));
            cloud_msg.points[i].z = k/10-0.8;
        }
        ROS_INFO(": [%f, %f]", degree, scan_msg.ranges[(i-count*j)]);
    }
}
    pub->publish(scan_msg);
    pcl_conversions::toPCL(ros::Time::now(), cloud_msg.header.stamp);
    cloud_pub->publish(cloud_msg);
}

bool getRPLIDARDeviceInfo(RPlidarDriver * drv)
{
    u_result     op_result;
    rplidar_response_device_info_t devinfo;

    op_result = drv->getDeviceInfo(devinfo);
    if (IS_FAIL(op_result)) {
        if (op_result == RESULT_OPERATION_TIMEOUT) {
            ROS_ERROR("Error, operation time out. RESULT_OPERATION_TIMEOUT! ");
        } else {
            ROS_ERROR("Error, unexpected error, code: %x",op_result);
        }
        return false;
    }

    // print out the device serial number, firmware and hardware version number..
    printf("RPLIDAR S/N: ");
    for (int pos = 0; pos < 16 ;++pos) {
        printf("%02X", devinfo.serialnum[pos]);
    }
    printf("\n");
    ROS_INFO("Firmware Ver: %d.%02d",devinfo.firmware_version>>8, devinfo.firmware_version & 0xFF);
    ROS_INFO("Hardware Rev: %d",(int)devinfo.hardware_version);
    return true;
}

bool checkRPLIDARHealth(RPlidarDriver * drv)
{
    u_result     op_result;
    rplidar_response_device_health_t healthinfo;

    op_result = drv->getHealth(healthinfo);
    if (IS_OK(op_result)) { 
        ROS_INFO("RPLidar health status : %d", healthinfo.status);
        if (healthinfo.status == RPLIDAR_STATUS_ERROR) {
            ROS_ERROR("Error, rplidar internal error detected. Please reboot the device to retry.");
            return false;
        } else {
            return true;
        }

    } else {
        ROS_ERROR("Error, cannot retrieve rplidar health code: %x", op_result);
        return false;
    }
}

bool stop_motor(std_srvs::Empty::Request &req,
                               std_srvs::Empty::Response &res)
{
  if(!drv)
       return false;

  ROS_DEBUG("Stop motor");
  drv->stop();
  drv->stopMotor();
  return true;
}

bool start_motor(std_srvs::Empty::Request &req,
                               std_srvs::Empty::Response &res)
{
  if(!drv)
       return false;
  ROS_DEBUG("Start motor");
  drv->startMotor();
  drv->startScan(0,1);
  return true;
}

int main(int argc, char * argv[]) {
    ros::init(argc, argv, "rplidar_node");

    std::string serial_port;
    int serial_baudrate = 115200;
    std::string frame_id;
    bool inverted = false;
    bool angle_compensate = true;
   
    float max_distance = 8.0;
    int angle_compensate_multiple = 1;//it stand of angle compensate at per 1 degree
    ros::NodeHandle nh;
    ros::Publisher scan_pub = nh.advertise<sensor_msgs::LaserScan>("scan", 1000);
    ros::Publisher cloud_pub = nh.advertise<PointCloud> ("point_cloud2", 1000);
    ros::NodeHandle nh_private("~");
    nh_private.param<std::string>("serial_port", serial_port, "/dev/ttyUSB0"); 
    nh_private.param<int>("serial_baudrate", serial_baudrate, 115200/*256000*/);//ros run for A1 A2, change to 256000 if A3
    nh_private.param<std::string>("frame_id", frame_id, "laser_frame");
    nh_private.param<bool>("inverted", inverted, false);
    nh_private.param<bool>("angle_compensate", angle_compensate, true);

    ROS_INFO("RPLIDAR running on ROS package rplidar_ros. SDK Version:"RPLIDAR_SDK_VERSION"");

    u_result     op_result;

    // create the driver instance
    drv = RPlidarDriver::CreateDriver(rp::standalone::rplidar::DRIVER_TYPE_SERIALPORT);
    
    if (!drv) {
        ROS_ERROR("Create Driver fail, exit");
        return -2;
    }

    // make connection...
    if (IS_FAIL(drv->connect(serial_port.c_str(), (_u32)serial_baudrate))) {
        ROS_ERROR("Error, cannot bind to the specified serial port %s.",serial_port.c_str());
        RPlidarDriver::DisposeDriver(drv);
        return -1;
    }

    // get rplidar device info
    if (!getRPLIDARDeviceInfo(drv)) {
        return -1;
    }

    // check health...
    if (!checkRPLIDARHealth(drv)) {
        RPlidarDriver::DisposeDriver(drv);
        return -1;
    }

    ros::ServiceServer stop_motor_service = nh.advertiseService("stop_motor", stop_motor);
    ros::ServiceServer start_motor_service = nh.advertiseService("start_motor", start_motor);

    drv->startMotor();
    RplidarScanMode current_scan_mode;
    op_result = drv->startScan(0,1,0, &current_scan_mode);
    if(op_result != RESULT_INVALID_DATA)
    {
        //default frequent is 10 hz (by motor pwm value),  current_scan_mode.us_per_sample is the number of scan point per us
        angle_compensate_multiple = (int)(1000*1000/current_scan_mode.us_per_sample/10.0/360.0);
        max_distance = current_scan_mode.max_distance;
        ROS_INFO("current scan mode: %s, max_distance: %.1f m, Point number: %.1fK ",  current_scan_mode.scan_mode,
                 current_scan_mode.max_distance, (1000/current_scan_mode.us_per_sample));
    }
    else
    {
        ROS_ERROR("Can not start scan: RESULT_INVALID_DATA!");
    }

    ros::Time start_scan_time;
    ros::Time end_scan_time;
    double scan_duration;
    while (ros::ok()) {
        rplidar_response_measurement_node_t nodes[360*8];
        size_t   count = _countof(nodes);

        start_scan_time = ros::Time::now();
        op_result = drv->grabScanData(nodes, count);
        end_scan_time = ros::Time::now();
        scan_duration = (end_scan_time - start_scan_time).toSec();

        if (op_result == RESULT_OK) {
            op_result = drv->ascendScanData(nodes, count);
            float angle_min = DEG2RAD(0.0f);
            float angle_max = DEG2RAD(359.0f);
            if (op_result == RESULT_OK) {
                if (angle_compensate) {
                    const int angle_compensate_multiple = 1;
                    const int angle_compensate_nodes_count = 360*angle_compensate_multiple;

                    int angle_compensate_offset = 0;
                    rplidar_response_measurement_node_t angle_compensate_nodes[angle_compensate_nodes_count];
                    memset(angle_compensate_nodes, 0, angle_compensate_nodes_count*sizeof(rplidar_response_measurement_node_t));

                    int i = 0, j = 0;
                    for( ; i < count; i++ ) {
                        if (nodes[i].distance_q2 != 0) {
                            float angle = (float)((nodes[i].angle_q6_checkbit >> RPLIDAR_RESP_MEASUREMENT_ANGLE_SHIFT)/64.0f);
                            int angle_value = (int)(angle * angle_compensate_multiple);
                            if ((angle_value - angle_compensate_offset) < 0) angle_compensate_offset = angle_value;
                            for (j = 0; j < angle_compensate_multiple; j++) {
                                angle_compensate_nodes[angle_value-angle_compensate_offset+j] = nodes[i];
                            }
                        }
                    }
  
                    publish_scan(&scan_pub, &cloud_pub,
                             angle_compensate_nodes, angle_compensate_nodes_count,
                             start_scan_time, scan_duration, inverted,
                             angle_min, angle_max, max_distance,
                             frame_id);
                } else {
                    int start_node = 0, end_node = 0;
                    int i = 0;
                    // find the first valid node and last valid node
                    while (nodes[i++].distance_q2 == 0);
                    start_node = i-1;
                    i = count -1;
                    while (nodes[i--].distance_q2 == 0);
                    end_node = i+1;

                    angle_min = DEG2RAD((float)(nodes[start_node].angle_q6_checkbit >> RPLIDAR_RESP_MEASUREMENT_ANGLE_SHIFT)/64.0f);
                    angle_max = DEG2RAD((float)(nodes[end_node].angle_q6_checkbit >> RPLIDAR_RESP_MEASUREMENT_ANGLE_SHIFT)/64.0f);

                    publish_scan(&scan_pub, &cloud_pub,&nodes[start_node], end_node-start_node +1,
                             start_scan_time, scan_duration, inverted,
                             angle_min, angle_max, max_distance,
                             frame_id);
               }
            } else if (op_result == RESULT_OPERATION_FAIL) {
                // All the data is invalid, just publish them
                float angle_min = DEG2RAD(0.0f);
                float angle_max = DEG2RAD(359.0f);

                publish_scan(&scan_pub, &cloud_pub,nodes, count,
                             start_scan_time, scan_duration, inverted,
                             angle_min, angle_max, max_distance,
                             frame_id);
            }
        }

        ros::spinOnce();
    }

    // done!
    drv->stop();
    drv->stopMotor();
    RPlidarDriver::DisposeDriver(drv);
    return 0;
}

测试

1.运行代码
roslaunch rplidar_ros view_rplidar.launch
rosrun rviz rviz
配置后可见
在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Rplidar A1使用并改为ROS中3D点云输出(PointCloud2) 的相关文章

  • 【STM32】HAL库开发教程(一)—基本使用

    前言 提示 xff1a 本系列本章针对STM32F207 xff0c 基于Cubemx和Keil进行程序开发 本系列文章并不是一步一操作的傻瓜式教程 xff0c 而更希望是一个向导 xff0c 引导读者去思考去开发 做为一个开发者应该是在思
  • 【STM32】HAL库开发教程(五)—RTC使用

    前言 不必害怕未知 xff0c 无需恐惧犯错 xff0c 做一个Creator xff01 一 RTC简介 STM32F2的实时时钟 RTC 是一个独立的BCD Binary Coded Decimal 定时器 计时器 xff0c 提供了一
  • 【STM32】HAL库开发教程(七)—SPI使用

    前言 不必害怕未知 xff0c 无需恐惧犯错 xff0c 做一个Creator xff01 本文主要介绍STM32 HAL库开发中SPI通信的使用 一 开发步骤 1 STM32CubeMX配置 在左侧引脚配置处勾选SPI进行配置在SPI模式
  • 【通信技术】信噪比及单位

    信噪比 xff1a 一个电子设备或者电子系统中信号与噪声的比例 计量单位 dB xff0c 其计算方法是10lg Ps Pn xff0c 其中Ps和Pn分别代表信号和噪声的有效功率 功率单位 xff1a dBm是一个考征功率绝对值的值 xf
  • 【C语言】字符串打印(定长)

    目的 xff1a 打印长度可控的字符串 char ucBuf uint8 t ucLen char ucString 256 memcpy ucString ucBuf ucLen ucString ucLen 61 39 0 39 pri
  • 【卫星】卫星通信基本概念与知识

    不必害怕未知 xff0c 无需恐惧犯错 xff0c 做一个Creator xff01 卫星通信基本概念与知识 上行链路 xff1a 从地球站发射信号到通信卫星所经过的通信路径成为上行链路 下行链路 xff1a 通信卫星将信号再转发到其他地球
  • 计算机基础笔记(三)—操作系统

    前言 不必害怕未知 xff0c 无需恐惧犯错 xff0c 做一个Creator xff01 目录 前言一 概述二 操作系统分类三 组成部分用户界面内存管理器进程管理进程同步设备管理文件管理 四 主流操作系统UNIXLinuxWindows
  • 计算机基础笔记(四)—数据结构

    前言 不必害怕未知 xff0c 无需恐惧犯错 xff0c 做一个Creator xff01 目录 前言数组链表栈 xff08 LIFO xff09 队列 xff08 FIFO xff09 广义线性表树图 定义 有特殊关系的数据的集合 xff
  • 计算机基础笔记(五)—数据库

    前言 不必害怕未知 xff0c 无需恐惧犯错 xff0c 做一个Creator xff01 目录 前言文件结构顺序文件索引文件散列文件目录 数据库数据库体系结构数据库模型数据库的设计其他数据库 文件结构 文件是数据记录的集合 xff0c 每
  • 陀螺仪数据处理(BMI088)

    1 BMI088惯性传感器介绍 1 1传感器原理图 传感器采用3 3V供电 xff0c 使用SPI IIC通讯模式 xff08 本文采用SPI通讯协议 xff09 1 2传感器功能介绍 注 xff1a 这里提到的数据读取频率 2000Hz是
  • FreeRTOS 多任务系统——任务切换、任务管理方式心得

    目前在进行对使用FreeRTOS的项目的代码升级 xff0c 之前采用的主逻辑任务切换模式 xff1a 由一个任务来进行逻辑上为串行的不同功能切换 xff0c 其他任务分别负责通信实时传输 传感器检测和电机控制 xff0c 系统中断中采用变
  • 13.C工程与寄存器封装

    文章目录 启动代码分析使用C语言点灯封装代码寄存器操作的标准化 启动代码分析 text global start start Vector table xff1a 占用异常向量表空间 xff0c 让它不再能被其它代码占用 b reset b
  • 授权(authorization)的设计思路

    本文对授权 authorization 的设计思路 客户端必须得到用户的授权 authorization grant xff0c 才能获得令牌 token 授权码模式 xff08 authorization code xff09 grant
  • Ubuntu18.04下安装ROS步骤及遇到的错误集锦(尤其是rosdep update报错)

    1 首先设置软件源 xff08 任选其一使用 xff09 1 xff09 国外的软件源 xff08 速度慢 xff09 sudo sh span class token operator span c span class token st
  • C语言中的 __FILE__ __LINE__ #line

    C语言中的 FILE 用以指示本行语句所在源文件的文件名 例 xff1a a c include lt stdio h gt int main printf 34 s n 34 FILE 在gcc编译生成a out xff0c 执行后输出结
  • ROS入门(一)安装并配置ROS环境

    1 安装ROS 在学习这些教程之前先按照 lt lt 在ubuntu中安装ROS kinetic gt gt 这篇博客 完成安装 注意 如果你是使用类似apt这样的软件管理器来安装ROS的 xff0c 那么安装后这些软件包将不具备写入权限
  • C语言带参#define个人理解

    之前接触带参 define比较少 xff0c 这几天 查阅stm32官方固件库 xff0c 看到以下代码有点懵 xff1a define IS GPIO ALL PERIPH PERIPH PERIPH 61 61 GPIOA PERIPH
  • Ubuntu学习笔记2-ROS安装及配置

    Ubuntu学习笔记1 ROS安装及配置 前期准备 内容参考大佬赵虚左的视频及文献 xff0c 此博客仅作记录防止忘记用 在Ubuntu虚拟机中安装ROS并使用Vscode开发ROS程序 xff0c 环境如下 xff1a Ubuntu版本
  • DDR模式寄存器

    mode register 模式寄存器 MR0 MR3 用于定义DDR3sdram的各种可编程操作模式 在初始化过程中 xff0c 模式寄存器通过模式寄存器设置 MRS 命令进行编程 xff0c 并保留存储的信息 MR0 8 除外 xff0
  • 什么是迭代器

    迭代器是一种设计模式 xff0c 它是一个对象 xff0c 他可以遍历并且选择序列中的一个对象 xff0c 是开发人员可以忽视这个序列中的底层结构 迭代器被称为轻量级的对象 xff0c 因为它创建的代价是非常小的Java中的Iterator

随机推荐

  • ARM_C高级学习笔记(六)大端模式和小端模式

    文章目录 xff08 一 xff09 什么是大小端模式 xff08 二 xff09 怎么测试大小端模式1 用union来测试机器的大小端模式2 用指针来测试机器的大小端模式 xff08 四 xff09 看似可行实则不行的测试大小端方式 xf
  • VS2019利用Curl库实现HTTP网络通信(C++)

    C 43 43 实现HTTP网络通信 xff0c 一般采用两种方式 xff0c 熟悉TCP协议的大哥可能不需要查这方面的知识 xff1b 还有一种方式就是使用第三方库 xff0c Qt环境下可以用QNetworkRequest实现很方便 x
  • 在windows配置 cygwin 和 gcc 

    1 install cygwin https www cygwin com 2 copy the setup exe under cygwin64 folder and run C cygwin64 gt setup x86 64 exe
  • VMware虚拟机Ubuntu22.04忽然不能上网

    问题描述 原本正常使用的虚拟机Ubuntu22 04忽然之间不能正常上网了 xff0c 右上角的网络连接标志也不见了 尝试删除网络适配器 xff0c 并重新添加网络适配器 不能解决 尝试windows下配置网络 原来正常上网 xff0c w
  • GIT 基于TAG拉取分支

    git 基于tag拉branch 获得最新 span class token function git span origin fetch 从tag创建新的分支 span class token function git span bran
  • 栈的作用

    栈 栈 xff08 stack xff09 又名堆栈 xff0c 它是一种运算受限的线性表 其限制是仅允许在表的一端进行插入和删除运算 这一端被称为栈顶 xff0c 相对地 xff0c 把另一端称为栈底 向一个栈插入新元素又称作进栈 入栈或
  • C++中vector的用法详解

    vector 向量 C 43 43 中的一种数据结构 确切的说是一个类 它相当于一个动态的数组 当程序员无法知道自己需要的数组的规模多大时 用其来解决问题可以达到最大节约空间的目的 用法 1 文件包含 首先在程序开头处加上 include
  • ImportError: libQtGui.so.4: cannot open shared object file: No such file or directory

    报错 xff1a File home sx125 anaconda3 envs pytorch lib python3 7 site packages cv2 init py line 3 in from cv2 import Import
  • 批量更改YOLO标签类别

    原本的标签的classes txt文件中person类别是1 即第二行才是person类 xff0c 而后来找到的数据集大且标注好了 xff0c 好巧不巧person类别是0 故要将labels文件的类别都改成0 要自己先创建好空的文件夹存
  • 【CMake】编译和链接静态库和动态库

    项目结构工作原理 配置项目编译库 项目结构 span class token builtin class name span include myClass h src CMakeLists txt myClass cpp CMakeLis
  • 字符串比较大小

    1 规则 1 如果 字符串1的第n位的ASCII码值 等于 字符串2的第n位的ASCII码值 则 继续比较下一位 2 如果 字符串1的第n位的ASCII码值 大于 字符串2的第n位的ASCII码值 则 输出结果 1 表示字符串1 gt 字符
  • 将本地jar添加到Maven本地仓库

    在Maven项目中 xff0c 如果需要引入自己的jar包 xff0c 需要将jar添加到本地Maven仓库 方法一 xff1a 假设将包htmlparser jar放入了项目下的lib目录中 xff1a gt project lib ht
  • UART的奇偶校验

    1 奇校验 当数据位中 1 的个数为奇数时 xff0c 校验位为 0 xff0c 否则为 1 2 偶校验 当数据位中 1 的个数为偶数时 xff0c 校验位为 0 xff0c 否则为 1
  • windows 关闭占用端口的进程

    1 netstat ano findstr yourPortNumber 2 taskkill PID typeyourPIDhere F
  • Linux TCP server/client例程

    1 服务器端 span class token macro property span class token directive hash span span class token directive keyword include s
  • Nvidia Jetson 平台 DeepStream-6.0.1 部署 YoloV5-6.0 实现目标检测

    项目介绍 xff1a 在 Jetson 平台上利用 DeepStream 处理多路视频源 xff0c 并实现自己训练的 YoloV5 模型的部署 文章目录 前言1 YoloV5 模型训练自己的数据集1 1 建立自己的数据集1 1 1 开始之
  • 软路由保姆级入门教程 一篇看懂软路由

    前言 amp nbsp amp nbsp 玩张大妈也一年多了 xff0c 软路由改装 刷机文章写了不少 xff0c 很早就打算写篇软路由入门文章 xff0c 但是一直没落实 xff0c 原因有二 xff1a 圈子里大佬众多 xff0c 基础
  • CMake入门02-CMake中的静态库

    CMake中的静态库 静态库 文件树 CMakeLists txt include static Hello h src Hello cpp main cpp 1 1 Hello h 声明了Hello类 xff0c Hello的方法是pri
  • C++:struct与class的区别

    xff08 1 xff09 C语言中struct与class的区别 xff1a a struct只作为一种复杂数据类型定义的结构体 xff0c 不能用于面向对象编程 xff1b b C语言没有class关键字 xff08 2 xff09 C
  • Rplidar A1使用并改为ROS中3D点云输出(PointCloud2)

    这里写自定义目录标题 Rplidar A1使用并改为ROS中3D点云输出Rplidar安装测试修改后完整代码测试 Rplidar A1使用并改为ROS中3D点云输出 3D激光雷达价格不菲 xff0c 在研究过程中 xff0c 可以尝试将2D