-
Notifications
You must be signed in to change notification settings - Fork 240
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
a2f19ff
commit d8d402d
Showing
2 changed files
with
368 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
365 changes: 365 additions & 0 deletions
365
doc/tutorials/writing_lidar_network_adapter_tutorial_c++.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,365 @@ | ||
# WritingLidarNetworkAdapterTutorial(c++) | ||
Description: This tutorial covers how to write a lidar network adapter tutorial in C++. | ||
Tutorial Level: BEGINNER | ||
Next Tutorial: [Examining the simple lidar tutorial](examine_the_simple_lidar_tutorial.md) | ||
|
||
## Table of Contents | ||
|
||
- [Writing a Simple lidar tutorial (C++)](#writing-a-simple-lidar-tutorial-(C++)) | ||
- [create beginner_tutorials directories](#create-beginner_tutorials-directories) | ||
- [The Code Explained](#the-code-explained) | ||
- [Building your project](#building-your-project) | ||
|
||
## Writing a Simple lidar tutorial (C++) | ||
Description: This tutorial covers how to write a LiDAR network adapter data console program in C++. | ||
Tutorial Level: BEGINNER | ||
|
||
### create beginner_tutorials directories | ||
```shell | ||
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/cpp_tutorials/lidar_tutorial/lidar_tutorial.cpp](https://github.com/YDLIDAR/ydlidar_tutorials/blob/master/cpp_tutorials/lidar_tutorial/lidar_tutorial.cpp) | ||
|
||
```c++ | ||
#include "CYdLidar.h" | ||
#include <string> | ||
using namespace std; | ||
using namespace ydlidar; | ||
|
||
#if defined(_MSC_VER) | ||
#pragma comment(lib, "ydlidar_sdk.lib") | ||
#endif | ||
|
||
int main(int argc, char *argv[]) { | ||
// init system signal | ||
ydlidar::os_init(); | ||
|
||
CYdLidar laser; | ||
//////////////////////string property///////////////// | ||
/// Lidar ports | ||
std::string port = "192.168.31.200; | ||
/// lidar port | ||
laser.setlidaropt(LidarPropSerialPort, port.c_str(), port.size()); | ||
/// ignore array | ||
std::string ignore_array; | ||
ignore_array.clear(); | ||
laser.setlidaropt(LidarPropIgnoreArray, ignore_array.c_str(), | ||
ignore_array.size()); | ||
|
||
//////////////////////int property///////////////// | ||
/// lidar port | ||
int optval = 8000; | ||
laser.setlidaropt(LidarPropSerialBaudrate, &optval, sizeof(int)); | ||
/// tof lidar | ||
optval = TYPE_TRIANGLE; | ||
laser.setlidaropt(LidarPropLidarType, &optval, sizeof(int)); | ||
/// device type | ||
optval = YDLIDAR_TYPE_TCP; | ||
laser.setlidaropt(LidarPropDeviceType, &optval, sizeof(int)); | ||
/// sample rate | ||
optval = 9; | ||
laser.setlidaropt(LidarPropSampleRate, &optval, sizeof(int)); | ||
/// abnormal count | ||
optval = 4; | ||
laser.setlidaropt(LidarPropAbnormalCheckCount, &optval, sizeof(int)); | ||
|
||
//////////////////////bool property///////////////// | ||
/// fixed angle resolution | ||
bool b_optvalue = false; | ||
laser.setlidaropt(LidarPropFixedResolution, &b_optvalue, sizeof(bool)); | ||
/// rotate 180 | ||
laser.setlidaropt(LidarPropReversion, &b_optvalue, sizeof(bool)); | ||
/// Counterclockwise | ||
laser.setlidaropt(LidarPropInverted, &b_optvalue, sizeof(bool)); | ||
b_optvalue = true; | ||
laser.setlidaropt(LidarPropAutoReconnect, &b_optvalue, sizeof(bool)); | ||
/// one-way communication | ||
b_optvalue = false; | ||
laser.setlidaropt(LidarPropSingleChannel, &b_optvalue, sizeof(bool)); | ||
/// intensity | ||
b_optvalue = false; | ||
laser.setlidaropt(LidarPropIntenstiy, &b_optvalue, sizeof(bool)); | ||
/// Motor DTR | ||
b_optvalue = false; | ||
laser.setlidaropt(LidarPropSupportMotorDtrCtrl, &b_optvalue, sizeof(bool)); | ||
|
||
//////////////////////float property///////////////// | ||
/// unit: ° | ||
float f_optvalue = 180.0f; | ||
laser.setlidaropt(LidarPropMaxAngle, &f_optvalue, sizeof(float)); | ||
f_optvalue = -180.0f; | ||
laser.setlidaropt(LidarPropMinAngle, &f_optvalue, sizeof(float)); | ||
/// unit: m | ||
f_optvalue = 16.f; | ||
laser.setlidaropt(LidarPropMaxRange, &f_optvalue, sizeof(float)); | ||
f_optvalue = 0.1f; | ||
laser.setlidaropt(LidarPropMinRange, &f_optvalue, sizeof(float)); | ||
/// unit: Hz | ||
f_optvalue = 10.f; | ||
laser.setlidaropt(LidarPropScanFrequency, &f_optvalue, sizeof(float)); | ||
|
||
// initialize SDK and LiDAR | ||
bool ret = laser.initialize(); | ||
if (ret) {//success | ||
//Start the device scanning routine which runs on a separate thread and enable motor. | ||
ret = laser.turnOn(); | ||
} else { | ||
fprintf(stderr, "%s\n", laser.DescribeError()); | ||
fflush(stderr); | ||
} | ||
|
||
// Turn On success and loop | ||
while (ret && ydlidar::os_isOk()) { | ||
LaserScan scan; | ||
if (laser.doProcessSimple(scan)) { | ||
fprintf(stdout, "Scan received[%llu]: %u ranges is [%f]Hz\n", | ||
scan.stamp, | ||
(unsigned int)scan.points.size(), 1.0 / scan.config.scan_time); | ||
fflush(stdout); | ||
} else { | ||
fprintf(stderr, "Failed to get Lidar Data\n"); | ||
fflush(stderr); | ||
} | ||
} | ||
// Stop the device scanning thread and disable motor. | ||
laser.turnOff(); | ||
// Uninitialize the SDK and Disconnect the LiDAR. | ||
laser.disconnecting(); | ||
return 0; | ||
} | ||
``` | ||
Note: The difference form the serial port is the following three properties | ||
* LidarPropSerialPort | ||
* LidarPropSerialBaudrate | ||
* LidarPropDeviceType | ||
When the network adapter board is connected to the lidar, `LidarPropSerialPort` is the lidar IP address and `LidarPropSerialBaudrate` is the lidar network port. | ||
The device type `LidarPropDeviceType` value is changed from the `YDLIDAR_TYPE_SERIAL` to `YDLIDAR_TYPE_TCP`. | ||
### The Code Explained | ||
Now, let's break the code down. | ||
```c++ | ||
#include "CYdLidar.h" | ||
``` | ||
CYdLidar.h is a convenience include that includes all the headers necessary to use the most common public pieces of the YDLIDAR SDK. | ||
|
||
```c++ | ||
ydlidar::os_init(); | ||
``` | ||
Initialize system signal. install a SIGINT handler which provides Ctrl-C handling | ||
|
||
```c++ | ||
CYdLidar laser; | ||
``` | ||
Create a handle to this Lidar. | ||
|
||
```c++ | ||
//////////////////////string property///////////////// | ||
/// Lidar ports | ||
std::string port = "192.168.31.200"; | ||
``` | ||
Query avaliable Lidar IP . | ||
|
||
|
||
```c++ | ||
/// lidar port | ||
laser.setlidaropt(LidarPropSerialPort, port.c_str(), port.size()); | ||
/// ignore array | ||
std::string ignore_array; | ||
ignore_array.clear(); | ||
laser.setlidaropt(LidarPropIgnoreArray, ignore_array.c_str(), | ||
ignore_array.size()); | ||
``` | ||
Set Lidar string property paramters. | ||
|
||
```c++ | ||
//////////////////////int property///////////////// | ||
/// lidar port | ||
int optval = 8000; | ||
laser.setlidaropt(LidarPropSerialBaudrate, &optval, sizeof(int)); | ||
/// tof lidar | ||
optval = TYPE_TRIANGLE; | ||
laser.setlidaropt(LidarPropLidarType, &optval, sizeof(int)); | ||
/// device type | ||
optval = YDLIDAR_TYPE_TCP; | ||
laser.setlidaropt(LidarPropDeviceType, &optval, sizeof(int)); | ||
/// sample rate | ||
optval = 9; | ||
laser.setlidaropt(LidarPropSampleRate, &optval, sizeof(int)); | ||
/// abnormal count | ||
optval = 4; | ||
laser.setlidaropt(LidarPropAbnormalCheckCount, &optval, sizeof(int)); | ||
|
||
``` | ||
Set Lidar string int paramters. | ||
|
||
|
||
```c++ | ||
//////////////////////bool property///////////////// | ||
/// fixed angle resolution | ||
bool b_optvalue = false; | ||
laser.setlidaropt(LidarPropFixedResolution, &b_optvalue, sizeof(bool)); | ||
/// rotate 180 | ||
laser.setlidaropt(LidarPropReversion, &b_optvalue, sizeof(bool)); | ||
/// Counterclockwise | ||
laser.setlidaropt(LidarPropInverted, &b_optvalue, sizeof(bool)); | ||
b_optvalue = true; | ||
laser.setlidaropt(LidarPropAutoReconnect, &b_optvalue, sizeof(bool)); | ||
/// one-way communication | ||
b_optvalue = false; | ||
laser.setlidaropt(LidarPropSingleChannel, &b_optvalue, sizeof(bool)); | ||
/// intensity | ||
b_optvalue = false; | ||
laser.setlidaropt(LidarPropIntenstiy, &b_optvalue, sizeof(bool)); | ||
/// Motor DTR | ||
b_optvalue = false; | ||
laser.setlidaropt(LidarPropSupportMotorDtrCtrl, &b_optvalue, sizeof(bool)); | ||
|
||
``` | ||
Set Lidar bool property paramters. | ||
|
||
|
||
```c++ | ||
//////////////////////float property///////////////// | ||
/// unit: ° | ||
float f_optvalue = 180.0f; | ||
laser.setlidaropt(LidarPropMaxAngle, &f_optvalue, sizeof(float)); | ||
f_optvalue = -180.0f; | ||
laser.setlidaropt(LidarPropMinAngle, &f_optvalue, sizeof(float)); | ||
/// unit: m | ||
f_optvalue = 16.f; | ||
laser.setlidaropt(LidarPropMaxRange, &f_optvalue, sizeof(float)); | ||
f_optvalue = 0.1f; | ||
laser.setlidaropt(LidarPropMinRange, &f_optvalue, sizeof(float)); | ||
/// unit: Hz | ||
f_optvalue = 10.f; | ||
laser.setlidaropt(LidarPropScanFrequency, &f_optvalue, sizeof(float)); | ||
``` | ||
Set Lidar float property paramters. | ||
|
||
```c++ | ||
// initialize SDK and LiDAR | ||
bool ret = laser.initialize(); | ||
``` | ||
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. | ||
|
||
```c++ | ||
if (ret) {//success | ||
//Start the device scanning routine which runs on a separate thread and enable motor. | ||
ret = laser.turnOn(); | ||
} else { | ||
fprintf(stderr, "%s\n", laser.DescribeError()); | ||
fflush(stderr); | ||
} | ||
``` | ||
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. | ||
```c++ | ||
// Turn On success and loop | ||
while (ret && ydlidar::os_isOk()) { | ||
``` | ||
By `ydlidar::os_init()` will install a SIGINT handler which provides Ctrl-C handling which will cause `ydlidar::os_isOk()` to return false if that happens. | ||
|
||
`ydlidar::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 `ydlidar::os_isOk()` returns false, Loop exit. | ||
|
||
```c++ | ||
LaserScan scan; | ||
if (laser.doProcessSimple(scan)) { | ||
fprintf(stdout, "Scan received[%llu]: %u ranges is [%f]Hz\n", | ||
scan.stamp, | ||
(unsigned int)scan.points.size(), 1.0 / scan.config.scan_time); | ||
fflush(stdout); | ||
} else { | ||
fprintf(stderr, "Failed to get Lidar Data\n"); | ||
fflush(stderr); | ||
} | ||
``` | ||
Get the LiDAR Scan Data. | ||
```c++ | ||
// Stop the device scanning thread and disable motor. | ||
laser.turnOff(); | ||
``` | ||
Stop the device scanning thread and disable motor. | ||
|
||
```c++ | ||
// Uninitialize the SDK and Disconnect the LiDAR. | ||
laser.disconnecting(); | ||
``` | ||
Uninitialize the SDK and Disconnect the LiDAR. | ||
|
||
## Building your project | ||
You need to create a CMakeLists.txt file. | ||
|
||
The generated CMakeLists.txt should look like this: | ||
[https://github.com/YDLIDAR/ydlidar_tutorials/blob/master/cpp_tutorials/lidar_tutorial/CMakeLists.txt](https://github.com/YDLIDAR/ydlidar_tutorials/blob/master/cpp_tutorials/lidar_tutorial/CMakeLists.txt) | ||
|
||
```cmake | ||
cmake_minimum_required(VERSION 2.8) | ||
PROJECT(lidar_tutorial) | ||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") | ||
add_definitions(-std=c++11) # Use C++11 | ||
#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.cpp) | ||
#Link your project to ydlidar_sdk library. | ||
target_link_libraries(${PROJECT_NAME} ${YDLIDAR_SDK_LIBRARIES}) | ||
############## YDLIDAR SDK END##################################### | ||
``` | ||
This will create one executable, lidar_tutorial, which by default will go into package directory of your build space. | ||
|
||
Linux: | ||
* `YDLIDAR_SDK_LIBRARIES` includes `ydlidar_sdk pthread rt` | ||
* If you need the pthread library at the end of the compilation flag, | ||
you need to put `YDLIDAR_SDK_LIBRARIES` at the end. | ||
|
||
|
||
you can use the following variable to depend on all necessary targets: | ||
|
||
```cmake | ||
target_link_libraries(${PROJECT_NAME} ${YDLIDAR_SDK_LIBRARIES}) | ||
``` | ||
Now run cmake: | ||
```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](examine_the_simple_lidar_tutorial.md). |