Description: This tutorial covers how to write a lidar tutorial in C. Tutorial Level: BEGINNER Next Tutorial: Examining the simple lidar tutorial
Description: This tutorial covers how to write a LiDAR data console program in C. Tutorial Level: BEGINNER
mkdir beginner_tutorials
cd beginner_tutorials
Create the lidar_tutorial.cpp file within the beginner_tutorials project and paste the following inside it:
https://github.com/YDLIDAR/ydlidar_tutorials/blob/master/c_tutorials/lidar_tutorial/lidar_tutorial.c
//
// The MIT License (MIT)
//
// Copyright (c) 2019 EAIBOT. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef WIN32
#include <windows.h>
#else
#include <unistd.h>
#endif
#include "ydlidar_sdk.h"
#if defined(_MSC_VER)
#pragma comment(lib, "ydlidar_sdk.lib")
#endif
int main(int argc, const char *argv[]) {
os_init();
YDLidar *laser = lidarCreate();
//string prop
char port[50] = "/dev/ydlidar";
LidarPort ports;
int size = lidarPortList(&ports);
int i = 0;
for(i =0; i < size; i++) {
printf("port: %s\n", ports.port[i].data);
/// last port
strcpy(port, ports.port[i].data);
}
setlidaropt(laser, LidarPropSerialPort, port, sizeof(port));
strcpy(port, "");
setlidaropt(laser, LidarPropIgnoreArray,port, sizeof(port));
//int prop
int i_optvalue = 512000;
setlidaropt(laser, LidarPropSerialBaudrate, &i_optvalue, sizeof(int));
i_optvalue = TYPE_TOF;
setlidaropt(laser, LidarPropLidarType, &i_optvalue, sizeof(int));
i_optvalue = YDLIDAR_TYPE_SERIAL;
setlidaropt(laser, LidarPropDeviceType, &i_optvalue, sizeof(int));
i_optvalue = 20;
setlidaropt(laser, LidarPropSampleRate, &i_optvalue, sizeof(int));
//bool prop
bool b_optval = true;
setlidaropt(laser, LidarPropAutoReconnect, &b_optval, sizeof(bool));
b_optval = false;
setlidaropt(laser, LidarPropSingleChannel, &b_optval, sizeof(bool));
setlidaropt(laser, LidarPropIntenstiy, &b_optval, sizeof(bool));
setlidaropt(laser, LidarPropInverted, &b_optval, sizeof(bool));
setlidaropt(laser, LidarPropReversion, &b_optval, sizeof(bool));
setlidaropt(laser, LidarPropSupportMotorDtrCtrl, &b_optval, sizeof(bool));
setlidaropt(laser, LidarPropFixedResolution, &b_optval, sizeof(bool));
//float prop
float f_optval = 10.f;
setlidaropt(laser, LidarPropScanFrequency, &f_optval, sizeof(float));
f_optval = 180.0f;
setlidaropt(laser, LidarPropMaxAngle, &f_optval, sizeof(float));
f_optval = -180.0f;
setlidaropt(laser, LidarPropMinAngle, &f_optval, sizeof(float));
f_optval = 64.f;
setlidaropt(laser, LidarPropMaxRange, &f_optval, sizeof(float));
f_optval = 0.05f;
setlidaropt(laser, LidarPropMinRange, &f_optval, sizeof(float));
getlidaropt(laser, LidarPropSerialBaudrate,&i_optvalue, sizeof(int));
printf("baudrate: %d\n", i_optvalue);
bool ret = initialize(laser);
if(ret) {
ret = turnOn(laser);
}
LaserFan scan;
LaserFanInit(&scan);
while (ret && os_isOk()) {
if(doProcessSimple(laser, &scan)) {
fprintf(stdout, "Scan received[%llu]: %u ranges is [%f]Hz\n",
scan.stamp,
(unsigned int)scan.npoints, 1.0 / scan.config.scan_time);
fflush(stdout);
} else {
fprintf(stderr, "Failed to get Lidar Data\n");
fflush(stderr);
}
}
LaserFanDestroy(&scan);
turnOff(laser);
disconnecting(laser);
lidarDestroy(&laser);
return 0;
}
Now, let's break the code down.
#include "ydlidar_sdk.h"
ydlidar_sdk.h is a convenience include that includes all the headers necessary to use the most common public pieces of the YDLIDAR SDK.
os_init();
Initialize system signal. install a SIGINT handler which provides Ctrl-C handling
YDLidar *laser = lidarCreate();
Create a handle to this Lidar.
//string prop
char port[50] = "/dev/ydlidar";
LidarPort ports;
int size = lidarPortList(&ports);
int i = 0;
for(i =0; i < size; i++) {
printf("port: %s\n", ports.port[i].data);
/// last port
strcpy(port, ports.port[i].data);
}
Query avaliable Lidar ports.
setlidaropt(laser, LidarPropSerialPort, port, sizeof(port));
strcpy(port, "");
setlidaropt(laser, LidarPropIgnoreArray,port, sizeof(port));
Set Lidar string property paramters.
//int prop
int i_optvalue = 512000;
setlidaropt(laser, LidarPropSerialBaudrate, &i_optvalue, sizeof(int));
i_optvalue = TYPE_TOF;
setlidaropt(laser, LidarPropLidarType, &i_optvalue, sizeof(int));
i_optvalue = YDLIDAR_TYPE_SERIAL;
setlidaropt(laser, LidarPropDeviceType, &i_optvalue, sizeof(int));
i_optvalue = 20;
setlidaropt(laser, LidarPropSampleRate, &i_optvalue, sizeof(int));
Set Lidar string int paramters.
//bool prop
bool b_optval = true;
setlidaropt(laser, LidarPropAutoReconnect, &b_optval, sizeof(bool));
b_optval = false;
setlidaropt(laser, LidarPropSingleChannel, &b_optval, sizeof(bool));
setlidaropt(laser, LidarPropIntenstiy, &b_optval, sizeof(bool));
setlidaropt(laser, LidarPropInverted, &b_optval, sizeof(bool));
setlidaropt(laser, LidarPropReversion, &b_optval, sizeof(bool));
setlidaropt(laser, LidarPropSupportMotorDtrCtrl, &b_optval, sizeof(bool));
setlidaropt(laser, LidarPropFixedResolution, &b_optval, sizeof(bool));
Set Lidar bool property paramters.
//float prop
float f_optval = 10.f;
setlidaropt(laser, LidarPropScanFrequency, &f_optval, sizeof(float));
f_optval = 180.0f;
setlidaropt(laser, LidarPropMaxAngle, &f_optval, sizeof(float));
f_optval = -180.0f;
setlidaropt(laser, LidarPropMinAngle, &f_optval, sizeof(float));
f_optval = 64.f;
setlidaropt(laser, LidarPropMaxRange, &f_optval, sizeof(float));
f_optval = 0.05f;
setlidaropt(laser, LidarPropMinRange, &f_optval, sizeof(float));
Set Lidar float property paramters.
// initialize SDK and LiDAR
bool ret = initialize(laser);
Initialize the SDK and LiDAR.
initialize
will return false if:
- Serial port does not correspond to the actual Lidar.
- Serial port does not have read and write permissions.
- Lidar baud rate settings error.
- Incorrect Lidar type setting.
if(ret) {
ret = turnOn(laser);
}
Start the device scanning routine which runs on a separate thread and enable motor.
turnOn
will return false if:
- Lidar stall.
- Lidar power suppy is unstable.
// Turn On success and loop
LaserFan scan;
LaserFanInit(&scan);
while (ret && os_isOk()) {
By os_init()
will install a SIGINT handler which provides Ctrl-C handling which will cause os_isOk()
to return false if that happens.
os_isOk()
will return false if:
- a SIGINT is received (Ctrl-C)
- ydlidar::os_shutdown() has been called by another part of the application.
Once os_isOk()
returns false, Loop exit.
Note:
LaserFan
need to be initialized withLaserFanInit
- After
LaserFan
leaves the Scope, it need to be destroyed withLaserFanDestroy
, otherwisw it will leak memory.
if(doProcessSimple(laser, &scan)) {
fprintf(stdout, "Scan received[%llu]: %u ranges is [%f]Hz\n",
scan.stamp,
(unsigned int)scan.npoints, 1.0 / scan.config.scan_time);
fflush(stdout);
} else {
fprintf(stderr, "Failed to get Lidar Data\n");
fflush(stderr);
}
Get the LiDAR Scan Data.
LaserFanDestroy(&scan);
Destroy LaserFan, Free up memory. Note:
- After
LaserFan
leaves the Scope, it need to be destroyed withLaserFanDestroy
, otherwisw it will leak memory.
// Stop the device scanning thread and disable motor.
turnOff(laser);
Stop the device scanning thread and disable motor.
// Uninitialize the SDK and Disconnect the LiDAR.
disconnecting(laser);
Uninitialize the SDK and Disconnect the LiDAR.
lidarDestroy(&laser);
Destroy YDLidar, Free up memory.
You need to create a CMakeLists.txt file.
The generated CMakeLists.txt should look like this: https://github.com/YDLIDAR/ydlidar_tutorials/blob/master/c_tutorials/lidar_tutorial/CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
PROJECT(lidar_tutorial C)
#Include directories
include_directories(
${CMAKE_SOURCE_DIR}
)
############## YDLIDAR SDK START#####################################
#find ydlidar_sdk package
find_package(ydlidar_sdk REQUIRED)
#Include directories
include_directories(
${YDLIDAR_SDK_INCLUDE_DIRS}
)
#link library directories
link_directories(${YDLIDAR_SDK_LIBRARY_DIRS})
add_executable(${PROJECT_NAME} lidar_tutorial.c)
#Link your project to ydlidar_sdk library.
target_link_libraries(${PROJECT_NAME} ${YDLIDAR_SDK_LIBRARIES} -lstdc++ -lm)
############## YDLIDAR SDK END#####################################
This will create one executable, lidar_tutorial, which by default will go into package directory of your build space.
ydlidar_sdk dependent libraries
- C++ standard library.
- math library.
Note:
- GCC CCLDFLAGS requires "-lstdc++ -lm".
you can use the following variable to depend on all necessary targets:
target_link_libraries(${PROJECT_NAME} ${YDLIDAR_SDK_LIBRARIES} -lstdc++ -lm)
Now run cmake:
# In your project directory
mkdir build
cd build
cmake ..
make j4
Now that you have written a simple lidar tutorial, let's examine the simple lidar tutorial.