feature:add C++ sample
This commit is contained in:
@@ -11,3 +11,5 @@ add_subdirectory(sample/hub)
|
||||
add_subdirectory(sample/lidar)
|
||||
add_subdirectory(sample/hub_lvx_file)
|
||||
add_subdirectory(sample/lidar_lvx_file)
|
||||
add_subdirectory(sample_cc/hub)
|
||||
add_subdirectory(sample_cc/lidar)
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,21 @@
|
||||
# Minimal makefile for Sphinx documentation
|
||||
#
|
||||
|
||||
# You can set these variables from the command line.
|
||||
SPHINXOPTS =
|
||||
SPHINXBUILD = sphinx-build
|
||||
SOURCEDIR = source
|
||||
BUILDDIR = build
|
||||
|
||||
# Put it first so that "make" without argument is like "make help".
|
||||
help:
|
||||
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
|
||||
.PHONY: help Makefile
|
||||
|
||||
# Catch-all target: route all unknown targets to Sphinx using the new
|
||||
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
|
||||
%: Makefile
|
||||
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
pdf:
|
||||
$(SPHINXBUILD) -b pdf "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
@@ -0,0 +1,35 @@
|
||||
@ECHO OFF
|
||||
|
||||
pushd %~dp0
|
||||
|
||||
REM Command file for Sphinx documentation
|
||||
|
||||
if "%SPHINXBUILD%" == "" (
|
||||
set SPHINXBUILD=sphinx-build
|
||||
)
|
||||
set SOURCEDIR=source
|
||||
set BUILDDIR=build
|
||||
|
||||
if "%1" == "" goto help
|
||||
|
||||
%SPHINXBUILD% >NUL 2>NUL
|
||||
if errorlevel 9009 (
|
||||
echo.
|
||||
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
|
||||
echo.installed, then set the SPHINXBUILD environment variable to point
|
||||
echo.to the full path of the 'sphinx-build' executable. Alternatively you
|
||||
echo.may add the Sphinx directory to PATH.
|
||||
echo.
|
||||
echo.If you don't have Sphinx installed, grab it from
|
||||
echo.http://sphinx-doc.org/
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
|
||||
goto end
|
||||
|
||||
:help
|
||||
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
|
||||
|
||||
:end
|
||||
popd
|
||||
@@ -0,0 +1,319 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Configuration file for the Sphinx documentation builder.
|
||||
#
|
||||
# This file does only contain a selection of the most common options. For a
|
||||
# full list see the documentation:
|
||||
# http://www.sphinx-doc.org/en/master/config
|
||||
|
||||
# -- Path setup --------------------------------------------------------------
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
#
|
||||
# import os
|
||||
# import sys
|
||||
# sys.path.insert(0, os.path.abspath('.'))
|
||||
|
||||
import sys
|
||||
import importlib
|
||||
importlib.reload(sys)
|
||||
|
||||
# -- Project information -----------------------------------------------------
|
||||
|
||||
project = u'Didar'
|
||||
copyright = u'2018, anson.guo'
|
||||
author = u'anson.guo'
|
||||
|
||||
# The short X.Y version
|
||||
version = u''
|
||||
# The full version, including alpha/beta/rc tags
|
||||
release = u''
|
||||
|
||||
|
||||
# -- General configuration ---------------------------------------------------
|
||||
|
||||
# If your documentation needs a minimal Sphinx version, state it here.
|
||||
#
|
||||
# needs_sphinx = '1.0'
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||
# ones.
|
||||
extensions = [
|
||||
'sphinx.ext.imgmath',
|
||||
]
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['_templates']
|
||||
|
||||
# The suffix(es) of source filenames.
|
||||
# You can specify multiple suffix as a list of string:
|
||||
#
|
||||
# source_suffix = ['.rst', '.md']
|
||||
source_suffix = '.rst'
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = 'index'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
#
|
||||
# This is also used if you do content translation via gettext catalogs.
|
||||
# Usually you set "language" from the command line for these cases.
|
||||
language = None
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
# This pattern also affects html_static_path and html_extra_path.
|
||||
exclude_patterns = []
|
||||
|
||||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
pygments_style = None
|
||||
|
||||
|
||||
# -- Options for HTML output -------------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
#
|
||||
html_theme = 'default'
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
# documentation.
|
||||
#
|
||||
# html_theme_options = {}
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ['_static']
|
||||
|
||||
# Custom sidebar templates, must be a dictionary that maps document names
|
||||
# to template names.
|
||||
#
|
||||
# The default sidebars (for documents that don't match any pattern) are
|
||||
# defined by theme itself. Builtin themes are using these templates by
|
||||
# default: ``['localtoc.html', 'relations.html', 'sourcelink.html',
|
||||
# 'searchbox.html']``.
|
||||
#
|
||||
# html_sidebars = {}
|
||||
|
||||
|
||||
# -- Options for HTMLHelp output ---------------------------------------------
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = 'Didardoc'
|
||||
|
||||
# -- Options for manual page output ------------------------------------------
|
||||
|
||||
# One entry per manual page. List of tuples
|
||||
# (source start file, name, description, authors, manual section).
|
||||
man_pages = [
|
||||
(master_doc, 'didar', u'Didar Documentation',
|
||||
[author], 1)
|
||||
]
|
||||
|
||||
|
||||
# -- Options for Texinfo output ----------------------------------------------
|
||||
|
||||
# Grouping the document tree into Texinfo files. List of tuples
|
||||
# (source start file, target name, title, author,
|
||||
# dir menu entry, description, category)
|
||||
texinfo_documents = [
|
||||
(master_doc, 'Didar', u'Didar Documentation',
|
||||
author, 'Didar', 'One line description of project.',
|
||||
'Miscellaneous'),
|
||||
]
|
||||
|
||||
|
||||
# -- Options for Epub output -------------------------------------------------
|
||||
|
||||
# Bibliographic Dublin Core info.
|
||||
epub_title = project
|
||||
|
||||
# The unique identifier of the text. This can be a ISBN number
|
||||
# or the project homepage.
|
||||
#
|
||||
# epub_identifier = ''
|
||||
|
||||
# A unique identification for the text.
|
||||
#
|
||||
# epub_uid = ''
|
||||
|
||||
# A list of files that should not be packed into the epub file.
|
||||
epub_exclude_files = ['search.html']
|
||||
|
||||
|
||||
# -- Extension configuration -------------------------------------------------
|
||||
extensions = [ 'sphinx.ext.todo', 'breathe', 'sphinx.ext.autodoc']
|
||||
breathe_projects = { "didar": "/home/dji/Livox-SDK/didar/doc/xml" }
|
||||
breathe_default_project = "didar"
|
||||
|
||||
|
||||
# pdf_documents = [
|
||||
# ('index', u'HanLP Handbook', u'HanLP Handbook', u'hankcs'),
|
||||
# ]
|
||||
|
||||
# -- Options for LaTeX output ---------------------------------------------
|
||||
latex_documents = [
|
||||
(master_doc, 'Didar.tex', 'Livox C++ API Reference',
|
||||
'Livox', 'manual')
|
||||
]
|
||||
|
||||
latex_elements = {
|
||||
# The paper size ('letterpaper' or 'a4paper').
|
||||
'papersize': 'a4paper',
|
||||
'fontpkg': '\\usepackage{times}'
|
||||
}
|
||||
|
||||
# latex_engine = 'pdflatex'
|
||||
# latex_elements = {
|
||||
# # The paper size ('letterpaper' or 'a4paper').
|
||||
# #
|
||||
# 'papersize': 'a4paper',
|
||||
# 'releasename':" ",
|
||||
# # Sonny, Lenny, Glenn, Conny, Rejne, Bjarne and Bjornstrup
|
||||
# # 'fncychap': '\\usepackage[Lenny]{fncychap}',
|
||||
# 'fncychap': '\\usepackage{fncychap}',
|
||||
# 'fontpkg': '\\usepackage{amsmath,amsfonts,amssymb,amsthm}',
|
||||
|
||||
# 'figure_align':'htbp',
|
||||
# # The font size ('10pt', '11pt' or '12pt').
|
||||
# #
|
||||
# 'pointsize': '10pt',
|
||||
|
||||
# # Additional stuff for the LaTeX preamble.
|
||||
# #
|
||||
# 'preamble': r'''
|
||||
# %%%%%%%%%%%%%%%%%%%% Meher %%%%%%%%%%%%%%%%%%
|
||||
# %%%add number to subsubsection 2=subsection, 3=subsubsection
|
||||
# %%% below subsubsection is not good idea.
|
||||
# \setcounter{secnumdepth}{3}
|
||||
# %
|
||||
# %%%% Table of content upto 2=subsection, 3=subsubsection
|
||||
# \setcounter{tocdepth}{2}
|
||||
|
||||
# \usepackage{amsmath,amsfonts,amssymb,amsthm}
|
||||
# \usepackage{graphicx}
|
||||
|
||||
# %%% reduce spaces for Table of contents, figures and tables
|
||||
# %%% it is used "\addtocontents{toc}{\vskip -1.2cm}" etc. in the document
|
||||
# \usepackage[notlot,nottoc,notlof]{}
|
||||
|
||||
# \usepackage{color}
|
||||
# \usepackage{transparent}
|
||||
# \usepackage{eso-pic}
|
||||
# \usepackage{lipsum}
|
||||
|
||||
# \usepackage{footnotebackref} %%link at the footnote to go to the place of footnote in the text
|
||||
|
||||
# %% spacing between line
|
||||
# \usepackage{setspace}
|
||||
# %%%%\onehalfspacing
|
||||
# %%%%\doublespacing
|
||||
# \singlespacing
|
||||
|
||||
|
||||
# %%%%%%%%%%% datetime
|
||||
# \usepackage{datetime}
|
||||
|
||||
# \newdateformat{MonthYearFormat}{%
|
||||
# \monthname[\THEMONTH], \THEYEAR}
|
||||
|
||||
|
||||
# %% RO, LE will not work for 'oneside' layout.
|
||||
# %% Change oneside to twoside in document class
|
||||
# \usepackage{fancyhdr}
|
||||
# \pagestyle{fancy}
|
||||
# \fancyhf{}
|
||||
|
||||
# %%% Alternating Header for oneside
|
||||
# \fancyhead[L]{\ifthenelse{\isodd{\value{page}}}{ \small \nouppercase{\leftmark} }{}}
|
||||
# \fancyhead[R]{\ifthenelse{\isodd{\value{page}}}{}{ \small \nouppercase{\rightmark} }}
|
||||
|
||||
# %%% Alternating Header for two side
|
||||
# %\fancyhead[RO]{\small \nouppercase{\rightmark}}
|
||||
# %\fancyhead[LE]{\small \nouppercase{\leftmark}}
|
||||
|
||||
# %% for oneside: change footer at right side. If you want to use Left and right then use same as header defined above.
|
||||
# \fancyfoot[R]{\ifthenelse{\isodd{\value{page}}}{{\tiny Meher Krishna Patel} }{\href{http://pythondsp.readthedocs.io/en/latest/pythondsp/toc.html}{\tiny PythonDSP}}}
|
||||
|
||||
# %%% Alternating Footer for two side
|
||||
# %\fancyfoot[RO, RE]{\scriptsize Meher Krishna Patel (mekrip@gmail.com)}
|
||||
|
||||
# %%% page number
|
||||
# \fancyfoot[CO, CE]{\thepage}
|
||||
|
||||
# \renewcommand{\headrulewidth}{0.5pt}
|
||||
# \renewcommand{\footrulewidth}{0.5pt}
|
||||
|
||||
# \RequirePackage{tocbibind} %%% comment this to remove page number for following
|
||||
# \addto\captionsenglish{\renewcommand{\contentsname}{Table of contents}}
|
||||
# \addto\captionsenglish{\renewcommand{\listfigurename}{List of figures}}
|
||||
# \addto\captionsenglish{\renewcommand{\listtablename}{List of tables}}
|
||||
# % \addto\captionsenglish{\renewcommand{\chaptername}{Chapter}}
|
||||
|
||||
|
||||
# %%reduce spacing for itemize
|
||||
# \usepackage{enumitem}
|
||||
# \setlist{nosep}
|
||||
|
||||
# %%%%%%%%%%% Quote Styles at the top of chapter
|
||||
# \usepackage{epigraph}
|
||||
# \setlength{\epigraphwidth}{0.8\columnwidth}
|
||||
# \newcommand{\chapterquote}[2]{\epigraphhead[60]{\epigraph{\textit{#1}}{\textbf {\textit{--#2}}}}}
|
||||
# %%%%%%%%%%% Quote for all places except Chapter
|
||||
# \newcommand{\sectionquote}[2]{{\quote{\textit{``#1''}}{\textbf {\textit{--#2}}}}}
|
||||
# ''',
|
||||
|
||||
|
||||
# 'maketitle': r'''
|
||||
# \pagenumbering{Roman} %%% to avoid page 1 conflict with actual page 1
|
||||
|
||||
# \begin{titlepage}
|
||||
# \centering
|
||||
|
||||
# \vspace*{40mm} %%% * is used to give space from top
|
||||
# \textbf{\Huge {Didar sdk document}}
|
||||
|
||||
# \vspace{0mm}
|
||||
# \Large \textbf{{Author}}
|
||||
|
||||
# \small Created on : Octorber, 2017
|
||||
|
||||
# \vspace*{0mm}
|
||||
# \small Last updated : \MonthYearFormat\today
|
||||
|
||||
|
||||
# %% \vfill adds at the bottom
|
||||
# \vfill
|
||||
# \small \textit{test }{\href{http:\\www.baidu.com}{baidu}}
|
||||
# \end{titlepage}
|
||||
|
||||
# \clearpage
|
||||
# \pagenumbering{roman}
|
||||
# \tableofcontents
|
||||
# \clearpage
|
||||
# \pagenumbering{arabic}
|
||||
|
||||
# ''',
|
||||
# # Latex figure (float) alignment
|
||||
# #
|
||||
# # 'figure_align': 'htbp',
|
||||
# 'sphinxsetup': \
|
||||
# 'hmargin={0.7in,0.7in}, vmargin={1in,1in}, \
|
||||
# verbatimwithframe=true, \
|
||||
# TitleColor={rgb}{0,0,0}, \
|
||||
# HeaderFamily=\\rmfamily\\bfseries, \
|
||||
# InnerLinkColor={rgb}{0,0,1}, \
|
||||
# OuterLinkColor={rgb}{0,0,1}',
|
||||
|
||||
# 'tableofcontents':' ',
|
||||
|
||||
|
||||
|
||||
# }
|
||||
|
||||
@@ -0,0 +1,368 @@
|
||||
.. Didar documentation master file, created by
|
||||
sphinx-quickstart on Mon Dec 10 15:38:07 2018.
|
||||
You can adapt this file completely to your liking, but it should at least
|
||||
contain the root `toctree` directive.
|
||||
|
||||
Welcome to the Livox LiDAR SDK API Reference
|
||||
#############################################
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:numbered:
|
||||
:caption: Contents:
|
||||
|
||||
Basic Types and Functions
|
||||
#############################
|
||||
|
||||
.. doxygenenum:: DeviceType
|
||||
:project: didar
|
||||
|
||||
.. doxygenenum:: LidarState
|
||||
:project: didar
|
||||
|
||||
.. doxygenenum:: LidarFeature
|
||||
:project: didar
|
||||
|
||||
.. doxygenenum:: ResponseStatus
|
||||
:project: didar
|
||||
|
||||
.. doxygenenum:: DeviceEvent
|
||||
:project: didar
|
||||
|
||||
.. doxygenenum:: TimestampType
|
||||
:project: didar
|
||||
|
||||
.. doxygenstruct:: DeviceInfo
|
||||
:project: didar
|
||||
:members:
|
||||
:undoc-members:
|
||||
|
||||
.. doxygenunion:: StatusUnion
|
||||
:project: didar
|
||||
|
||||
.. doxygenfunction:: Init
|
||||
:project: didar
|
||||
|
||||
.. doxygenfunction:: Start
|
||||
:project: didar
|
||||
|
||||
.. doxygenfunction:: Uninit
|
||||
:project: didar
|
||||
|
||||
.. doxygenstruct:: BroadcastDeviceInfo
|
||||
:project: didar
|
||||
:members:
|
||||
:undoc-members:
|
||||
|
||||
.. doxygentypedef:: DeviceBroadcastCallback
|
||||
:project: didar
|
||||
|
||||
.. doxygenfunction:: SetBroadcastCallback
|
||||
:project: didar
|
||||
|
||||
.. doxygentypedef:: DeviceStateUpdateCallback
|
||||
:project: didar
|
||||
|
||||
.. doxygenfunction:: SetDeviceStateUpdateCallback
|
||||
:project: didar
|
||||
|
||||
.. doxygenfunction:: AddHubToConnect
|
||||
:project: didar
|
||||
|
||||
.. doxygenfunction:: AddLidarToConnect
|
||||
:project: didar
|
||||
|
||||
.. doxygenfunction:: GetConnectedDevices
|
||||
:project: didar
|
||||
|
||||
General Functions
|
||||
######################
|
||||
|
||||
Query Device Information
|
||||
==========================
|
||||
|
||||
.. doxygenstruct:: DeviceInformationResponse
|
||||
:project: didar
|
||||
:members:
|
||||
:undoc-members:
|
||||
|
||||
.. doxygentypedef:: DeviceInformationCallback
|
||||
:project: didar
|
||||
|
||||
.. doxygenfunction:: QueryDeviceInformation
|
||||
:project: didar
|
||||
|
||||
Receive Point Cloud Data
|
||||
==========================
|
||||
|
||||
.. doxygenstruct:: LivoxEthPacket
|
||||
:project: didar
|
||||
:members:
|
||||
:undoc-members:
|
||||
|
||||
.. doxygentypedef:: DataCallback
|
||||
:project: didar
|
||||
|
||||
.. doxygenfunction:: SetDataCallback
|
||||
:project: didar
|
||||
|
||||
.. doxygenfunction:: HubGetLidarHandle
|
||||
:project: didar
|
||||
|
||||
Set Coordinate System
|
||||
============================
|
||||
|
||||
.. doxygenfunction:: SetCartesianCoordinate
|
||||
:project: didar
|
||||
|
||||
.. doxygenfunction:: SetSphericalCoordinate
|
||||
:project: didar
|
||||
|
||||
Error Message From Device
|
||||
=======================================
|
||||
|
||||
.. doxygenstruct:: ErrorMessage
|
||||
:project: didar
|
||||
:members:
|
||||
:undoc-members:
|
||||
|
||||
.. doxygentypedef:: ErrorMessageCallback
|
||||
:project: didar
|
||||
|
||||
.. doxygenfunction:: SetErrorMessageCallback
|
||||
:project: didar
|
||||
|
||||
Configure Static/Dynamic IP
|
||||
=======================================
|
||||
|
||||
.. doxygenstruct:: SetDeviceIPModeRequest
|
||||
:project: didar
|
||||
:members:
|
||||
:undoc-members:
|
||||
|
||||
.. doxygenfunction:: SetStaticDynamicIP
|
||||
:project: didar
|
||||
|
||||
.. doxygenstruct:: GetDeviceIPModeResponse
|
||||
:project: didar
|
||||
:members:
|
||||
:undoc-members:
|
||||
|
||||
.. doxygentypedef:: GetDeviceIPInformationCallback
|
||||
:project: didar
|
||||
|
||||
.. doxygenfunction:: GetDeviceIPInformation
|
||||
:project: didar
|
||||
|
||||
Livox Hub Functions
|
||||
######################
|
||||
|
||||
Query Connected LiDAR Unit Information
|
||||
=======================================
|
||||
|
||||
.. doxygenstruct:: ConnectedLidarInfo
|
||||
:project: didar
|
||||
:members:
|
||||
:undoc-members:
|
||||
|
||||
.. doxygenstruct:: HubQueryLidarInformationResponse
|
||||
:project: didar
|
||||
:members:
|
||||
:undoc-members:
|
||||
|
||||
.. doxygentypedef:: HubQueryLidarInformationCallback
|
||||
:project: didar
|
||||
|
||||
.. doxygenfunction:: HubQueryLidarInformation
|
||||
:project: didar
|
||||
|
||||
Configure Lidars Mode
|
||||
==========================================
|
||||
|
||||
.. doxygenstruct:: HubSetModeResponse
|
||||
:project: didar
|
||||
:members:
|
||||
:undoc-members:
|
||||
|
||||
.. doxygentypedef:: HubSetModeCallback
|
||||
:project: didar
|
||||
|
||||
.. doxygenstruct:: HubSetModeRequest
|
||||
:project: didar
|
||||
:members:
|
||||
:undoc-members:
|
||||
|
||||
.. doxygenstruct:: LidarModeRequestItem
|
||||
:project: didar
|
||||
:members:
|
||||
:undoc-members:
|
||||
|
||||
.. doxygenfunction:: HubSetMode
|
||||
:project: didar
|
||||
|
||||
.. doxygenstruct:: LidarStateItem
|
||||
:project: didar
|
||||
:members:
|
||||
:undoc-members:
|
||||
|
||||
.. doxygenstruct:: HubQueryLidarStatusResponse
|
||||
:project: didar
|
||||
:members:
|
||||
:undoc-members:
|
||||
|
||||
.. doxygentypedef:: HubQueryLidarStatusCallback
|
||||
:project: didar
|
||||
|
||||
.. doxygenfunction:: HubQueryLidarStatus
|
||||
:project: didar
|
||||
|
||||
Sampling Control
|
||||
=================
|
||||
|
||||
.. doxygentypedef:: CommonCommandCallback
|
||||
:project: didar
|
||||
|
||||
.. doxygenfunction:: HubStartSampling
|
||||
:project: didar
|
||||
|
||||
.. doxygenfunction:: HubStopSampling
|
||||
:project: didar
|
||||
|
||||
Slot Power Control
|
||||
========================
|
||||
|
||||
.. doxygenstruct:: HubControlSlotPowerRequest
|
||||
:project: didar
|
||||
:members:
|
||||
:undoc-members:
|
||||
|
||||
.. doxygenfunction:: HubControlSlotPower
|
||||
:project: didar
|
||||
|
||||
Configure Livox Hub Extrinsic Parameters
|
||||
========================================
|
||||
|
||||
.. doxygenstruct:: HubSetExtrinsicParameterResponse
|
||||
:project: didar
|
||||
:members:
|
||||
:undoc-members:
|
||||
|
||||
.. doxygentypedef:: HubSetExtrinsicParameterCallback
|
||||
:project: didar
|
||||
|
||||
.. doxygenstruct:: HubSetExtrinsicParameterRequest
|
||||
:project: didar
|
||||
:members:
|
||||
:undoc-members:
|
||||
|
||||
.. doxygenstruct:: ExtrinsicParameterRequestItem
|
||||
:project: didar
|
||||
:members:
|
||||
:undoc-members:
|
||||
|
||||
.. doxygenfunction:: HubSetExtrinsicParameter
|
||||
:project: didar
|
||||
|
||||
.. doxygenstruct:: HubGetExtrinsicParameterRequest
|
||||
:project: didar
|
||||
:members:
|
||||
:undoc-members:
|
||||
|
||||
.. doxygenstruct:: DeviceBroadcastCode
|
||||
:project: didar
|
||||
:members:
|
||||
:undoc-members:
|
||||
|
||||
.. doxygenstruct:: HubGetExtrinsicParameterResponse
|
||||
:project: didar
|
||||
:members:
|
||||
:undoc-members:
|
||||
|
||||
.. doxygenstruct:: ExtrinsicParameterResponseItem
|
||||
:project: didar
|
||||
:members:
|
||||
:undoc-members:
|
||||
|
||||
.. doxygentypedef:: HubGetExtrinsicParameterCallback
|
||||
:project: didar
|
||||
|
||||
.. doxygenfunction:: HubGetExtrinsicParameter
|
||||
:project: didar
|
||||
|
||||
Enable Hub Calculating Extrinsic Parameters
|
||||
========================================================
|
||||
|
||||
.. doxygenfunction:: HubExtrinsicParameterCalculation
|
||||
:project: didar
|
||||
|
||||
Enable or Disable The Rain/Fog Suppression
|
||||
========================================================
|
||||
|
||||
.. doxygenstruct:: RainFogSuppressRequestItem
|
||||
:project: didar
|
||||
:members:
|
||||
:undoc-members:
|
||||
|
||||
.. doxygenstruct:: HubRainFogSuppressRequest
|
||||
:project: didar
|
||||
:members:
|
||||
:undoc-members:
|
||||
|
||||
.. doxygenstruct:: HubRainFogSuppressResponse
|
||||
:project: didar
|
||||
:members:
|
||||
:undoc-members:
|
||||
|
||||
.. doxygentypedef:: HubRainFogSuppressCallback
|
||||
:project: didar
|
||||
|
||||
.. doxygenfunction:: HubRainFogSuppress
|
||||
:project: didar
|
||||
|
||||
LiDAR Functions
|
||||
#####################
|
||||
|
||||
Configure LiDAR Mode
|
||||
==============================
|
||||
|
||||
.. doxygenenum:: LidarMode
|
||||
:project: didar
|
||||
|
||||
.. doxygenfunction:: LidarSetMode
|
||||
:project: didar
|
||||
|
||||
Sample Control
|
||||
=================
|
||||
|
||||
.. doxygenfunction:: LidarStartSampling
|
||||
:project: didar
|
||||
|
||||
.. doxygenfunction:: LidarStopSampling
|
||||
:project: didar
|
||||
|
||||
Configure LiDAR Extrinsic Parameters
|
||||
====================================
|
||||
.. doxygenstruct:: LidarSetExtrinsicParameterRequest
|
||||
:project: didar
|
||||
:members:
|
||||
:undoc-members:
|
||||
|
||||
.. doxygenfunction:: LidarSetExtrinsicParameter
|
||||
:project: didar
|
||||
|
||||
.. doxygenstruct:: LidarGetExtrinsicParameterResponse
|
||||
:project: didar
|
||||
:members:
|
||||
:undoc-members:
|
||||
|
||||
.. doxygentypedef:: LidarGetExtrinsicParameterCallback
|
||||
:project: didar
|
||||
|
||||
.. doxygenfunction:: LidarGetExtrinsicParameter
|
||||
:project: didar
|
||||
|
||||
Enable and Disable the Rain/Fog Suppression
|
||||
============================================
|
||||
|
||||
.. doxygenfunction:: LidarRainFogSuppress
|
||||
:project: didar
|
||||
@@ -0,0 +1,8 @@
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
|
||||
set(DEMO_NAME hub_sample_cc)
|
||||
add_executable(${DEMO_NAME} lds_hub.cpp main.cpp)
|
||||
target_link_libraries(${DEMO_NAME}
|
||||
PRIVATE
|
||||
${PROJECT_NAME}_static
|
||||
)
|
||||
@@ -0,0 +1,385 @@
|
||||
//
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2019 Livox. 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 "lds_hub.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <thread>
|
||||
#include <memory>
|
||||
|
||||
|
||||
/** Const varible ------------------------------------------------------------------------------- */
|
||||
/** User add broadcast code here */
|
||||
static const char* local_broadcast_code_list[] = {
|
||||
"000000000000001",
|
||||
};
|
||||
|
||||
|
||||
/** For callback use only */
|
||||
static LdsHub* g_lds_hub = nullptr;
|
||||
|
||||
|
||||
/** Global function for common use ---------------------------------------------------------------*/
|
||||
|
||||
/** Lds hub function -----------------------------------------------------------------------------*/
|
||||
LdsHub::LdsHub() {
|
||||
auto_connect_mode_ = true;
|
||||
whitelist_count_ = 0;
|
||||
is_initialized_ = false;
|
||||
|
||||
lidar_count_ = 0;
|
||||
memset(broadcast_code_whitelist_, 0, sizeof(broadcast_code_whitelist_));
|
||||
|
||||
memset(lidars_, 0, sizeof(lidars_));
|
||||
for (uint32_t i=0; i<kMaxLidarCount; i++) {
|
||||
lidars_[i].handle = kMaxLidarCount; /** Unallocated state */
|
||||
lidars_[i].connect_state = kConnectStateOff;
|
||||
}
|
||||
memset(&hub_, 0, sizeof(hub_));
|
||||
hub_.handle = kMaxLidarCount;
|
||||
hub_.connect_state = kConnectStateOff;
|
||||
}
|
||||
|
||||
LdsHub::~LdsHub() {
|
||||
}
|
||||
|
||||
int LdsHub::InitLdsHub(std::vector<std::string>& broadcast_code_strs) {
|
||||
|
||||
if (is_initialized_) {
|
||||
printf("LiDAR data source is already inited!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!Init()) {
|
||||
Uninit();
|
||||
printf("Livox-SDK init fail!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
LivoxSdkVersion _sdkversion;
|
||||
GetLivoxSdkVersion(&_sdkversion);
|
||||
printf("Livox SDK version %d.%d.%d\n", _sdkversion.major, _sdkversion.minor, _sdkversion.patch);
|
||||
|
||||
SetBroadcastCallback(LdsHub::OnDeviceBroadcast);
|
||||
SetDeviceStateUpdateCallback(LdsHub::OnDeviceChange);
|
||||
|
||||
/** Add commandline input broadcast code */
|
||||
for (auto input_str : broadcast_code_strs) {
|
||||
LdsHub::AddBroadcastCodeToWhitelist(input_str.c_str());
|
||||
printf("Cmdline input broadcast code : %s\n", input_str.c_str());
|
||||
}
|
||||
|
||||
/** Add local broadcast code */
|
||||
LdsHub::AddLocalBroadcastCode();
|
||||
|
||||
if (whitelist_count_) {
|
||||
LdsHub::DisableAutoConnectMode();
|
||||
printf("Disable auto connect mode!\n");
|
||||
|
||||
printf("List all broadcast code in whiltelist:\n");
|
||||
for (uint32_t i=0; i<whitelist_count_; i++) {
|
||||
printf("%s\n", broadcast_code_whitelist_[i]);
|
||||
}
|
||||
} else {
|
||||
LdsHub::EnableAutoConnectMode();
|
||||
printf("No broadcast code was added to whitelist, swith to automatic connection mode!\n");
|
||||
}
|
||||
|
||||
/** Start livox sdk to receive lidar data */
|
||||
if (!Start()) {
|
||||
Uninit();
|
||||
printf("Livox-SDK init fail!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** Add here, only for callback use */
|
||||
if (g_lds_hub == nullptr) {
|
||||
g_lds_hub = this;
|
||||
}
|
||||
is_initialized_= true;
|
||||
printf("Livox-SDK init success!\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LdsHub::DeInitLdsHub(void) {
|
||||
|
||||
if (!is_initialized_) {
|
||||
printf("LiDAR data source is not exit");
|
||||
return -1;
|
||||
}
|
||||
|
||||
Uninit();
|
||||
printf("Livox SDK Deinit completely!\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Static function in LdsLidar for callback */
|
||||
void LdsHub::GetLidarDataCb(uint8_t hub_handle, LivoxEthPacket *data,
|
||||
uint32_t data_num, void *client_data) {
|
||||
|
||||
LdsHub* lds_hub = static_cast<LdsHub *>(client_data);
|
||||
LivoxEthPacket* eth_packet = data;
|
||||
|
||||
if (!data || !data_num) {
|
||||
return;
|
||||
}
|
||||
|
||||
/** Caculate which lidar this eth packet data belong to */
|
||||
uint8_t handle = HubGetLidarHandle(eth_packet->slot, eth_packet->id);
|
||||
if (handle >= kMaxLidarCount) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (data) {
|
||||
lds_hub->receive_packet_count_++;
|
||||
if (0 == (lds_hub->receive_packet_count_ % 100)) {
|
||||
printf("Receive packet count %d %d\n", handle, lds_hub->receive_packet_count_);
|
||||
|
||||
/** Parsing the timestamp and the point cloud data. */
|
||||
uint64_t cur_timestamp = *((uint64_t *)(data->timestamp));
|
||||
LivoxRawPoint *p_point_data = (LivoxRawPoint *)data->data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LdsHub::OnDeviceBroadcast(const BroadcastDeviceInfo *info) {
|
||||
if (info == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (info->dev_type != kDeviceTypeHub) {
|
||||
printf("It's not a hub : %s\n", info->broadcast_code);
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_lds_hub->IsAutoConnectMode()) {
|
||||
printf("In automatic connection mode, will connect %s\n", info->broadcast_code);
|
||||
} else {
|
||||
if (!g_lds_hub->FindInWhitelist(info->broadcast_code)) {
|
||||
printf("Not in the whitelist, please add %s to if want to connect!\n",\
|
||||
info->broadcast_code);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
LidarDevice* p_hub = &g_lds_hub->hub_;
|
||||
if (p_hub->connect_state == kConnectStateOff) {
|
||||
bool result = false;
|
||||
uint8_t handle = 0;
|
||||
result = AddHubToConnect(info->broadcast_code, &handle);
|
||||
if (result == kStatusSuccess && handle < kMaxLidarCount) {
|
||||
SetDataCallback(handle, LdsHub::GetLidarDataCb, (void *)g_lds_hub);
|
||||
p_hub->handle = handle;
|
||||
p_hub->connect_state = kConnectStateOff;
|
||||
} else {
|
||||
printf("Add Hub to connect is failed : %d %d \n", result, handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Callback function of changing of device state. */
|
||||
void LdsHub::OnDeviceChange(const DeviceInfo *info, DeviceEvent type) {
|
||||
if (info == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (info->handle >= kMaxLidarCount) {
|
||||
return;
|
||||
}
|
||||
|
||||
LidarDevice* p_hub = &g_lds_hub->hub_;
|
||||
if (type == kEventConnect) {
|
||||
if (p_hub->connect_state == kConnectStateOff) {
|
||||
p_hub->connect_state = kConnectStateOn;
|
||||
p_hub->info = *info;
|
||||
}
|
||||
} else if (type == kEventDisconnect) {
|
||||
p_hub->connect_state = kConnectStateOff;
|
||||
printf("Hub[%s] disconnect!\n", info->broadcast_code);
|
||||
} else if (type == kEventStateChange) {
|
||||
p_hub->info = *info;
|
||||
printf("Hub[%s] StateChange\n", info->broadcast_code);
|
||||
}
|
||||
|
||||
if (p_hub->connect_state == kConnectStateOn) {
|
||||
printf("Hub[%s] status_code[%d] working state[%d] feature[%d]\n", \
|
||||
p_hub->info.broadcast_code,\
|
||||
p_hub->info.status.status_code,\
|
||||
p_hub->info.state,\
|
||||
p_hub->info.feature);
|
||||
if (p_hub->info.state == kLidarStateNormal) {
|
||||
HubQueryLidarInformation(HubQueryLidarInfoCb, g_lds_hub);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LdsHub::HubQueryLidarInfoCb(uint8_t status, uint8_t handle, \
|
||||
HubQueryLidarInformationResponse *response,\
|
||||
void *client_data) {
|
||||
LdsHub* lds_hub = static_cast<LdsHub *>(client_data);
|
||||
if (handle >= kMaxLidarCount) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (status == kStatusSuccess) {
|
||||
if (response->count) {
|
||||
printf("Hub have %d lidars:\n", response->count);
|
||||
for (int i = 0; i < response->count; i++) {
|
||||
uint32_t index = (response->device_info_list[i].slot - 1) * 3 +\
|
||||
response->device_info_list[i].id - 1;
|
||||
if (index < kMaxLidarCount) {
|
||||
LidarDevice* p_lidar = &lds_hub->lidars_[index];
|
||||
p_lidar->handle = index;
|
||||
p_lidar->info.handle = index;
|
||||
p_lidar->info.slot = response->device_info_list[i].slot;
|
||||
p_lidar->info.id = response->device_info_list[i].id;
|
||||
p_lidar->info.type = response->device_info_list[i].dev_type;
|
||||
p_lidar->connect_state = kConnectStateSampling;
|
||||
strncpy(p_lidar->info.broadcast_code, \
|
||||
response->device_info_list[i].broadcast_code, \
|
||||
sizeof(p_lidar->info.broadcast_code));
|
||||
printf("[%d]%s DeviceType[%d] Slot[%d] Ver[%d.%d.%d.%d]\n", index, \
|
||||
p_lidar->info.broadcast_code,\
|
||||
p_lidar->info.type, p_lidar->info.slot,\
|
||||
response->device_info_list[i].version[0],\
|
||||
response->device_info_list[i].version[1],\
|
||||
response->device_info_list[i].version[2],\
|
||||
response->device_info_list[i].version[3]);
|
||||
}
|
||||
}
|
||||
|
||||
HubStartSampling(StartSampleCb, lds_hub);
|
||||
lds_hub->hub_.connect_state = kConnectStateSampling;
|
||||
} else {
|
||||
printf("Hub have no lidar, will not start sample!\n");
|
||||
HubQueryLidarInformation(HubQueryLidarInfoCb, lds_hub);
|
||||
}
|
||||
} else {
|
||||
printf("Device Query Informations Failed %d\n", status);
|
||||
}
|
||||
}
|
||||
|
||||
/** Callback function of starting sampling. */
|
||||
void LdsHub::StartSampleCb(uint8_t status, uint8_t handle, \
|
||||
uint8_t response, void *clent_data) {
|
||||
LdsHub* lds_hub = static_cast<LdsHub *>(clent_data);
|
||||
if (handle >= kMaxLidarCount) {
|
||||
return;
|
||||
}
|
||||
|
||||
LidarDevice* p_hub = &lds_hub->hub_;
|
||||
if (status == kStatusSuccess) {
|
||||
if (response != 0) {
|
||||
p_hub->connect_state = kConnectStateOn;
|
||||
printf("Hub start sample fail : state[%d] handle[%d] res[%d]\n", \
|
||||
status, handle, response);
|
||||
} else {
|
||||
printf("Hub start sample success!\n");
|
||||
}
|
||||
} else if (status == kStatusTimeout) {
|
||||
p_hub->connect_state = kConnectStateOn;
|
||||
printf("Hub start sample timeout : state[%d] handle[%d] res[%d]\n", \
|
||||
status, handle, response);
|
||||
}
|
||||
}
|
||||
|
||||
/** Callback function of stopping sampling. */
|
||||
void LdsHub::StopSampleCb(uint8_t status, uint8_t handle, \
|
||||
uint8_t response, void *clent_data) {
|
||||
}
|
||||
|
||||
/** Add broadcast code to whitelist */
|
||||
int LdsHub::AddBroadcastCodeToWhitelist(const char* broadcast_code) {
|
||||
if (!broadcast_code || (strlen(broadcast_code) > kBroadcastCodeSize) || \
|
||||
(whitelist_count_ >= kMaxLidarCount)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (LdsHub::FindInWhitelist(broadcast_code)) {
|
||||
printf("%s is alrealy exist!\n", broadcast_code);
|
||||
return -1;
|
||||
}
|
||||
|
||||
strcpy(broadcast_code_whitelist_[whitelist_count_], broadcast_code);
|
||||
++whitelist_count_;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void LdsHub::AddLocalBroadcastCode(void) {
|
||||
for (size_t i=0; i<sizeof(local_broadcast_code_list)/sizeof(intptr_t); ++i) {
|
||||
std::string invalid_bd = "000000000";
|
||||
printf("Local broadcast code : %s\n", local_broadcast_code_list[i]);
|
||||
if ((kBroadcastCodeSize == strlen(local_broadcast_code_list[i])) && \
|
||||
(nullptr == strstr(local_broadcast_code_list[i], invalid_bd.c_str()))) {
|
||||
LdsHub::AddBroadcastCodeToWhitelist(local_broadcast_code_list[i]);
|
||||
} else {
|
||||
printf("Invalid local broadcast code : %s\n", local_broadcast_code_list[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool LdsHub::FindInWhitelist(const char* broadcast_code) {
|
||||
if (!broadcast_code) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (uint32_t i=0; i<whitelist_count_; i++) {
|
||||
if (strncmp(broadcast_code, broadcast_code_whitelist_[i], kBroadcastCodeSize) == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Get and update LiDAR info */
|
||||
void LdsHub::UpdateHubLidarinfo(void) {
|
||||
DeviceInfo *_lidars = (DeviceInfo *) malloc(sizeof(DeviceInfo) * kMaxLidarCount);
|
||||
|
||||
uint8_t count = kMaxLidarCount;
|
||||
uint8_t status = GetConnectedDevices(_lidars, &count);
|
||||
if (status == kStatusSuccess) {
|
||||
printf("Hub have lidars : \n");
|
||||
int i = 0;
|
||||
for (i = 0; i < count; ++i) {
|
||||
uint8_t handle = _lidars[i].handle;
|
||||
if (handle < kMaxLidarCount) {
|
||||
lidars_[handle].handle = handle;
|
||||
lidars_[handle].info = _lidars[i];
|
||||
lidars_[handle].connect_state = kConnectStateSampling;
|
||||
printf("[%d] : %s\r\n", _lidars[i].handle, _lidars[i].broadcast_code);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (_lidars) {
|
||||
free(_lidars);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
//
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2019 Livox. 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.
|
||||
//
|
||||
|
||||
/** Livox LiDAR data source, data from hub */
|
||||
|
||||
#ifndef COAT_LDS_HUB_H_
|
||||
#define COAT_LDS_HUB_H_
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "livox_def.h"
|
||||
#include "livox_sdk.h"
|
||||
|
||||
typedef enum {
|
||||
kConnectStateOff = 0,
|
||||
kConnectStateOn = 1,
|
||||
kConnectStateSampling = 2,
|
||||
} LidarConnectState;
|
||||
|
||||
typedef struct {
|
||||
uint8_t handle;
|
||||
LidarConnectState connect_state;
|
||||
DeviceInfo info;
|
||||
} LidarDevice;
|
||||
|
||||
/**
|
||||
* LiDAR data source, data from hub.
|
||||
*/
|
||||
class LdsHub {
|
||||
public:
|
||||
static LdsHub& GetInstance() {
|
||||
static LdsHub lds_hub;
|
||||
return lds_hub;
|
||||
}
|
||||
|
||||
int InitLdsHub(std::vector<std::string>& broadcast_code_strs);
|
||||
int DeInitLdsHub(void);
|
||||
|
||||
private:
|
||||
LdsHub();
|
||||
LdsHub(const LdsHub&) = delete;
|
||||
~LdsHub();
|
||||
LdsHub& operator=(const LdsHub&) = delete;
|
||||
|
||||
/** LiDAR data receive callback */
|
||||
static void GetLidarDataCb(uint8_t hub_handle, LivoxEthPacket *data,\
|
||||
uint32_t data_num, void *client_data);
|
||||
static void OnDeviceBroadcast(const BroadcastDeviceInfo *info);
|
||||
static void OnDeviceChange(const DeviceInfo *info, DeviceEvent type);
|
||||
static void StartSampleCb(uint8_t status, uint8_t handle, uint8_t response, void *clent_data);
|
||||
static void StopSampleCb(uint8_t status, uint8_t handle, uint8_t response, void *clent_data);
|
||||
static void HubQueryLidarInfoCb(uint8_t status, uint8_t handle, \
|
||||
HubQueryLidarInformationResponse *response, void *client_data);
|
||||
|
||||
int AddBroadcastCodeToWhitelist(const char* broadcast_code);
|
||||
void AddLocalBroadcastCode(void);
|
||||
bool FindInWhitelist(const char* broadcast_code);
|
||||
void UpdateHubLidarinfo(void);
|
||||
|
||||
void EnableAutoConnectMode(void) { auto_connect_mode_ = true; }
|
||||
void DisableAutoConnectMode(void) { auto_connect_mode_ = false; }
|
||||
bool IsAutoConnectMode(void) { return auto_connect_mode_; }
|
||||
|
||||
bool auto_connect_mode_;
|
||||
uint32_t whitelist_count_;
|
||||
volatile bool is_initialized_;
|
||||
char broadcast_code_whitelist_[kMaxLidarCount][kBroadcastCodeSize];
|
||||
|
||||
uint32_t lidar_count_;
|
||||
LidarDevice lidars_[kMaxLidarCount];
|
||||
LidarDevice hub_;
|
||||
uint32_t receive_packet_count_;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,141 @@
|
||||
//
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2019 Livox. 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>
|
||||
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <apr_general.h>
|
||||
#include <apr_getopt.h>
|
||||
#include "lds_hub.h"
|
||||
|
||||
/** Cmdline input broadcast code */
|
||||
static std::vector<std::string> cmdline_broadcast_code;
|
||||
|
||||
/** Set the program options.
|
||||
* You can input the registered device broadcast code and decide whether to save the log file.
|
||||
*/
|
||||
static int SetProgramOption(int argc, const char *argv[]) {
|
||||
apr_status_t rv;
|
||||
apr_pool_t *mp = NULL;
|
||||
static const apr_getopt_option_t opt_option[] = {
|
||||
/** Long-option, short-option, has-arg flag, description */
|
||||
{ "code", 'c', 1, "Register device broadcast code" },
|
||||
{ "log", 'l', 0, "Save the log file" },
|
||||
{ "help", 'h', 0, "Show help" },
|
||||
{ NULL, 0, 0, NULL },
|
||||
};
|
||||
apr_getopt_t *opt = NULL;
|
||||
int optch = 0;
|
||||
const char *optarg = NULL;
|
||||
|
||||
if (apr_initialize() != APR_SUCCESS) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (apr_pool_create(&mp, NULL) != APR_SUCCESS) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
rv = apr_getopt_init(&opt, mp, argc, argv);
|
||||
if (rv != APR_SUCCESS) {
|
||||
printf("Program options initialization failed.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** Parse the all options based on opt_option[] */
|
||||
bool is_help = false;
|
||||
while ((rv = apr_getopt_long(opt, opt_option, &optch, &optarg)) == APR_SUCCESS) {
|
||||
switch (optch) {
|
||||
case 'c': {
|
||||
printf("Register broadcast code: %s\n", optarg);
|
||||
cmdline_broadcast_code.clear();
|
||||
cmdline_broadcast_code.push_back(optarg);
|
||||
break;
|
||||
}
|
||||
case 'l': {
|
||||
printf("Save the log file.\n");
|
||||
SaveLoggerFile();
|
||||
break;
|
||||
}
|
||||
case 'h': {
|
||||
printf(
|
||||
" [-c] Register device broadcast code\n"
|
||||
" [-l] Save the log file\n"
|
||||
" [-h] Show help\n"
|
||||
);
|
||||
is_help = true;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (rv != APR_EOF) {
|
||||
printf("Invalid options.\n");
|
||||
}
|
||||
|
||||
apr_pool_destroy(mp);
|
||||
mp = NULL;
|
||||
apr_terminate();
|
||||
if (is_help)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, const char *argv[]) {
|
||||
/** Set the program options. */
|
||||
if (SetProgramOption(argc, argv)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
LdsHub& read_hub = LdsHub::GetInstance();
|
||||
int ret = read_hub.InitLdsHub(cmdline_broadcast_code);
|
||||
if (!ret) {
|
||||
printf("Init lds hub success!\n");
|
||||
} else {
|
||||
printf("Init lds hub fail!\n");
|
||||
}
|
||||
|
||||
printf("Start discovering device.\n");
|
||||
|
||||
#ifdef WIN32
|
||||
Sleep(100000);
|
||||
#else
|
||||
sleep(100);
|
||||
#endif
|
||||
|
||||
read_hub.DeInitLdsHub();
|
||||
printf("Livox hub demo end!\n");
|
||||
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
|
||||
set(DEMO_NAME lidar_sample_cc)
|
||||
add_executable(${DEMO_NAME} main.cpp lds_lidar.cpp)
|
||||
target_link_libraries(${DEMO_NAME}
|
||||
PRIVATE
|
||||
${PROJECT_NAME}_static
|
||||
)
|
||||
@@ -0,0 +1,320 @@
|
||||
//
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2019 Livox. 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 "lds_lidar.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <thread>
|
||||
#include <memory>
|
||||
|
||||
|
||||
/** Const varible ------------------------------------------------------------------------------- */
|
||||
/** User add broadcast code here */
|
||||
static const char* local_broadcast_code_list[] = {
|
||||
"000000000000001",
|
||||
};
|
||||
|
||||
/** For callback use only */
|
||||
LdsLidar* g_lidars = nullptr;
|
||||
|
||||
/** Lds lidar function ---------------------------------------------------------------------------*/
|
||||
LdsLidar::LdsLidar() {
|
||||
auto_connect_mode_ = true;
|
||||
whitelist_count_ = 0;
|
||||
is_initialized_ = false;
|
||||
|
||||
lidar_count_ = 0;
|
||||
memset(broadcast_code_whitelist_, 0, sizeof(broadcast_code_whitelist_));
|
||||
|
||||
memset(lidars_, 0, sizeof(lidars_));
|
||||
for (uint32_t i=0; i<kMaxLidarCount; i++) {
|
||||
lidars_[i].handle = kMaxLidarCount; /** Unallocated state */
|
||||
lidars_[i].connect_state = kConnectStateOff;
|
||||
}
|
||||
}
|
||||
|
||||
LdsLidar::~LdsLidar() {
|
||||
}
|
||||
|
||||
int LdsLidar::InitLdsLidar(std::vector<std::string>& broadcast_code_strs) {
|
||||
|
||||
if (is_initialized_) {
|
||||
printf("LiDAR data source is already inited!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!Init()) {
|
||||
Uninit();
|
||||
printf("Livox-SDK init fail!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
LivoxSdkVersion _sdkversion;
|
||||
GetLivoxSdkVersion(&_sdkversion);
|
||||
printf("Livox SDK version %d.%d.%d\n", _sdkversion.major, _sdkversion.minor, _sdkversion.patch);
|
||||
|
||||
SetBroadcastCallback(LdsLidar::OnDeviceBroadcast);
|
||||
SetDeviceStateUpdateCallback(LdsLidar::OnDeviceChange);
|
||||
|
||||
/** Add commandline input broadcast code */
|
||||
for (auto input_str : broadcast_code_strs) {
|
||||
LdsLidar::AddBroadcastCodeToWhitelist(input_str.c_str());
|
||||
}
|
||||
|
||||
/** Add local broadcast code */
|
||||
LdsLidar::AddLocalBroadcastCode();
|
||||
|
||||
if (whitelist_count_) {
|
||||
LdsLidar::DisableAutoConnectMode();
|
||||
printf("Disable auto connect mode!\n");
|
||||
|
||||
printf("List all broadcast code in whiltelist:\n");
|
||||
for (uint32_t i=0; i<whitelist_count_; i++) {
|
||||
printf("%s\n", broadcast_code_whitelist_[i]);
|
||||
}
|
||||
} else {
|
||||
LdsLidar::EnableAutoConnectMode();
|
||||
printf("No broadcast code was added to whitelist, swith to automatic connection mode!\n");
|
||||
}
|
||||
|
||||
/** Start livox sdk to receive lidar data */
|
||||
if (!Start()) {
|
||||
Uninit();
|
||||
printf("Livox-SDK init fail!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** Add here, only for callback use */
|
||||
if (g_lidars == nullptr) {
|
||||
g_lidars = this;
|
||||
}
|
||||
is_initialized_= true;
|
||||
printf("Livox-SDK init success!\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int LdsLidar::DeInitLdsLidar(void) {
|
||||
|
||||
if (!is_initialized_) {
|
||||
printf("LiDAR data source is not exit");
|
||||
return -1;
|
||||
}
|
||||
|
||||
Uninit();
|
||||
printf("Livox SDK Deinit completely!\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/** Static function in LdsLidar for callback or event process ------------------------------------*/
|
||||
|
||||
/** Receiving point cloud data from Livox LiDAR. */
|
||||
void LdsLidar::GetLidarDataCb(uint8_t handle, LivoxEthPacket *data,
|
||||
uint32_t data_num, void *client_data) {
|
||||
using namespace std;
|
||||
|
||||
LdsLidar* lidar_this = static_cast<LdsLidar *>(client_data);
|
||||
LivoxEthPacket* eth_packet = data;
|
||||
|
||||
if (!data || !data_num || (handle >= kMaxLidarCount)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (eth_packet) {
|
||||
lidar_this->data_recveive_count_[handle] += data_num;
|
||||
if (lidar_this->data_recveive_count_[handle] % 10000 == 0) {
|
||||
printf("receive packet count %d %d\n", handle, lidar_this->data_recveive_count_[handle]);
|
||||
|
||||
/** Parsing the timestamp and the point cloud data. */
|
||||
uint64_t cur_timestamp = *((uint64_t *)(data->timestamp));
|
||||
LivoxRawPoint *p_point_data = (LivoxRawPoint *)data->data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LdsLidar::OnDeviceBroadcast(const BroadcastDeviceInfo *info) {
|
||||
if (info == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (info->dev_type == kDeviceTypeHub) {
|
||||
printf("In lidar mode, couldn't connect a hub : %s\n", info->broadcast_code);
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_lidars->IsAutoConnectMode()) {
|
||||
printf("In automatic connection mode, will connect %s\n", info->broadcast_code);
|
||||
} else {
|
||||
if (!g_lidars->FindInWhitelist(info->broadcast_code)) {
|
||||
printf("Not in the whitelist, please add %s to if want to connect!\n",\
|
||||
info->broadcast_code);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool result = false;
|
||||
uint8_t handle = 0;
|
||||
result = AddLidarToConnect(info->broadcast_code, &handle);
|
||||
if (result == kStatusSuccess && handle < kMaxLidarCount) {
|
||||
SetDataCallback(handle, LdsLidar::GetLidarDataCb, (void *)g_lidars);
|
||||
g_lidars->lidars_[handle].handle = handle;
|
||||
g_lidars->lidars_[handle].connect_state = kConnectStateOff;
|
||||
} else {
|
||||
printf("Add lidar to connect is failed : %d %d \n", result, handle);
|
||||
}
|
||||
}
|
||||
|
||||
/** Callback function of changing of device state. */
|
||||
void LdsLidar::OnDeviceChange(const DeviceInfo *info, DeviceEvent type) {
|
||||
if (info == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t handle = info->handle;
|
||||
if (handle >= kMaxLidarCount) {
|
||||
return;
|
||||
}
|
||||
|
||||
LidarDevice* p_lidar = &(g_lidars->lidars_[handle]);
|
||||
if (type == kEventConnect) {
|
||||
QueryDeviceInformation(handle, DeviceInformationCb, g_lidars);
|
||||
if (p_lidar->connect_state == kConnectStateOff) {
|
||||
p_lidar->connect_state = kConnectStateOn;
|
||||
p_lidar->info = *info;
|
||||
}
|
||||
} else if (type == kEventDisconnect) {
|
||||
p_lidar->connect_state = kConnectStateOff;
|
||||
printf("Lidar[%s] disconnect!\n", info->broadcast_code);
|
||||
} else if (type == kEventStateChange) {
|
||||
p_lidar->info = *info;
|
||||
}
|
||||
|
||||
if (p_lidar->connect_state == kConnectStateOn) {
|
||||
printf("Lidar[%s] status_code[%d] working state[%d] feature[%d]\n", \
|
||||
p_lidar->info.broadcast_code,\
|
||||
p_lidar->info.status.status_code,\
|
||||
p_lidar->info.state,\
|
||||
p_lidar->info.feature);
|
||||
if (p_lidar->info.state == kLidarStateNormal) {
|
||||
LidarStartSampling(handle, LdsLidar::StartSampleCb, g_lidars);
|
||||
p_lidar->connect_state = kConnectStateSampling;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Query the firmware version of Livox LiDAR. */
|
||||
void LdsLidar::DeviceInformationCb(uint8_t status, uint8_t handle, \
|
||||
DeviceInformationResponse *ack, void *clent_data) {
|
||||
if (status != kStatusSuccess) {
|
||||
printf("Device Query Informations Failed : %d\n", status);
|
||||
}
|
||||
if (ack) {
|
||||
printf("firm ver: %d.%d.%d.%d\n",
|
||||
ack->firmware_version[0],
|
||||
ack->firmware_version[1],
|
||||
ack->firmware_version[2],
|
||||
ack->firmware_version[3]);
|
||||
}
|
||||
}
|
||||
|
||||
/** Callback function of starting sampling. */
|
||||
void LdsLidar::StartSampleCb(uint8_t status, uint8_t handle, \
|
||||
uint8_t response, void *clent_data) {
|
||||
LdsLidar* lds_lidar = static_cast<LdsLidar *>(clent_data);
|
||||
|
||||
if (handle >= kMaxLidarCount) {
|
||||
return;
|
||||
}
|
||||
|
||||
LidarDevice* p_lidar = &(lds_lidar->lidars_[handle]);
|
||||
if (status == kStatusSuccess) {
|
||||
if (response != 0) {
|
||||
p_lidar->connect_state = kConnectStateOn;
|
||||
printf("Lidar start sample fail : state[%d] handle[%d] res[%d]\n", \
|
||||
status, handle, response);
|
||||
} else {
|
||||
printf("Lidar start sample success\n");
|
||||
}
|
||||
} else if (status == kStatusTimeout) {
|
||||
p_lidar->connect_state = kConnectStateOn;
|
||||
printf("Lidar start sample timeout : state[%d] handle[%d] res[%d]\n", \
|
||||
status, handle, response);
|
||||
}
|
||||
}
|
||||
|
||||
/** Callback function of stopping sampling. */
|
||||
void LdsLidar::StopSampleCb(uint8_t status, uint8_t handle, \
|
||||
uint8_t response, void *clent_data) {
|
||||
}
|
||||
|
||||
/** Add broadcast code to whitelist */
|
||||
int LdsLidar::AddBroadcastCodeToWhitelist(const char* bd_code) {
|
||||
if (!bd_code || (strlen(bd_code) > kBroadcastCodeSize) || \
|
||||
(whitelist_count_ >= kMaxLidarCount)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (LdsLidar::FindInWhitelist(bd_code)) {
|
||||
printf("%s is alrealy exist!\n", bd_code);
|
||||
return -1;
|
||||
}
|
||||
|
||||
strcpy(broadcast_code_whitelist_[whitelist_count_], bd_code);
|
||||
++whitelist_count_;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void LdsLidar::AddLocalBroadcastCode(void) {
|
||||
for (size_t i=0; i<sizeof(local_broadcast_code_list)/sizeof(intptr_t); ++i) {
|
||||
std::string invalid_bd = "000000000";
|
||||
printf("Local broadcast code : %s\n", local_broadcast_code_list[i]);
|
||||
if ((kBroadcastCodeSize == strlen(local_broadcast_code_list[i])) && \
|
||||
(nullptr == strstr(local_broadcast_code_list[i], invalid_bd.c_str()))) {
|
||||
LdsLidar::AddBroadcastCodeToWhitelist(local_broadcast_code_list[i]);
|
||||
} else {
|
||||
printf("Invalid local broadcast code : %s\n", local_broadcast_code_list[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool LdsLidar::FindInWhitelist(const char* bd_code) {
|
||||
if (!bd_code) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (uint32_t i=0; i<whitelist_count_; i++) {
|
||||
if (strncmp(bd_code, broadcast_code_whitelist_[i], kBroadcastCodeSize) == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
//
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2019 Livox. 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.
|
||||
//
|
||||
|
||||
/** Livox LiDAR data source, data from dependent lidar */
|
||||
|
||||
#ifndef LDS_LIDAR_H_
|
||||
#define LDS_LIDAR_H_
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "livox_def.h"
|
||||
#include "livox_sdk.h"
|
||||
|
||||
|
||||
typedef enum {
|
||||
kConnectStateOff = 0,
|
||||
kConnectStateOn = 1,
|
||||
kConnectStateSampling = 2,
|
||||
} LidarConnectState;
|
||||
|
||||
typedef struct {
|
||||
uint8_t handle;
|
||||
LidarConnectState connect_state;
|
||||
DeviceInfo info;
|
||||
} LidarDevice;
|
||||
|
||||
/**
|
||||
* LiDAR data source, data from dependent lidar.
|
||||
*/
|
||||
class LdsLidar {
|
||||
public:
|
||||
|
||||
static LdsLidar& GetInstance() {
|
||||
static LdsLidar lds_lidar;
|
||||
return lds_lidar;
|
||||
}
|
||||
|
||||
int InitLdsLidar(std::vector<std::string>& broadcast_code_strs);
|
||||
int DeInitLdsLidar(void);
|
||||
|
||||
private:
|
||||
LdsLidar();
|
||||
LdsLidar(const LdsLidar&) = delete;
|
||||
~LdsLidar();
|
||||
LdsLidar& operator=(const LdsLidar&) = delete;
|
||||
|
||||
static void GetLidarDataCb(uint8_t handle, LivoxEthPacket *data,\
|
||||
uint32_t data_num, void *client_data);
|
||||
static void OnDeviceBroadcast(const BroadcastDeviceInfo *info);
|
||||
static void OnDeviceChange(const DeviceInfo *info, DeviceEvent type);
|
||||
static void StartSampleCb(uint8_t status, uint8_t handle, uint8_t response, void *clent_data);
|
||||
static void StopSampleCb(uint8_t status, uint8_t handle, uint8_t response, void *clent_data);
|
||||
static void DeviceInformationCb(uint8_t status, uint8_t handle, \
|
||||
DeviceInformationResponse *ack, void *clent_data);
|
||||
|
||||
int AddBroadcastCodeToWhitelist(const char* broadcast_code);
|
||||
void AddLocalBroadcastCode(void);
|
||||
bool FindInWhitelist(const char* broadcast_code);
|
||||
|
||||
void EnableAutoConnectMode(void) { auto_connect_mode_ = true; }
|
||||
void DisableAutoConnectMode(void) { auto_connect_mode_ = false; }
|
||||
bool IsAutoConnectMode(void) { return auto_connect_mode_; }
|
||||
|
||||
bool auto_connect_mode_;
|
||||
uint32_t whitelist_count_;
|
||||
volatile bool is_initialized_;
|
||||
char broadcast_code_whitelist_[kMaxLidarCount][kBroadcastCodeSize];
|
||||
|
||||
uint32_t lidar_count_;
|
||||
LidarDevice lidars_[kMaxLidarCount];
|
||||
|
||||
uint32_t data_recveive_count_[kMaxLidarCount];
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,151 @@
|
||||
//
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2019 Livox. 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>
|
||||
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <apr_general.h>
|
||||
#include <apr_getopt.h>
|
||||
#include "lds_lidar.h"
|
||||
|
||||
/** Cmdline input broadcast code */
|
||||
static std::vector<std::string> cmdline_broadcast_code;
|
||||
|
||||
/** Set the program options.
|
||||
* You can input the registered device broadcast code and decide whether to save the log file.
|
||||
*/
|
||||
static int SetProgramOption(int argc, const char *argv[]) {
|
||||
apr_status_t rv;
|
||||
apr_pool_t *mp = NULL;
|
||||
static const apr_getopt_option_t opt_option[] = {
|
||||
/** Long-option, short-option, has-arg flag, description */
|
||||
{ "code", 'c', 1, "Register device broadcast code" },
|
||||
{ "log", 'l', 0, "Save the log file" },
|
||||
{ "help", 'h', 0, "Show help" },
|
||||
{ NULL, 0, 0, NULL },
|
||||
};
|
||||
apr_getopt_t *opt = NULL;
|
||||
int optch = 0;
|
||||
const char *optarg = NULL;
|
||||
|
||||
if (apr_initialize() != APR_SUCCESS) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (apr_pool_create(&mp, NULL) != APR_SUCCESS) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
rv = apr_getopt_init(&opt, mp, argc, argv);
|
||||
if (rv != APR_SUCCESS) {
|
||||
printf("Program options initialization failed.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** Parse the all options based on opt_option[] */
|
||||
bool is_help = false;
|
||||
while ((rv = apr_getopt_long(opt, opt_option, &optch, &optarg)) == APR_SUCCESS) {
|
||||
switch (optch) {
|
||||
case 'c': {
|
||||
printf("Register broadcast code: %s\n", optarg);
|
||||
char *sn_list = (char *)malloc(sizeof(char)*(strlen(optarg) + 1));
|
||||
strncpy(sn_list, optarg, sizeof(char)*(strlen(optarg) + 1));
|
||||
char *sn_list_head = sn_list;
|
||||
sn_list = strtok(sn_list, "&");
|
||||
cmdline_broadcast_code.clear();
|
||||
while (sn_list) {
|
||||
cmdline_broadcast_code.push_back(sn_list);
|
||||
sn_list = strtok(nullptr, "&");
|
||||
}
|
||||
free(sn_list_head);
|
||||
sn_list_head = nullptr;
|
||||
break;
|
||||
}
|
||||
case 'l': {
|
||||
printf("Save the log file.\n");
|
||||
SaveLoggerFile();
|
||||
break;
|
||||
}
|
||||
case 'h': {
|
||||
printf(
|
||||
" [-c] Register device broadcast code\n"
|
||||
" [-l] Save the log file\n"
|
||||
" [-h] Show help\n"
|
||||
);
|
||||
is_help = true;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (rv != APR_EOF) {
|
||||
printf("Invalid options.\n");
|
||||
}
|
||||
|
||||
apr_pool_destroy(mp);
|
||||
mp = NULL;
|
||||
apr_terminate();
|
||||
if (is_help)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, const char *argv[]) {
|
||||
/** Set the program options. */
|
||||
if (SetProgramOption(argc, argv)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
LdsLidar& read_lidar = LdsLidar::GetInstance();
|
||||
|
||||
int ret = read_lidar.InitLdsLidar(cmdline_broadcast_code);
|
||||
if (!ret) {
|
||||
printf("Init lds lidar success!\n");
|
||||
} else {
|
||||
printf("Init lds lidar fail!\n");
|
||||
}
|
||||
|
||||
printf("Start discovering device.\n");
|
||||
|
||||
#ifdef WIN32
|
||||
Sleep(100000);
|
||||
#else
|
||||
sleep(100);
|
||||
#endif
|
||||
|
||||
read_lidar.DeInitLdsLidar();
|
||||
printf("Livox lidar demo end!\n");
|
||||
|
||||
}
|
||||
@@ -108,4 +108,5 @@ target_sources(${SDK_LIBRARY}
|
||||
install(TARGETS ${SDK_LIBRARY}
|
||||
PUBLIC_HEADER DESTINATION include
|
||||
ARCHIVE DESTINATION lib
|
||||
LIBRARY DESTINATION lib)
|
||||
LIBRARY DESTINATION lib)
|
||||
|
||||
|
||||
@@ -28,6 +28,12 @@ std::shared_ptr<spdlog::logger> logger = NULL;
|
||||
bool is_save_log_file = false;
|
||||
|
||||
void InitLogger() {
|
||||
|
||||
if (spdlog::get("console") != nullptr) {
|
||||
logger = spdlog::get("console");
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<spdlog::sink_ptr> sinkList;
|
||||
auto consoleSink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
|
||||
consoleSink->set_level(spdlog::level::debug);
|
||||
|
||||
@@ -110,15 +110,19 @@ void DeviceManager::UpdateDevices(const DeviceInfo &device, DeviceEvent type) {
|
||||
connected_cb_(&device, type);
|
||||
}
|
||||
|
||||
if ((device_mode_ == kDeviceModeHub) && (type == kEventConnect)) {
|
||||
LOG_DEBUG("Send Query lidars command");
|
||||
command_handler().SendCommand(kHubDefaultHandle,
|
||||
kCommandSetHub,
|
||||
kCommandIDHubQueryLidarInformation,
|
||||
NULL,
|
||||
0,
|
||||
MakeCommandCallback<DeviceManager, HubQueryLidarInformationResponse>(
|
||||
this, &DeviceManager::HubLidarInfomationCallback));
|
||||
if (device_mode_ == kDeviceModeHub) {
|
||||
if (type == kEventConnect) {
|
||||
LOG_DEBUG("Send Query lidars command");
|
||||
command_handler().SendCommand(kHubDefaultHandle,
|
||||
kCommandSetHub,
|
||||
kCommandIDHubQueryLidarInformation,
|
||||
NULL,
|
||||
0,
|
||||
MakeCommandCallback<DeviceManager, HubQueryLidarInformationResponse>(
|
||||
this, &DeviceManager::HubLidarInfomationCallback));
|
||||
} else if (connected_cb_) {
|
||||
connected_cb_(&device, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -227,7 +231,8 @@ void DeviceManager::UpdateDeviceState(uint8_t handle, const HeartbeatResponse &r
|
||||
update = true;
|
||||
}
|
||||
if (info.status.progress != response.error_union.progress) {
|
||||
LOG_INFO(" Update progress {}, device connect {}", (uint16_t)response.error_union.progress, devices_[handle].connected);
|
||||
LOG_INFO(
|
||||
" Update progress {}, device connect {}", (uint16_t)response.error_union.progress, devices_[handle].connected);
|
||||
info.status.progress = response.error_union.progress;
|
||||
update = true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user