lrfultisenseparser_web_logo

LrfUltisenseParser C++ library

v1.0.1

Table of contents

Overview

The LrfUltisenseParser C++ library is designed for encoding control commands and decoding responses for Safran Laser Range Finders. The library provides simple interface and doesn’t have third party dependencies to be installed in OS. It uses C++17 standard. Also, the library provides test application to check communication with the LRF via serial ports. Test application depends on SerialPort library (provides methods to work with serial ports, source code included, Apache 2.0 license).

Versions

Table 1 - Library versions.

Version Release date What’s new
1.0.0 30.07.2024 - First version.
1.0.1 27.09.2024 - Fixed decoding distance reply.

Library files

The library is supplied only by source code. The user is given a set of files in the form of a CMake project (repository). The repository structure is shown below:

CMakeLists.txt ---------------------- Main CMake file of the library.
src  -------------------------------- Folder with library source code.
    CMakeLists.txt ------------------ CMake file of the library.
    LrfUltisenseParser.h ------------ Main library header file.
    LrfUltisenseParserVersion.h ----- Header file with library version.
    LrfUltisenseParserVersion.h.in -- CMake service file to generate version header.
    LrfUltisenseParser.cpp ---------- C++ implementation file.
test -------------------------------- Folder for test application files.
    3rdparty ------------------------ Folder with third-party libraries.
        CMakeLists.txt -------------- CMake file to include third-party libraries.
        SerialPort ------------------ Folder with SerialPort library source code.
    CMakeLists.txt ------------------ CMake file for test application.
    main.cpp ------------------------ Source C++ file of test application.

LrfUltisenseParser class description

LrfUltisenseParser class declaration

namespace cr
{
namespace lrf
{
class LrfUltisenseParser
{
public:

    /// Get library version.
    static std::string getVersion();

    /// Encode command.
    bool getCommand(uint8_t* data, int& size, LrfUltisenseCommand id, int arg = 0);

    /// Decode response byte-by-byte.
    LrfUltisenseResponse decodeResponse(uint8_t nextByte);

    /// Get current distance.
    float getDistance();
};
}
}

getVersion method

The getVersion() static method returns string of current LrfUltisenseParser class version. Method declaration:

static std::string getVersion();

Method can be used without LrfUltisenseParser class instance:

cout << "LrfUltisenseParser version: " << LrfUltisenseParser::getVersion();

Console output:

LrfUltisenseParser version: 1.0.1

getCommand method

The getCommand(…) method encodes (prepares data) control command for range finder. The Ultisense range finder does not send data on its own, but only responds to commands. Method declaration:

bool getCommand(uint8_t* data, int& size, LrfUltisenseCommand id, int arg = 0);
Parameter Value
data Pointer to buffer for encoded data (command). Buffer must have size >= 64.
size Size of encoded command.
id Command ID according to LrfUltisenseCommand enum.
arg Command argument. The value depends on command ID (see LrfUltisenseCommand enum). Some commands don’t have arguments.

Returns: TRUE if commands encoded or FALSE if not (not valid ID or not valid parameters).

Example of encoding command:

// Encode command.
cr::lrf::LrfUltisenseParser parser;
uint8_t command[64];
int size = 0;
parser.getCommand(command, size, LrfUltisenseCommand::MEASURE_DISTANCE);

// Send command via serial port (pseudo code).
serialPort.write(command, size);

decodeResponse method

The decodeResponse(…) method decodes response from range finder. Once the data from the serial port has been read the user must pass it to the method byte-by-byte (each byte separately in sequence). The library has an internal ring buffer. When the user passes another byte, the library shifts the ring buffer by one byte and copies the new byte to the end of the buffer. If the library detects a valid response in the ring buffer, it returns the response ID (see LrfUltisenseResponse enum description) and returns the response arguments. In all other cases, the library returns a NONE identifier. Method declaration:

LrfUltisenseResponse decodeResponse(uint8_t nextByte);
Parameter Value
nextByte Next read byte from serial port.

Returns: LrfUltisenseResponse (response ID) if response detected or NONE ID if not.

Example of decoding response:

// Read data from serial port (pseudo code).
uint8_t data[256];
int bytes = serialPort.read(data, 256);

// Decode response.
cr::lrf::LrfUltisenseParser parser;
for (int i = 0; i < bytes; ++i)
{
    LrfUltisenseResponse response = parser.decodeResponse(data[i]);
    if (response != cr::lrf::LrfUltisenseResponse::NONE)
    {
        std::cout << "Response: " << (int)response << std::endl;
    }
}

getDistance method

The getDistance(…) method returns last decoded distance. The range finder can return multiple measurement but the library returns first valid measurement. Method declaration:

float getDistance();

Returns: Value of last measured distance, meters.

Data structures

LrfUltisenseCommand enum

LrfUltisenseCommand enum declared in the LrfUltisenseParser.h file and includes commands IDs. Enum declaration:

namespace cr
{
namespace lrf
{
enum class LrfUltisenseCommand
{
    /// Measure distance command. No argument.
    MEASURE_DISTANCE = 1,
    /// Fake measure distance command. No argument.
    FAKE_MEASURE_DISTANCE,
    /// Set a continuous low power laser emission at a wavelength of
    /// 1550 nm (typical). Argument:
    /// arg:  0 - OFF.
    ///       1 - Lowest power.
    ///       2 - ...
    ///       3 - ...
    ///       4 - ...
    ///       5 - ...
    ///       6 - Highest power.
    SET_CONTINUOUS_LOW_POWER_MODE,
    /// Set a continuous laser emission at a wavelength of 830 nm (typical).
    /// Argument:
    /// arg:  0 - OFF.
    ///       1 - ON.
    SET_LASER_POINTER_MODE,
    /// Arm. Enable laser emission. No argument.
    ARM,
    /// Disarm. Disable laser emission. No argument.
    DISARM,
    /// Set operating mode. Argument:
    /// arg:  0 - OFF.
    ///       1 - Stand-by-mode.
    ///       2 - Normal mode.
    SET_OPERATING_MODE,
    /// Initiate a set of x range measurements with a repetition
    /// frequency of 1 Hz. Argument:
    /// arg - number of requests (2,3,4 ...).
    SET_BLOCK_RANGE_REQUEST,
    /// Set continuous range request. Argument:
    /// arg:  0 - STOP.
    ///       1 - Repetition rate of 0.5 Hz.
    ///       2 - Repetition rate of 1 Hz.
    ///       3 - Repetition rate of 3 Hz.
    ///       4 - Repetition rate of 5 Hz.
    ///       5 - Repetition rate of 10 Hz.
    SET_CONTINUOUS_RANGE_REQUEST,
    /// Set min gate range. Argument:
    /// arg - distance in meters.
    SET_MIN_GATE_RANGE,
    /// Set max gate range. Argument:
    /// arg - distance in meters.
    SET_MAX_GATE_RANGE
};
}
}

Table 2 - Range finder commands IDs.

Command Description
MEASURE_DISTANCE Command to measure distance once.
FAKE_MEASURE_DISTANCE Command to provide fake measurements. Used to test control algorithms.
SET_CONTINUOUS_LOW_POWER_MODE Set a continuous low power laser emission at a wavelength of 1550 nm (typical). Argument: 0 - Off. 1 - Lowest power, 2 - …, 3 - …, 4 - …, 5 - …, 6 - Highest power.
SET_LASER_POINTER_MODE Set a continuous laser emission at a wavelength of 830 nm (typical). Argument: 0 - Off, 1 - On.
ARM Arm laser range finder.
DISARM Disarm laser range finder.
SET_OPERATING_MODE Set operating mode. Argument: 0 - Off (Note: after this command the range finder will be powered off), 1 - Stand-by-mode, 2 - Normal mode.
SET_BLOCK_RANGE_REQUEST Initiate a set of x range measurements with a repetition frequency of 1 Hz. Argument: number of requests (2, 3, 4, …).
SET_CONTINUOUS_RANGE_REQUEST Set continuous range request. Argument: 0 - STOP, 1 - Repetition rate of 0.5 Hz, 2 - Repetition rate of 1 Hz, 3 - Repetition rate of 3 Hz, 4 - Repetition rate of 5 Hz, 5 - Repetition rate of 10 Hz.
SET_MIN_GATE_RANGE Set min gate range. Argument: minimum gate distance, meters.
SET_MAX_GATE_RANGE Set max gate range. Argument: maximum gate distance, meters.

LrfUltisenseResponse enum

LrfUltisenseResponse enum declared in LrfUltisenseParser.h file and describes responses from range finder. Enum declaration:

namespace cr
{
namespace lrf
{
enum class LrfUltisenseResponse
{
    /// No response.
    NONE = 1,
    /// Acknowledge frame. No arguments.
    ACKNOWLEDGE,
    /// Measured distance.
    DISTANCE,
    /// Fake measured distance.
    FAKE_DISTANCE
};
}
}

Table 3 - LRF responses IDs description.

Command Description
NONE Response not detected.
ACKNOWLEDGE Command acknowledge detected. Range finder sends acknowledge message for each input command.
DISTANCE Distance data detected.
FAKE_DISTANCE Fake distance data detected (after command LrfUltisenseCommand::FAKE_MEASURE_DISTANCE).

Test application

Folder LrfUltisenseParser/test contains the test application files. The test application allows you to generate any range finder command, send it to the range over the serial port, receive and decode the response. Once started, the user must enter the serial port name (full name for Linux or just the port number for Windows) and baud rate (default 115200):

================================================
Lrf Ultisense Parser Test v1.0.0
================================================

Set serial port name: /dev/ttyUSB0
Set baudrate (default : 115200): 115200

After user can chose command (enter command ID). If no necessary command has been displayed use can set ID according to LrfUltisenseCommand enum (test application supports all commands):

Serial port open!
===========================================
===========================================
Commands:
1 - MEASURE_DISTANCE
2 - FAKE_MEASURE_DISTANCE
3 - SET_CONTINUOUS_LOW_POWER_MODE
4 - SET_LASER_POINTER_MODE
5 - ARM
6 - DISARM
7 - SET_OPERATING_MODE
8 - SET_BLOCK_RANGE_REQUEST
9 - SET_CONTINUOUS_RANGE_REQUEST	
10 - Just read data from serial port
==========================================

Chose command:

Then, corresponding command will be generated and sent to range finder.

Build and connect to your project

Typical commands to build LrfUltisenseParser library:

cd LrfUltisenseParser
mkdir build
cd build
cmake ..
make

If you want to connect LrfUltisenseParser library to your CMake project as source code you can make follow. For example, if your repository has structure:

CMakeLists.txt
src
    CMakeList.txt
    yourLib.h
    yourLib.cpp

Create folder 3rdparty and copy folder of LrfUltisenseParser repository there. New structure of your repository:

CMakeLists.txt
src
    CMakeList.txt
    yourLib.h
    yourLib.cpp
3rdparty
    LrfUltisenseParser

Create CMakeLists.txt file in 3rdparty folder. CMakeLists.txt should contain:

cmake_minimum_required(VERSION 3.13)

################################################################################
## 3RD-PARTY
## dependencies for the project
################################################################################
project(3rdparty LANGUAGES CXX)

################################################################################
## SETTINGS
## basic 3rd-party settings before use
################################################################################
# To inherit the top-level architecture when the project is used as a submodule.
SET(PARENT ${PARENT}_YOUR_PROJECT_3RDPARTY)
# Disable self-overwriting of parameters inside included subdirectories.
SET(${PARENT}_SUBMODULE_CACHE_OVERWRITE OFF CACHE BOOL "" FORCE)

################################################################################
## CONFIGURATION
## 3rd-party submodules configuration
################################################################################
SET(${PARENT}_SUBMODULE_ULTISENSE_PARSER                ON  CACHE BOOL "" FORCE)
if (${PARENT}_SUBMODULE_ULTISENSE_PARSER)
    SET(${PARENT}ULTISENSE_PARSER                       ON  CACHE BOOL "" FORCE)
    SET(${PARENT}ULTISENSE_PARSER_TEST                  OFF CACHE BOOL "" FORCE)
endif()

################################################################################
## INCLUDING SUBDIRECTORIES
## Adding subdirectories according to the 3rd-party configuration
################################################################################
if (${PARENT}_SUBMODULE_ULTISENSE_PARSER)
    add_subdirectory(LrfUltisenseParser)
endif()

File 3rdparty/CMakeLists.txt adds folder LrfUltisenseParser to your project and excludes test application from compiling (by default test application excluded from compiling if LrfUltisenseParser included as sub-repository). Your repository new structure:

CMakeLists.txt
src
    CMakeList.txt
    yourLib.h
    yourLib.cpp
3rdparty
    CMakeLists.txt
    LrfUltisenseParser

Next you need include folder 3rdparty in main CMakeLists.txt file of your repository. Add string at the end of your main CMakeLists.txt:

add_subdirectory(3rdparty)

Next you have to include Lens library in your src/CMakeLists.txt file:

target_link_libraries(${PROJECT_NAME} LrfUltisenseParser)

Done!