add sicktoolbox

This commit is contained in:
robin_shaun 2021-02-27 08:21:50 +08:00
parent 3dcec7b6d3
commit f8a94e6054
85 changed files with 22445 additions and 0 deletions

View File

@ -0,0 +1,43 @@
-------------------------------------------------------------------
-------------------------------------------------------------------
The Sick LIDAR Matlab/C++ Toolbox
-------------------------------------------------------------------
The Sick LIDAR Matlab/C++ Toolbox was originally developed
and is currently maintained by Jason Derenick and Thomas Miller
at Lehigh University. It is branched from the source code used
by the Ben Franklin Racing Team, whose robot car, "Little Ben",
was only one of six to successfully finish the 2007 DARPA Urban
Grand Challenge.
***AUTHORS
-----------------------------------------
Jason Derenick, Ph.D. Candidate
Computer Science and Engineering
Lehigh University
19 Memorial Drive West
Bethlehem, PA 18015 USA
derenick(at)lehigh(dot)edu
http://vader.cse.lehigh.edu/~derenick
-----------------------------------------
-----------------------------------------
Thomas Miller
Computer Science and Engineering
Lehigh University
19 Memorial Drive West
Bethlehem, PA 18015 USA
thm204(at)lehigh(dot)edu
http://www.lehigh.edu/~thm204
-----------------------------------------
Jason and Thomas are advised by Professor John Spletzer
in the Department of Computer Science and Engineering.
***ACKNOWLEDGEMENTS
Please see the THANKS file :o)
-------------------------------------------------------------------

View File

@ -0,0 +1,96 @@
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Changelog for package sicktoolbox
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1.0.104 (2019-05-04)
--------------------
1.0.103 (2013-08-21)
--------------------
* No more Willow Garage email.
* Update CMakeLists.txt
* Contributors: Chad Rockey
1.0.102 (2013-03-28)
--------------------
* Update README
* Catkinized and converted to CMake.
* Initial package.xml and CmakeLists.txt
* Applied power_delay.patch.
* Applying unistd.patch
* Applied stdlib_include.patch
* Removing Matlab support.
* Commiting configured files for cmake conversion.
* Forgot an installation step for the INSTALL readme.
* Updated install files, updated install directions.
* Some minor changes
* Cleaned up and began adjusting mex interface a bit for the lms1xx
* Actually, the previous post should have been renamaing 1ms to lms2xx. Now I am adding lms1xx
* Added directory for lms1xx in matlab examples directory
* Added include for GCC4.3
* A number of improvements, bug fixes. Also put together mex file for streaming values via the lms 1xx using the given C++ driver. Adjusted mex build scripts to build and include lms1xx.
* deleting sicklms2xxlite
* Changed name of sickld-1.0 to sickld
* Moving mex lms dir to lms2xx
* fixed some bugs and restructured the driver to provide more low-level control
* Added range and reflectivity streaming; however, still can't figure out how to successfully transition between measurement modes without uninitializing. Lots of cleanup
* Adjusted the lms1xx app and some minor cleanup
* Added some range measurement acquisition to driver
* Polished configuration functions
* Adjusted lms1xx example file
* committing cahnges to base and sick ld & lms2xx drivers
* Fixed some bugs and setup configuration capability for the lms 1xx driver
* Started adding _getSickStatus and began writing the message parsing code for the Sick LMS 1xx - currently the LMS 1xx will compile but is unstable
* Setup connect/disconnect routines and buffer monitor for SickLMS1xx driver. Also, included an example for testing the code right now.
* Started adding driver files for SickLMS1xx unit
* Adjusted lms examples to using renamed sicklms2xx class. Also fixed corresponding makefiles and changed the prefix for each lms example to lms2xx (e.g. lms_config is now lms2xx_config)
* Moved c++/examples/lms to c++/examples/lms2xx
* Supplanted SickLMS with SickLMS2xx and sick_lms with sick_lms_2xx where appropriate. Currently compiles, but needs a sanity test
* Created sicklms1xx driver directory and Makefile.am for each directory (currently, they are empty)
* Updating configure.ac to use the new AX macros for lms1xx and lms2xx source directories
* changes sicklms-1.0 to sicklms2xx and sicklmslite-1.0 to sicklms1xx
* Adding macros for setting lms2xx and lms1xx source directories
* Changed lms driver directory to lms2xx and created lms1xx drive directory in c++/drivers
* Fixed a bug concerning dynamically allocating strings on the stack of an active exception. Thanks to Philipp Aumayr and Simon Opelt for their original patch, which motivated this fix.
* Fixed quotation bug for newer versions of autoconf/aclocal.
See http://www.gnu.org/software/autoconf/manual/html_node/Quoting-and-Parameters.html
* Added stdlib.h to ld_config's main.cc and lms_config's main.cc
*
*
*
*
* Added ld_lite directory
* Addedd lms_lite directory
*
*
* Added ld_lite folder for ld_lite driver
* Added lms_lite directory for lms_lite driver
* lmsmex.cc now supports up to four separate Sick LMS units.
* Set lmsmex.cc to also return a vector of bearings for range and/or reflectivity values. The coordinate system corresponds to that defined in the Sick LMS 2xx manuals. Adjusted lms_cart and lms_stream examples to use this vector.
* Removed SickConfig.hh from the driver headers and adjusted the installation to leave out SickConfig.hh and the utility headers as per Tully's suggestion.
* Changed std::cerr to std::cout for printing 'cancel buffer monitor' string
* Adjusted m-file comments for sickld and sicklms
* Adjusted m-file comments
* Fixing permissions
* Still fixing file permissions
* Adjusting file permissions
* Took out std::cerr in bad checksum exception handler.
* Took out std::cerr in bad checksum exception handler.
* Monitor now clears buffer on bad checksum
* Monitor now clears msg container on bad checksum
* Fixed print-out in build_mex script
* Took out packed attribute for structs in SickLMS.hh.
* Removed try/catch in buffer monitor base
* Adjusted the examples to exit more cleanly.
* Fixed rm -r bug in build_mex and install_mex
* Adjusted configure.ac
* Fixing README
* testing
* Adjusted NEWS
* Modified INSTALL
* Fixing permissions on matlab/install_mex.
* Fixing permissions with mex bash script.
* Changed dates in mex installation bash scripts.
* Removed doc directory from c++/drivers/ld.
* Initial project import.
* Contributors: Chad Rockey, Chris Mansley, Jason Derenick, Michael Sands, Tom Miller, chadrockey

View File

@ -0,0 +1,121 @@
cmake_minimum_required(VERSION 2.8.3)
project(sicktoolbox)
find_package(catkin REQUIRED)
## System dependencies are found with CMake's conventions
find_package(Threads REQUIRED)
###################################
## catkin specific configuration ##
###################################
## The catkin_package macro generates cmake config files for your package
## Declare things to be passed to dependent projects
## LIBRARIES: libraries you create in this project that dependent projects also need
## CATKIN_DEPENDS: catkin_packages dependent projects also need
## DEPENDS: system dependencies of this project that dependent projects also need
catkin_package(
INCLUDE_DIRS include
LIBRARIES SickLD SickLMS1xx SickLMS2xx
CATKIN_DEPENDS
DEPENDS Threads
)
###########
## Build ##
###########
## Specify additional locations of header files
## Your package locations should be listed before other locations
include_directories(include ${catkin_INCLUDE_DIRS})
# Driver libraries
add_library(SickLD c++/drivers/ld/sickld/SickLD.cc c++/drivers/ld/sickld/SickLDBufferMonitor.cc c++/drivers/ld/sickld/SickLDMessage.cc)
target_link_libraries(SickLD ${catkin_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
add_library(SickLMS1xx c++/drivers/lms1xx/sicklms1xx/SickLMS1xx.cc c++/drivers/lms1xx/sicklms1xx/SickLMS1xxBufferMonitor.cc c++/drivers/lms1xx/sicklms1xx/SickLMS1xxMessage.cc)
target_link_libraries(SickLMS1xx ${catkin_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
add_library(SickLMS2xx c++/drivers/lms2xx/sicklms2xx/SickLMS2xx.cc c++/drivers/lms2xx/sicklms2xx/SickLMS2xxBufferMonitor.cc c++/drivers/lms2xx/sicklms2xx/SickLMS2xxMessage.cc)
target_link_libraries(SickLMS2xx ${catkin_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
# Examples
add_library(LDConfigLib c++/examples/ld/ld_config/src/ConfigFile.cpp)
add_executable(ld_config c++/examples/ld/ld_config/src/main.cc)
target_link_libraries(ld_config SickLD LDConfigLib ${catkin_LIBRARIES})
add_executable(ld_more_config c++/examples/ld/ld_more_config/src/main.cc)
target_link_libraries(ld_more_config SickLD ${catkin_LIBRARIES})
add_executable(ld_multi_sector c++/examples/ld/ld_multi_sector/src/main.cc)
target_link_libraries(ld_multi_sector SickLD ${catkin_LIBRARIES})
add_executable(ld_single_sector c++/examples/ld/ld_single_sector/src/main.cc)
target_link_libraries(ld_single_sector SickLD ${catkin_LIBRARIES})
add_executable(lms1xx_simple_app c++/examples/lms1xx/lms1xx_simple_app/src/main.cc)
target_link_libraries(lms1xx_simple_app SickLMS1xx ${catkin_LIBRARIES})
add_executable(lms2xx_config c++/examples/lms2xx/lms2xx_config/src/main.cc)
target_link_libraries(lms2xx_config SickLMS2xx ${catkin_LIBRARIES})
add_executable(lms2xx_mean_values c++/examples/lms2xx/lms2xx_mean_values/src/main.cc)
target_link_libraries(lms2xx_mean_values SickLMS2xx ${catkin_LIBRARIES})
add_executable(lms2xx_partial_scan c++/examples/lms2xx/lms2xx_partial_scan/src/main.cc)
target_link_libraries(lms2xx_partial_scan SickLMS2xx ${catkin_LIBRARIES})
add_executable(lms2xx_real_time_indices c++/examples/lms2xx/lms2xx_real_time_indices/src/main.cc)
target_link_libraries(lms2xx_real_time_indices SickLMS2xx ${catkin_LIBRARIES})
add_executable(lms2xx_set_variant c++/examples/lms2xx/lms2xx_set_variant/src/main.cc)
target_link_libraries(lms2xx_set_variant SickLMS2xx ${catkin_LIBRARIES})
add_executable(lms2xx_simple_app c++/examples/lms2xx/lms2xx_simple_app/src/main.cc)
target_link_libraries(lms2xx_simple_app SickLMS2xx ${catkin_LIBRARIES})
add_executable(lms2xx_stream_range_and_reflect c++/examples/lms2xx/lms2xx_stream_range_and_reflect/src/main.cc)
target_link_libraries(lms2xx_stream_range_and_reflect SickLMS2xx ${catkin_LIBRARIES})
add_executable(lms2xx_subrange c++/examples/lms2xx/lms2xx_subrange/src/main.cc)
target_link_libraries(lms2xx_subrange SickLMS2xx ${catkin_LIBRARIES})
#############
## Install ##
#############
# all install targets should use catkin DESTINATION variables
# See http://ros.org/doc/groovy/api/catkin/html/adv_user_guide/variables.html
## Mark executable scripts (Python etc.) for installation
## in contrast to setup.py, you can choose the destination
# install(PROGRAMS
# scripts/my_python_script
# DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
# )
## Mark executables and/or libraries for installation
install(TARGETS SickLD SickLMS1xx SickLMS2xx LDConfigLib ld_config
ld_more_config ld_multi_sector ld_single_sector lms1xx_simple_app
lms2xx_config lms2xx_mean_values lms2xx_partial_scan lms2xx_real_time_indices
lms2xx_set_variant lms2xx_simple_app lms2xx_stream_range_and_reflect lms2xx_subrange
ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)
## TODO Move headers that aren't needed externally back into the source
## Mark cpp header files for installation
install(DIRECTORY include/${PROJECT_NAME}/
DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
FILES_MATCHING PATTERN "*.hh"
PATTERN ".svn" EXCLUDE
)
## TODO There are readmes, etc, create install rules for these
## Mark other files for installation (e.g. launch and bag files, etc.)
# install(FILES
# # myfile1
# # myfile2
# DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}
# )

View File

@ -0,0 +1,39 @@
--------------------------------------------------------------------
--------------------------------------------------------------------
The Sick LIDAR Matlab/C++ Toolbox (BSD) License
--------------------------------------------------------------------
The Sick LIDAR Matlab/C++ Toolbox
Copyright (c) 2008, Jason C. Derenick and Thomas H. Miller
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the following
disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials
provided with the distribution.
* Neither the name(s) of the copyright holders nor the names
of its contributors may be used to endorse or promote products
derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------

View File

@ -0,0 +1,23 @@
-------------------------------------------------------------------
-------------------------------------------------------------------
The Sick LIDAR C++ Toolbox
-------------------------------------------------------------------
This is the ROS fork of the Sick LIDAR C++ Toolbox. If you're
looking for Matlab, please see the original at:
http://sicktoolbox.sourceforge.net/
*** Quick Start
To get up and running quickly with the toolbox, be sure to read
the quick start guide in the manuals directory. Additionally, to
enable 500Kbps communication via a USB-COMi-M be sure to see the
RS-422 tutorial in said directory.
*** Other Files
Please see the following documents for additional info:
COPYING - Information regarding the software license
AUTHORS - Information about the authors
THANKS - Acknowledgements
-------------------------------------------------------------------

View File

@ -0,0 +1,31 @@
-------------------------------------------------------------------
-------------------------------------------------------------------
The Sick LIDAR Matlab/C++ Toolbox
-------------------------------------------------------------------
The authors would like to express their sincere gratitude to the
following members of the Ben Franklin Racing Team for their key
insights and help in developing the toolbox:
Aleksandr Kushleyev
Tully Foote
Alex Stewart
Jon Bohren
Brian Satterfield
Professor Daniel Lee
Professor John Spetzer
Additionally, we'd like to thank Douglas Paul for his work on the
initial Sick LMS 2xx serial driver.
*** Additional Acknowledgments
This software makes use of the following open-source
packages for its package configuration:
doxample - by Oren Ben-kiki
http://www.ben-kiki.org/oren/doxample
acx_pthread - by Steven G. Johnson
http://autoconf-archive.cryp.to/acx_pthread.html
-------------------------------------------------------------------

View File

@ -0,0 +1 @@
# dummy

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,132 @@
/*!
* \file SickLDBufferMonitor.cc
* \brief Implements a class for monitoring the receive
* buffer when interfacing w/ a Sick LD LIDAR.
*
* Code by Jason C. Derenick and Thomas H. Miller.
* Contact derenick(at)lehigh(dot)edu
*
* The Sick LIDAR Matlab/C++ Toolbox
* Copyright (c) 2008, Jason C. Derenick and Thomas H. Miller
* All rights reserved.
*
* This software is released under a BSD Open-Source License.
* See http://sicktoolbox.sourceforge.net
*/
/* Auto-generated header */
#include <sicktoolbox/SickConfig.hh>
/* Implementation dependencies */
#include <iostream>
#include <sys/ioctl.h>
#include <sicktoolbox/SickLDBufferMonitor.hh>
#include <sicktoolbox/SickLDMessage.hh>
#include <sicktoolbox/SickException.hh>
#include <sicktoolbox/SickLDUtility.hh>
/* Associate the namespace */
namespace SickToolbox {
/**
* \brief A standard constructor
*/
SickLDBufferMonitor::SickLDBufferMonitor( ) : SickBufferMonitor< SickLDBufferMonitor, SickLDMessage >(this) { }
/**
* \brief Acquires the next message from the SickLD byte stream
* \param &sick_message The returned message object
*/
void SickLDBufferMonitor::GetNextMessageFromDataStream( SickLDMessage &sick_message ) throw( SickIOException ) {
/* Flush the input buffer */
uint8_t byte_buffer;
/* A buffer to hold the current byte out of the stream */
const uint8_t sick_response_header[4] = {0x02,'U','S','P'};
uint8_t checksum = 0;
uint8_t message_buffer[SickLDMessage::MESSAGE_MAX_LENGTH] = {0};
uint32_t payload_length = 0;
try {
/* Search for the header in the byte stream */
for (unsigned int i = 0; i < sizeof(sick_response_header);) {
/* Acquire the next byte from the stream */
_readBytes(&byte_buffer,1,DEFAULT_SICK_BYTE_TIMEOUT);
/* Check if the current byte matches the expected header byte */
if (byte_buffer == sick_response_header[i]) {
i++;
}
else {
i = 0;
}
}
/* Populate message buffer w/ response header */
memcpy(message_buffer,sick_response_header,4);
/* Acquire the payload length! */
_readBytes(&message_buffer[4],4,DEFAULT_SICK_BYTE_TIMEOUT);
/* Extract the payload size and adjust the byte order */
memcpy(&payload_length,&message_buffer[4],4);
payload_length = sick_ld_to_host_byte_order(payload_length);
/* Read the packet payload */
_readBytes(&message_buffer[8],payload_length,DEFAULT_SICK_BYTE_TIMEOUT);
/* Read the checksum */
_readBytes(&checksum,1,DEFAULT_SICK_BYTE_TIMEOUT);
/* Build the return message object based upon the received payload
* and compute the associated checksum.
*
* NOTE: In constructing this message we ignore the header bytes
* buffered since the BuildMessage routine will insert the
* correct header automatically and compute the payload's
* checksum for us. We could probably get away with using
* just ParseMessage here and not computing the checksum as
* we are using TCP. However, its safer this way.
*/
sick_message.BuildMessage(&message_buffer[SickLDMessage::MESSAGE_HEADER_LENGTH],payload_length);
/* Verify the checksum is correct (this is probably unnecessary since we are using TCP/IP) */
if (sick_message.GetChecksum() != checksum) {
throw SickBadChecksumException("SickLD::GetNextMessageFromDataStream: BAD CHECKSUM!!!");
}
/* Success */
}
catch(SickTimeoutException &sick_timeout) { /* This is ok! */ }
/* Catch a bad checksum! */
catch(SickBadChecksumException &sick_checksum_exception) {
sick_message.Clear(); // Clear the message container
}
/* Catch any serious IO buffer exceptions */
catch(SickIOException &sick_io_exception) {
throw;
}
/* A sanity check */
catch (...) {
throw;
}
}
/**
* \brief A standard destructor
*/
SickLDBufferMonitor::~SickLDBufferMonitor( ) { }
} /* namespace SickToolbox */

View File

@ -0,0 +1,153 @@
/*!
* \file SickLDMessage.cc
* \brief Implements the class SickLDMessage.
*
* Code by Jason C. Derenick and Thomas H. Miller.
* Contact derenick(at)lehigh(dot)edu
*
* The Sick LIDAR Matlab/C++ Toolbox
* Copyright (c) 2008, Jason C. Derenick and Thomas H. Miller
* All rights reserved.
*
* This software is released under a BSD Open-Source License.
* See http://sicktoolbox.sourceforge.net
*/
/* Auto-generated header */
#include <sicktoolbox/SickConfig.hh>
/* Implementation dependencies */
#include <iomanip>
#include <iostream>
#include <arpa/inet.h>
#include <sicktoolbox/SickLDMessage.hh>
#include <sicktoolbox/SickLDUtility.hh> // for byye-order conversions where necessary
/* Associate the namespace */
namespace SickToolbox {
/**
* \brief A default constructor
*/
SickLDMessage::SickLDMessage( ) :
SickMessage< SICK_LD_MSG_HEADER_LEN, SICK_LD_MSG_PAYLOAD_MAX_LEN, SICK_LD_MSG_TRAILER_LEN >() {
/* Initialize the object */
Clear();
}
/**
* \brief Another constructor.
* \param *payload_buffer The payload for the packet as an array of bytes (including the header)
* \param payload_length The length of the payload array in bytes
*/
SickLDMessage::SickLDMessage( const uint8_t * const payload_buffer, const unsigned int payload_length ) :
SickMessage< SICK_LD_MSG_HEADER_LEN, SICK_LD_MSG_PAYLOAD_MAX_LEN, SICK_LD_MSG_TRAILER_LEN >() {
/* Build the message object (implicit initialization) */
BuildMessage(payload_buffer,payload_length);
}
/**
* \brief Another constructor.
* \param *message_buffer A well-formed message to be parsed into the class' fields
*/
SickLDMessage::SickLDMessage( const uint8_t * const message_buffer ) :
SickMessage< SICK_LD_MSG_HEADER_LEN, SICK_LD_MSG_PAYLOAD_MAX_LEN, SICK_LD_MSG_TRAILER_LEN >() {
/* Parse the message into the container (implicit initialization) */
ParseMessage(message_buffer);
}
/**
* \brief Constructs a Sick LD message given parameter values
* \param *payload_buffer An address of the first byte to be copied into the message's payload
* \param payload_length The number of bytes to be copied into the message buffer
*/
void SickLDMessage::BuildMessage( const uint8_t * const payload_buffer, const unsigned int payload_length ) {
/* Call the parent method
* NOTE: The parent method resets the object and assigns _message_length, _payload_length,
* _populated and copies the payload into the message buffer at the correct position
*/
SickMessage< SICK_LD_MSG_HEADER_LEN, SICK_LD_MSG_PAYLOAD_MAX_LEN, SICK_LD_MSG_TRAILER_LEN >
::BuildMessage(payload_buffer,payload_length);
/*
* Set the message header!
*/
_message_buffer[0] = 0x02; // STX
_message_buffer[1] = 'U'; // User
_message_buffer[2] = 'S'; // Service
_message_buffer[3] = 'P'; // Protocol
/* Include the payload length in the header */
uint32_t payload_length_32 = host_to_sick_ld_byte_order((uint32_t)_payload_length);
memcpy(&_message_buffer[4],&payload_length_32,4);
/*
* Set the message trailer (just a checksum)!
*/
_message_buffer[_message_length-1] = _computeXOR(&_message_buffer[8],(uint32_t)_payload_length);
}
/**
* \brief Parses a sequence of bytes into a SickLDMessage object
* \param *message_buffer A well-formed message to be parsed into the class' fields
*/
void SickLDMessage::ParseMessage( const uint8_t * const message_buffer ) {
/* Call the parent method
* NOTE: This method resets the object and assigns _populated as true
*/
SickMessage< SICK_LD_MSG_HEADER_LEN, SICK_LD_MSG_PAYLOAD_MAX_LEN, SICK_LD_MSG_TRAILER_LEN >
::ParseMessage(message_buffer);
/* Extract the payload length */
uint32_t payload_length_32 = 0;
memcpy(&payload_length_32,&message_buffer[4],4);
_payload_length = (unsigned int)sick_ld_to_host_byte_order(payload_length_32);
/* Compute the total message length */
_message_length = MESSAGE_HEADER_LENGTH + MESSAGE_TRAILER_LENGTH + _payload_length;
/* Copy the given packet into the buffer */
memcpy(_message_buffer,message_buffer,_message_length);
}
/**
* \brief Print the message contents.
*/
void SickLDMessage::Print( ) const {
std::cout.setf(std::ios::hex,std::ios::basefield);
std::cout << "Checksum: " << (unsigned int) GetChecksum() << std::endl;
std::cout << "Service code: " << (unsigned int) GetServiceCode() << std::endl;
std::cout << "Service subcode: " << (unsigned int) GetServiceSubcode() << std::endl;
std::cout << std::flush;
/* Call parent's print function */
SickMessage< SICK_LD_MSG_HEADER_LEN, SICK_LD_MSG_PAYLOAD_MAX_LEN, SICK_LD_MSG_TRAILER_LEN >::Print();
}
/**
* \brief Compute the message checksum (single-byte XOR).
* \param data The address of the first data element in a sequence of bytes to be included in the sum
* \param length The number of byte in the data sequence
*/
uint8_t SickLDMessage::_computeXOR( const uint8_t * const data, const uint32_t length ) {
/* Compute the XOR by summing all of the bytes */
uint8_t checksum = 0;
for (uint32_t i = 0; i < length; i++) {
checksum ^= data[i]; // NOTE: this is equivalent to simply summing all of the bytes
}
/* done */
return checksum;
}
SickLDMessage::~SickLDMessage( ) { }
} /* namespace SickToolbox */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,127 @@
/*!
* \file SickLMS1xxBufferMonitor.cc
* \brief Implements a class for monitoring the receive
* buffer when interfacing w/ a Sick LMS 1xx LIDAR.
*
* Code by Jason C. Derenick and Christopher R. Mansley.
* Contact jasonder(at)seas(dot)upenn(dot)edu
*
* The Sick LIDAR Matlab/C++ Toolbox
* Copyright (c) 2009, Jason C. Derenick and Christopher R. Mansley
* All rights reserved.
*
* This software is released under a BSD Open-Source License.
* See http://sicktoolbox.sourceforge.net
*/
/* Auto-generated header */
#include <sicktoolbox/SickConfig.hh>
/* Implementation dependencies */
#include <iostream>
#include <sys/ioctl.h>
#include <sicktoolbox/SickLMS1xxBufferMonitor.hh>
#include <sicktoolbox/SickLMS1xxMessage.hh>
#include <sicktoolbox/SickLMS1xxUtility.hh>
#include <sicktoolbox/SickException.hh>
/* Associate the namespace */
namespace SickToolbox {
/**
* \brief A standard constructor
*/
SickLMS1xxBufferMonitor::SickLMS1xxBufferMonitor( ) : SickBufferMonitor< SickLMS1xxBufferMonitor, SickLMS1xxMessage >(this) { }
/**
* \brief Acquires the next message from the SickLMS1xx byte stream
* \param &sick_message The returned message object
*/
void SickLMS1xxBufferMonitor::GetNextMessageFromDataStream( SickLMS1xxMessage &sick_message ) throw( SickIOException ) {
/* Flush the input buffer */
uint8_t byte_buffer = 0;
uint8_t payload_buffer[SickLMS1xxMessage::MESSAGE_PAYLOAD_MAX_LENGTH] = {0};
try {
/* Flush the TCP receive buffer */
_flushTCPRecvBuffer();
/* Search for STX in the byte stream */
do {
/* Grab the next byte from the stream */
_readBytes(&byte_buffer,1,DEFAULT_SICK_LMS_1XX_BYTE_TIMEOUT);
}
while (byte_buffer != 0x02);
/* Ok, now acquire the payload! (until ETX) */
int payload_length = 0;
do {
payload_length++;
_readBytes(&payload_buffer[payload_length-1],1,DEFAULT_SICK_LMS_1XX_BYTE_TIMEOUT);
}
while (payload_buffer[payload_length-1] != 0x03);
payload_length--;
/* Build the return message object based upon the received payload
* NOTE: In constructing this message we ignore the header bytes
* buffered since the BuildMessage routine will insert the
* correct header automatically and verify the message size
*/
sick_message.BuildMessage(payload_buffer,payload_length);
/* Success */
}
catch(SickTimeoutException &sick_timeout) { /* This is ok! */ }
/* Catch any serious IO buffer exceptions */
catch(SickIOException &sick_io_exception) {
throw;
}
/* A sanity check */
catch (...) {
throw;
}
}
/**
* \brief Flushes TCP receive buffer contents
*/
void SickLMS1xxBufferMonitor::_flushTCPRecvBuffer( ) const throw (SickIOException) {
char null_byte;
int num_bytes_waiting = 0;
/* Acquire number of awaiting bytes */
if (ioctl(_sick_fd,FIONREAD,&num_bytes_waiting)) {
throw SickIOException("SickLMS1xxBufferMonitor::_flushTCPRecvBuffer: ioctl() failed!");
}
/* Flush awaiting bytes */
for (int i = 0; i < num_bytes_waiting; i++) {
/* Capture a single byte from the stream! */
if (read(_sick_fd,&null_byte,1) != 1) {
throw SickIOException("SickLMS1xxBufferMonitor::_flushTCPRecvBuffer: ioctl() failed!");
}
}
}
/**
* \brief A standard destructor
*/
SickLMS1xxBufferMonitor::~SickLMS1xxBufferMonitor( ) { }
} /* namespace SickToolbox */

View File

@ -0,0 +1,201 @@
/*!
* \file SickLMS1xxMessage.cc
* \brief Implements the class SickLMS1xxMessage.
*
* Code by Jason C. Derenick and Christopher R. Mansley.
* Contact jasonder(at)seas(dot)upenn(dot)edu
*
* The Sick LIDAR Matlab/C++ Toolbox
* Copyright (c) 2009, Jason C. Derenick and Christopher R. Mansley
* All rights reserved.
*
* This software is released under a BSD Open-Source License.
* See http://sicktoolbox.sourceforge.net
*/
/* Auto-generated header */
#include <sicktoolbox/SickConfig.hh>
/* Implementation dependencies */
#include <iomanip>
#include <iostream>
#include <arpa/inet.h>
#include <sicktoolbox/SickLMS1xxMessage.hh>
#include <sicktoolbox/SickLMS1xxUtility.hh> // for byye-order conversions where necessary
/* Associate the namespace */
namespace SickToolbox {
/**
* \brief A default constructor
*/
SickLMS1xxMessage::SickLMS1xxMessage( ) :
SickMessage< SICK_LMS_1XX_MSG_HEADER_LEN, SICK_LMS_1XX_MSG_PAYLOAD_MAX_LEN, SICK_LMS_1XX_MSG_TRAILER_LEN >(),
_command_type(""),
_command("")
{
/* Initialize the object */
Clear();
}
/**
* \brief Another constructor.
* \param *payload_buffer The payload for the packet as an array of bytes (including the header)
* \param payload_length The length of the payload array in bytes
*/
SickLMS1xxMessage::SickLMS1xxMessage( const uint8_t * const payload_buffer, const unsigned int payload_length ) :
SickMessage< SICK_LMS_1XX_MSG_HEADER_LEN, SICK_LMS_1XX_MSG_PAYLOAD_MAX_LEN, SICK_LMS_1XX_MSG_TRAILER_LEN >(),
_command_type("Unknown"),
_command("Unknown")
{
/* Build the message object (implicit initialization) */
BuildMessage(payload_buffer,payload_length);
}
/**
* \brief Another constructor.
* \param *message_buffer A well-formed message to be parsed into the class' fields
*/
SickLMS1xxMessage::SickLMS1xxMessage( const uint8_t * const message_buffer ) :
SickMessage< SICK_LMS_1XX_MSG_HEADER_LEN, SICK_LMS_1XX_MSG_PAYLOAD_MAX_LEN, SICK_LMS_1XX_MSG_TRAILER_LEN >(),
_command_type("Unknown"),
_command("Unknown")
{
/* Parse the message into the container (implicit initialization) */
ParseMessage(message_buffer);
}
/**
* \brief Constructs a well-formed Sick LMS 1xx message
* \param *payload_buffer An address of the first byte to be copied into the message's payload
* \param payload_length The number of bytes to be copied into the message buffer
*/
void SickLMS1xxMessage::BuildMessage( const uint8_t * const payload_buffer, const unsigned int payload_length ) {
/* Call the parent method
* NOTE: The parent method resets the object and assigns _message_length, _payload_length,
* _populated and copies the payload into the message buffer at the correct position
*/
SickMessage< SICK_LMS_1XX_MSG_HEADER_LEN, SICK_LMS_1XX_MSG_PAYLOAD_MAX_LEN, SICK_LMS_1XX_MSG_TRAILER_LEN >
::BuildMessage(payload_buffer,payload_length);
/*
* Set the message header!
*/
_message_buffer[0] = 0x02; // STX
/*
* Set the message trailer!
*/
_message_buffer[_message_length-1] = 0x03; // ETX
/* Grab the (3-byte) command type */
char command_type[4] = {0};
for (int i = 0; i < 3; i++) {
command_type[i] = _message_buffer[i+1];
}
command_type[4] = '\0';
_command_type = command_type;
/* Grab the command (max length is 14 bytes) */
char command[15] = {0};
int i = 0;
for (; (i < 14) && (_message_buffer[5+i] != 0x20); i++) {
command[i] = _message_buffer[5+i];
}
command[i] = '\0';
_command = command;
}
/**
* \brief Parses a sequence of bytes into a SickLMS1xxMessage object
* \param *message_buffer A well-formed message to be parsed into the class' fields
*/
void SickLMS1xxMessage::ParseMessage( const uint8_t * const message_buffer ) throw (SickIOException) {
/* Call the parent method
* NOTE: This method resets the object and assigns _populated as true
*/
SickMessage< SICK_LMS_1XX_MSG_HEADER_LEN, SICK_LMS_1XX_MSG_PAYLOAD_MAX_LEN, SICK_LMS_1XX_MSG_TRAILER_LEN >
::ParseMessage(message_buffer);
/* Compute the message length */
int i = 1;
const char * token = NULL;
while (message_buffer[i-1] != 0x03) {
if (i == 1) {
/* Grab the command type */
if ((token = strtok((char *)&_message_buffer[1]," ")) == NULL) {
throw SickIOException("SickLMS1xxMessage::ParseMessage: strtok() failed!");
}
_command_type = token;
/* Grab the Command Code */
if ((token = strtok(NULL," ")) == NULL) {
throw SickIOException("SickLMS1xxMessage::ParseMessage: strtok() failed!");
}
_command = token;
}
i++; // Update message length
/* A sanity check */
if (i > SickLMS1xxMessage::MESSAGE_MAX_LENGTH) {
throw SickIOException("SickLMS1xxMessage::ParseMessage: Message Exceeds Max Message Length!");
}
}
/* Compute the total message length */
_payload_length = _message_length - MESSAGE_HEADER_LENGTH - MESSAGE_TRAILER_LENGTH;
/* Copy the given packet into the buffer */
memcpy(_message_buffer,message_buffer,_message_length);
}
/**
* \brief Reset all internal fields and buffers associated with the object.
*/
void SickLMS1xxMessage::Clear( ) {
/* Call the parent method and clear out class' protected members */
SickMessage< SICK_LMS_1XX_MSG_HEADER_LEN, SICK_LMS_1XX_MSG_PAYLOAD_MAX_LEN, SICK_LMS_1XX_MSG_TRAILER_LEN >::Clear();
/* Reset the class' additional fields */
_command_type = "Unknown";
_command = "Unknown";
}
/**
* \brief Print the message contents.
*/
void SickLMS1xxMessage::Print( ) const {
//std::cout.setf(std::ios::hex,std::ios::basefield);
std::cout << "Command Type: " << GetCommandType() << std::endl;
std::cout << "Command Code: " << GetCommand() << std::endl;
std::cout << std::flush;
/* Call parent's print function */
SickMessage< SICK_LMS_1XX_MSG_HEADER_LEN, SICK_LMS_1XX_MSG_PAYLOAD_MAX_LEN, SICK_LMS_1XX_MSG_TRAILER_LEN >::Print();
}
SickLMS1xxMessage::~SickLMS1xxMessage( ) { }
} /* namespace SickToolbox */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,133 @@
/*!
* \file SickLMS2xxBufferMonitor.cc
* \brief Implements a class for monitoring the receive
* buffer when interfacing w/ a Sick LMS 2xx LIDAR.
*
* Code by Jason C. Derenick and Thomas H. Miller.
* Contact derenick(at)lehigh(dot)edu
*
* The Sick LIDAR Matlab/C++ Toolbox
* Copyright (c) 2008, Jason C. Derenick and Thomas H. Miller
* All rights reserved.
*
* This software is released under a BSD Open-Source License.
* See http://sicktoolbox.sourceforge.net
*/
/* Auto-generated header */
#include <sicktoolbox/SickConfig.hh>
/* Implementation dependencies */
#include <iostream>
#include <termios.h>
#include <sicktoolbox/SickLMS2xx.hh>
#include <sicktoolbox/SickLMS2xxBufferMonitor.hh>
#include <sicktoolbox/SickLMS2xxMessage.hh>
#include <sicktoolbox/SickLMS2xxUtility.hh>
#include <sicktoolbox/SickException.hh>
/* Associate the namespace */
namespace SickToolbox {
/**
* \brief A standard constructor
*/
SickLMS2xxBufferMonitor::SickLMS2xxBufferMonitor( ) : SickBufferMonitor<SickLMS2xxBufferMonitor,SickLMS2xxMessage>(this) { }
/**
* \brief Acquires the next message from the SickLMS2xx byte stream
* \param &sick_message The returned message object
*/
void SickLMS2xxBufferMonitor::GetNextMessageFromDataStream( SickLMS2xxMessage &sick_message ) throw( SickIOException ) {
uint8_t search_buffer[2] = {0};
uint8_t payload_length_buffer[2] = {0};
uint8_t payload_buffer[SickLMS2xxMessage::MESSAGE_PAYLOAD_MAX_LENGTH] = {0};
uint8_t checksum_buffer[2] = {0};
uint16_t payload_length, checksum;
try {
/* Drain the I/O buffers! */
if (tcdrain(_sick_fd) != 0) {
throw SickIOException("SickLMS2xxBufferMonitor::GetNextMessageFromDataStream: tcdrain failed!");
}
/* Read until we get a valid message header */
unsigned int bytes_searched = 0;
while(search_buffer[0] != 0x02 || search_buffer[1] != DEFAULT_SICK_LMS_2XX_HOST_ADDRESS) {
/* Slide the search window */
search_buffer[0] = search_buffer[1];
/* Attempt to read in another byte */
_readBytes(&search_buffer[1],1,DEFAULT_SICK_LMS_2XX_SICK_BYTE_TIMEOUT);
/* Header should be no more than max message length + header length bytes away */
if (bytes_searched > SickLMS2xxMessage::MESSAGE_MAX_LENGTH + SickLMS2xxMessage::MESSAGE_HEADER_LENGTH) {
throw SickTimeoutException("SickLMS2xxBufferMonitor::GetNextMessageFromDataStream: header timeout!");
}
/* Increment the number of bytes searched */
bytes_searched++;
}
/* Read until we receive the payload length or we timeout */
_readBytes(payload_length_buffer,2,DEFAULT_SICK_LMS_2XX_SICK_BYTE_TIMEOUT);
/* Extract the payload length */
memcpy(&payload_length,payload_length_buffer,2);
payload_length = sick_lms_2xx_to_host_byte_order(payload_length);
/* Make sure the payload length is legitimate, otherwise disregard */
if (payload_length <= SickLMS2xxMessage::MESSAGE_MAX_LENGTH) {
/* Read until we receive the payload or we timeout */
_readBytes(payload_buffer,payload_length,DEFAULT_SICK_LMS_2XX_SICK_BYTE_TIMEOUT);
/* Read until we receive the checksum or we timeout */
_readBytes(checksum_buffer,2,DEFAULT_SICK_LMS_2XX_SICK_BYTE_TIMEOUT);
/* Copy into uint16_t so it can be used */
memcpy(&checksum,checksum_buffer,2);
checksum = sick_lms_2xx_to_host_byte_order(checksum);
/* Build a frame and compute the crc */
sick_message.BuildMessage(DEFAULT_SICK_LMS_2XX_HOST_ADDRESS,payload_buffer,payload_length);
/* See if the checksums match */
if(sick_message.GetChecksum() != checksum) {
throw SickBadChecksumException("SickLMS2xx::GetNextMessageFromDataStream: CRC16 failed!");
}
}
}
catch(SickTimeoutException &sick_timeout_exception) { /* This is ok! */ }
/* Handle a bad checksum! */
catch(SickBadChecksumException &sick_checksum_exception) {
sick_message.Clear(); // Clear the message container
}
/* Handle any serious IO exceptions */
catch(SickIOException &sick_io_exception) {
throw;
}
/* A sanity check */
catch (...) {
throw;
}
}
/**
* \brief A standard destructor
*/
SickLMS2xxBufferMonitor::~SickLMS2xxBufferMonitor( ) { }
} /* namespace SickToolbox */

View File

@ -0,0 +1,181 @@
/*!
* \file SickLMS2xxMessage.cc
* \brief Implementation of class SickFrame.
*
* Code by Jason C. Derenick and Thomas H. Miller.
* Contact derenick(at)lehigh(dot)edu
*
* The Sick LIDAR Matlab/C++ Toolbox
* Copyright (c) 2008, Jason C. Derenick and Thomas H. Miller
* All rights reserved.
*
* This software is released under a BSD Open-Source License.
* See http://sicktoolbox.sourceforge.net
*/
/* Auto-generated header */
#include <sicktoolbox/SickConfig.hh>
/* Implementation dependencies */
#include <iomanip>
#include <iostream>
#include <sicktoolbox/SickLMS2xxMessage.hh>
#include <sicktoolbox/SickLMS2xxUtility.hh>
/* Associate the namespace */
namespace SickToolbox {
/*!
* \brief A default constructor
*/
SickLMS2xxMessage::SickLMS2xxMessage( ) {
/* Initialize the object */
Clear();
}
/*!
* \brief A constructor for building a message from the given parameter values
* \param dest_address The source address of the message
* \param payload_buffer The payload of the message as an array of bytes (including the command code)
* \param payload_length The length of the payload array in bytes
*/
SickLMS2xxMessage::SickLMS2xxMessage( const uint8_t dest_address, const uint8_t * const payload_buffer, const unsigned int payload_length ) :
SickMessage< SICK_LMS_2XX_MSG_HEADER_LEN, SICK_LMS_2XX_MSG_PAYLOAD_MAX_LEN, SICK_LMS_2XX_MSG_TRAILER_LEN >() {
/* Build the message */
BuildMessage(dest_address,payload_buffer,payload_length);
}
/*!
* \brief A constructor for parsing a byte sequence into a message object
* \param message_buffer A well-formed message to be parsed into the class' fields
*/
SickLMS2xxMessage::SickLMS2xxMessage( uint8_t * const message_buffer ) :
SickMessage< SICK_LMS_2XX_MSG_HEADER_LEN, SICK_LMS_2XX_MSG_PAYLOAD_MAX_LEN, SICK_LMS_2XX_MSG_TRAILER_LEN >() {
/* Parse the byte sequence into a message object */
ParseMessage(message_buffer);
}
/*!
* \brief Consructs a message object from given parameter values
* \param dest_address The destination address of the frame
* \param *payload_buffer The payload for the frame as an array of bytes (including the command code)
* \param payload_length The length of the payload array in bytes
*/
void SickLMS2xxMessage::BuildMessage( const uint8_t dest_address, const uint8_t * const payload_buffer,
const unsigned int payload_length ) {
/* Call the parent method!
* NOTE: The parent method resets the object and assigns _message_length, _payload_length,
* _populated and copies the payload into the message buffer at the correct position
*/
SickMessage< SICK_LMS_2XX_MSG_HEADER_LEN, SICK_LMS_2XX_MSG_PAYLOAD_MAX_LEN, SICK_LMS_2XX_MSG_TRAILER_LEN >
::BuildMessage(payload_buffer,payload_length);
/*
* Set the message header!
*/
_message_buffer[0] = 0x02; // Start of transmission (stx)
_message_buffer[1] = dest_address; // Sick LMS address
/* Include the payload length in the header */
uint16_t payload_length_16 = host_to_sick_lms_2xx_byte_order((uint16_t)_payload_length);
memcpy(&_message_buffer[2],&payload_length_16,2);
/*
* Set the message trailer!
*/
_checksum = host_to_sick_lms_2xx_byte_order(_computeCRC(_message_buffer,_payload_length+4));
memcpy(&_message_buffer[_payload_length+4],&_checksum,2);
}
/*!
* \brief Parses a sequence of bytes into a well-formed message
* \param *message_buffer The buffer containing the source message
*/
void SickLMS2xxMessage::ParseMessage( const uint8_t * const message_buffer ) {
/* Call the parent method!
* NOTE: This method resets the object and assigns _populated as true
*/
SickMessage< SICK_LMS_2XX_MSG_HEADER_LEN, SICK_LMS_2XX_MSG_PAYLOAD_MAX_LEN, SICK_LMS_2XX_MSG_TRAILER_LEN >
::ParseMessage(message_buffer);
/* Extract the payload length */
uint16_t payload_length_16 = 0;
memcpy(&payload_length_16,&message_buffer[2],2);
_payload_length = (unsigned int)sick_lms_2xx_to_host_byte_order(payload_length_16);
/* Compute the total message length */
_message_length = MESSAGE_HEADER_LENGTH + MESSAGE_TRAILER_LENGTH + _payload_length;
/* Copy the give message into the buffer */
memcpy(_message_buffer, message_buffer,_message_length);
/* Extract the checksum from the frame */
memcpy(&_checksum,&_message_buffer[_payload_length+MESSAGE_HEADER_LENGTH],2);
_checksum = sick_lms_2xx_to_host_byte_order(_checksum);
}
/*!
* \brief Reset all internal fields and buffers associated with the object.
*/
void SickLMS2xxMessage::Clear( ) {
/* Call the parent method and clear out class' protected members */
SickMessage< SICK_LMS_2XX_MSG_HEADER_LEN, SICK_LMS_2XX_MSG_PAYLOAD_MAX_LEN, SICK_LMS_2XX_MSG_TRAILER_LEN >::Clear();
/* Reset the class' additional fields */
_checksum = 0;
}
/*!
* \brief Print the message contents.
*/
void SickLMS2xxMessage::Print( ) const {
std::cout.setf(std::ios::hex,std::ios::basefield);
std::cout << "Checksum: " << (unsigned int) GetChecksum() << std::endl;
std::cout << "Dest. Addr.: " << (unsigned int) GetDestAddress() << std::endl;
std::cout << "Command Code: " << (unsigned int) GetCommandCode() << std::endl;
std::cout << std::flush;
/* Call parent's print function */
SickMessage< SICK_LMS_2XX_MSG_HEADER_LEN, SICK_LMS_2XX_MSG_PAYLOAD_MAX_LEN, SICK_LMS_2XX_MSG_TRAILER_LEN >::Print();
}
/*!
* \brief Computes the CRC16 of the given data buffer
* \param data An array of bytes whose checksum to compute
* \param len The length of the data array
* \return CRC16 computed over given data buffer
*/
uint16_t SickLMS2xxMessage::_computeCRC( uint8_t * data, unsigned int data_length ) const {
uint16_t uCrc16;
uint8_t abData[2];
uCrc16 = abData[0] = 0;
while (data_length-- ) {
abData[1] = abData[0];
abData[0] = *data++;
if(uCrc16 & 0x8000) {
uCrc16 = (uCrc16 & 0x7fff) << 1;
uCrc16 ^= CRC16_GEN_POL;
}
else {
uCrc16 <<= 1;
}
uCrc16 ^= MKSHORT(abData[0],abData[1]);
}
return uCrc16;
}
SickLMS2xxMessage::~SickLMS2xxMessage( ) { }
} /* namespace SickToolbox */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,21 @@
###############################################################
#
# The Sick LIDAR Matlab/C++ Toolbox
#
# File: sickld.conf
# Auth: Jason Derenick and Thomas Miller at Lehigh University
# Cont: derenick(at)lehigh(dot)edu
# Date: 20 July 2007
#
# Desc: Sample config file for ld_config utility.
#
###############################################################
# Define the Sick LD motor speed (Hz)
SICK_LD_MOTOR_SPEED = 10
# Define the Sick LD scan res. (angle step) in degrees
SICK_LD_SCAN_RESOLUTION = 0.5
# Define the active scan areas for the device
SICK_LD_SCAN_AREAS = [90 270] [315 45]

View File

@ -0,0 +1,3 @@
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<link href="doxygen.css" rel="stylesheet" type="text/css">
<link href="tabs.css" rel="stylesheet" type="text/css">

View File

@ -0,0 +1 @@
# dummy

View File

@ -0,0 +1,142 @@
// ConfigFile.cpp
#include "ConfigFile.h"
using std::string;
ConfigFile::ConfigFile( string filename, string delimiter,
string comment, string sentry )
: myDelimiter(delimiter), myComment(comment), mySentry(sentry)
{
// Construct a ConfigFile, getting keys and values from given file
std::ifstream in( filename.c_str() );
if( !in ) throw file_not_found( filename );
in >> (*this);
}
ConfigFile::ConfigFile()
: myDelimiter( string(1,'=') ), myComment( string(1,'#') )
{
// Construct a ConfigFile without a file; empty
}
void ConfigFile::remove( const string& key )
{
// Remove key and its value
myContents.erase( myContents.find( key ) );
return;
}
bool ConfigFile::keyExists( const string& key ) const
{
// Indicate whether key is found
mapci p = myContents.find( key );
return ( p != myContents.end() );
}
/* static */
void ConfigFile::trim( string& s )
{
// Remove leading and trailing whitespace
static const char whitespace[] = " \n\t\v\r\f";
s.erase( 0, s.find_first_not_of(whitespace) );
s.erase( s.find_last_not_of(whitespace) + 1U );
}
std::ostream& operator<<( std::ostream& os, const ConfigFile& cf )
{
// Save a ConfigFile to os
for( ConfigFile::mapci p = cf.myContents.begin();
p != cf.myContents.end();
++p )
{
os << p->first << " " << cf.myDelimiter << " ";
os << p->second << std::endl;
}
return os;
}
std::istream& operator>>( std::istream& is, ConfigFile& cf )
{
// Load a ConfigFile from is
// Read in keys and values, keeping internal whitespace
typedef string::size_type pos;
const string& delim = cf.myDelimiter; // separator
const string& comm = cf.myComment; // comment
const string& sentry = cf.mySentry; // end of file sentry
const pos skip = delim.length(); // length of separator
string nextline = ""; // might need to read ahead to see where value ends
while( is || nextline.length() > 0 )
{
// Read an entire line at a time
string line;
if( nextline.length() > 0 )
{
line = nextline; // we read ahead; use it now
nextline = "";
}
else
{
std::getline( is, line );
}
// Ignore comments
line = line.substr( 0, line.find(comm) );
// Check for end of file sentry
if( sentry != "" && line.find(sentry) != string::npos ) return is;
// Parse the line if it contains a delimiter
pos delimPos = line.find( delim );
if( delimPos < string::npos )
{
// Extract the key
string key = line.substr( 0, delimPos );
line.replace( 0, delimPos+skip, "" );
// See if value continues on the next line
// Stop at blank line, next line with a key, end of stream,
// or end of file sentry
bool terminate = false;
while( !terminate && is )
{
std::getline( is, nextline );
terminate = true;
string nlcopy = nextline;
ConfigFile::trim(nlcopy);
if( nlcopy == "" ) continue;
nextline = nextline.substr( 0, nextline.find(comm) );
if( nextline.find(delim) != string::npos )
continue;
if( sentry != "" && nextline.find(sentry) != string::npos )
continue;
nlcopy = nextline;
ConfigFile::trim(nlcopy);
if( nlcopy != "" ) line += "\n";
line += nextline;
terminate = false;
}
// Store key and value
ConfigFile::trim(key);
ConfigFile::trim(line);
cf.myContents[key] = line; // overwrites if key is repeated
}
}
return is;
}

View File

@ -0,0 +1,253 @@
// ConfigFile.h
// Class for reading named values from configuration files
// Richard J. Wagner v2.1 24 May 2004 wagnerr@umich.edu
// Copyright (c) 2004 Richard J. Wagner
//
// 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.
// Typical usage
// -------------
//
// Given a configuration file "settings.inp":
// atoms = 25
// length = 8.0 # nanometers
// name = Reece Surcher
//
// Named values are read in various ways, with or without default values:
// ConfigFile config( "settings.inp" );
// int atoms = config.read<int>( "atoms" );
// double length = config.read( "length", 10.0 );
// string author, title;
// config.readInto( author, "name" );
// config.readInto( title, "title", string("Untitled") );
//
// See file example.cpp for more examples.
#ifndef CONFIGFILE_H
#define CONFIGFILE_H
#include <string>
#include <map>
#include <iostream>
#include <fstream>
#include <sstream>
using std::string;
class ConfigFile {
// Data
protected:
string myDelimiter; // separator between key and value
string myComment; // separator between value and comments
string mySentry; // optional string to signal end of file
std::map<string,string> myContents; // extracted keys and values
typedef std::map<string,string>::iterator mapi;
typedef std::map<string,string>::const_iterator mapci;
// Methods
public:
ConfigFile( string filename,
string delimiter = "=",
string comment = "#",
string sentry = "EndConfigFile" );
ConfigFile();
// Search for key and read value or optional default value
template<class T> T read( const string& key ) const; // call as read<T>
template<class T> T read( const string& key, const T& value ) const;
template<class T> bool readInto( T& var, const string& key ) const;
template<class T>
bool readInto( T& var, const string& key, const T& value ) const;
// Modify keys and values
template<class T> void add( string key, const T& value );
void remove( const string& key );
// Check whether key exists in configuration
bool keyExists( const string& key ) const;
// Check or change configuration syntax
string getDelimiter() const { return myDelimiter; }
string getComment() const { return myComment; }
string getSentry() const { return mySentry; }
string setDelimiter( const string& s )
{ string old = myDelimiter; myDelimiter = s; return old; }
string setComment( const string& s )
{ string old = myComment; myComment = s; return old; }
// Write or read configuration
friend std::ostream& operator<<( std::ostream& os, const ConfigFile& cf );
friend std::istream& operator>>( std::istream& is, ConfigFile& cf );
protected:
template<class T> static string T_as_string( const T& t );
template<class T> static T string_as_T( const string& s );
static void trim( string& s );
// Exception types
public:
struct file_not_found {
string filename;
file_not_found( const string& filename_ = string() )
: filename(filename_) {} };
struct key_not_found { // thrown only by T read(key) variant of read()
string key;
key_not_found( const string& key_ = string() )
: key(key_) {} };
};
/* static */
template<class T>
string ConfigFile::T_as_string( const T& t )
{
// Convert from a T to a string
// Type T must support << operator
std::ostringstream ost;
ost << t;
return ost.str();
}
/* static */
template<class T>
T ConfigFile::string_as_T( const string& s )
{
// Convert from a string to a T
// Type T must support >> operator
T t;
std::istringstream ist(s);
ist >> t;
return t;
}
/* static */
template<>
inline string ConfigFile::string_as_T<string>( const string& s )
{
// Convert from a string to a string
// In other words, do nothing
return s;
}
/* static */
template<>
inline bool ConfigFile::string_as_T<bool>( const string& s )
{
// Convert from a string to a bool
// Interpret "false", "F", "no", "n", "0" as false
// Interpret "true", "T", "yes", "y", "1", "-1", or anything else as true
bool b = true;
string sup = s;
for( string::iterator p = sup.begin(); p != sup.end(); ++p )
*p = toupper(*p); // make string all caps
if( sup==string("FALSE") || sup==string("F") ||
sup==string("NO") || sup==string("N") ||
sup==string("0") || sup==string("NONE") )
b = false;
return b;
}
template<class T>
T ConfigFile::read( const string& key ) const
{
// Read the value corresponding to key
mapci p = myContents.find(key);
if( p == myContents.end() ) throw key_not_found(key);
return string_as_T<T>( p->second );
}
template<class T>
T ConfigFile::read( const string& key, const T& value ) const
{
// Return the value corresponding to key or given default value
// if key is not found
mapci p = myContents.find(key);
if( p == myContents.end() ) return value;
return string_as_T<T>( p->second );
}
template<class T>
bool ConfigFile::readInto( T& var, const string& key ) const
{
// Get the value corresponding to key and store in var
// Return true if key is found
// Otherwise leave var untouched
mapci p = myContents.find(key);
bool found = ( p != myContents.end() );
if( found ) var = string_as_T<T>( p->second );
return found;
}
template<class T>
bool ConfigFile::readInto( T& var, const string& key, const T& value ) const
{
// Get the value corresponding to key and store in var
// Return true if key is found
// Otherwise set var to given default
mapci p = myContents.find(key);
bool found = ( p != myContents.end() );
if( found )
var = string_as_T<T>( p->second );
else
var = value;
return found;
}
template<class T>
void ConfigFile::add( string key, const T& value )
{
// Add a key with given value
string v = T_as_string( value );
trim(key);
trim(v);
myContents[key] = v;
return;
}
#endif // CONFIGFILE_H
// Release notes:
// v1.0 21 May 1999
// + First release
// + Template read() access only through non-member readConfigFile()
// + ConfigurationFileBool is only built-in helper class
//
// v2.0 3 May 2002
// + Shortened name from ConfigurationFile to ConfigFile
// + Implemented template member functions
// + Changed default comment separator from % to #
// + Enabled reading of multiple-line values
//
// v2.1 24 May 2004
// + Made template specializations inline to avoid compiler-dependent linkage
// + Allowed comments within multiple-line values
// + Enabled blank line termination for multiple-line values
// + Added optional sentry to detect end of configuration file
// + Rewrote messy trimWhitespace() function as elegant trim()

View File

@ -0,0 +1,430 @@
/*!
* \file main.cc
* \brief A simple configuration utility for Sick LD LIDARs.
*
* Code by Jason C. Derenick and Thomas H. Miller.
* Contact derenick(at)lehigh(dot)edu
*
* ConfigFile was written by Richard J. Wagner
* Download at http://www-personal.umich.edu/~wagnerr/ChE.html
*
* LDConfig is a simple utility to make configuring the SICK LD-LRS
* easier. By editing the configuration file, one can set up the LD-LRS
* in different configurations, without mucking about in source code.
*
* The Sick LIDAR Matlab/C++ Toolbox
* Copyright (c) 2008, Jason C. Derenick and Thomas H. Miller
* All rights reserved.
*
* This software is released under a BSD Open-Source License.
* See http://sicktoolbox.sourceforge.net
*/
#include <string>
#include <iostream>
#include <signal.h>
#include <stdlib.h>
#include <sicktoolbox/SickLD.hh>
#include <stdlib.h>
#include "ConfigFile.h"
#define INVALID_OPTION_STRING " Invalid option!!! :o("
#define PROMPT_STRING "ld?> "
/* Config file parameters */
#define CONFIG_OPT_MOTOR_SPD_STR "SICK_LD_MOTOR_SPEED"
#define CONFIG_OPT_SCAN_AREA_STR "SICK_LD_SCAN_AREAS"
#define CONFIG_OPT_SCAN_RES_STR "SICK_LD_SCAN_RESOLUTION"
using namespace std;
using namespace SickToolbox;
/**
* \fn sigintHandler
* \brief Callback for SIGINT interrupt. Used for uninitialization.
* \param signal Signal ID
*/
void sigintHandler(int signal);
/**
* \fn getUserOption
* \brief A utility function for capturing input from the user
* \param is_null_input Indicates whether the user entered null input
* \return User option as an integer
*/
int getUserOption(bool &is_null_input);
/**
* \fn getFilename
* \brief Prompts the user for config filename
* \return Configuration file path
*/
string getFilename();
/**
* \fn setConfig
* \brief Attempts to set the desired config via the driver.
* Parses configuration file as well.
*/
void setConfig();
/**
* \fn printConfig
* \brief Prints the current Sick status/config
*/
void printConfig();
/**
* \fn parseScanAreasStr
* \brief Parses the scan areas input string.
* \param start_angs Array of angles to begin a sector
* \param stop_angs Array of angles to end a sector
* \param areas String of sectors (e.g. "[0 10.75] [40.5 60.0] [85 100]")
* \param num_pairs Number of angle pairs found
* \return true on success, false otherwise
*
* pre: all parameters != NULL
* post: start_angs and stop_angs hold num_pairs values;
* 0 < num_pairs < SickLD::SICK_MAX_NUM_MEASURING_SECTORS
*
* This function separates the scan areas found in the config file
* into two arrays - one with angles that the scan areas begin at,
* and another with the angles that the scan areas end at. Uses
* setAngle()
*/
bool parseScanAreasStr(string& scan_areas_str, double *start_angs, double *stop_angs, int& num_sectors);
/**
* \fn parseNumStr
* \param entry String to be converted to a number
* \param num Variable to receive converted string
* \return true on success, false otherwise
*
* Parses entry string into a double, and saves it in num.
*/
bool parseNumStr(const string& entry, double& num);
/* A pointer to the current driver instance */
SickLD *sick_ld = NULL;
int main(int argc, char* argv[])
{
string sick_ip_addr(DEFAULT_SICK_IP_ADDRESS); // IP address of the Sick LD unit
/* Check the num args */
if(argc > 2 || (argc == 2 && strcasecmp(argv[1],"--help") == 0)) {
cerr << "Usage: ld_config [SICK IP ADDRESS]" << endl
<< "Ex. ld_config 192.168.1.11" << endl;
return -1;
}
/* Assign the IP address */
if(argc == 2) {
sick_ip_addr = argv[1];
}
/* Instantiate the SickLD driver */
sick_ld = new SickLD(sick_ip_addr);
cout << endl;
cout << "The Sick LIDAR C++/Matlab Toolbox " << endl;
cout << "Sick LD Config Utility " << endl;
cout << endl;
/* Initialize the Sick LD */
try {
sick_ld->Initialize();
}
catch(...) {
cerr << "Initialize failed! Are you using the correct IP address?" << endl;
return -1;
}
/* Register the signal handler */
signal(SIGINT,sigintHandler);
do {
cout << "Enter your choice: (Ctrl-c to exit)" << endl;
cout << " [1] Set new configuration"<< endl;
cout << " [2] Show current settings"<< endl;
cout << PROMPT_STRING;
bool is_null_input;
switch(getUserOption(is_null_input)) {
case 1:
setConfig();
break;
case 2:
printConfig();
break;
default:
if(!is_null_input) {
cerr << INVALID_OPTION_STRING << endl;
}
}
cout << endl;
} while(true);
/* Success */
return 0;
}
/**
* Handles the SIGINT signal
*/
void sigintHandler(int signal) {
cout << endl;
cout << "Quitting..." << endl;
/* Unitialize the device */
try {
sick_ld->Uninitialize();
delete sick_ld;
}
catch(...) {
cerr << "Uninitialize failed!" << endl;
exit(-1);
}
cout << endl;
cout << "Thanks for using the Sick LIDAR Matlab/C++ Toolbox!" << endl;
cout << "Bye Bye :o)" << endl;
exit(0);
}
/**
* Reads user input string and returns numeric representation.
*/
int getUserOption(bool &is_null_input) {
string user_input_str;
getline(cin,user_input_str);
// Check whether its null input
is_null_input = true;
if (user_input_str.length() > 0) {
is_null_input = false;
}
int int_val = 0;
istringstream input_stream(user_input_str);
input_stream >> int_val;
return int_val;
}
/**
* Prompts the user for the filename
*/
string getFilename() {
string filename;
cout << "config file: ";
getline(cin,filename);
return filename;
}
/**
* Parses config file and loads new configuration
*/
void setConfig() {
int motor_spd;
int num_sectors;
double scan_res;
double start_angs[SickLD::SICK_MAX_NUM_MEASURING_SECTORS] = {0};
double stop_angs[SickLD::SICK_MAX_NUM_MEASURING_SECTORS] = {0};
string scan_areas_str;
ConfigFile sick_config_file; // Extracts values from config file
string config_path;
/* Prompt the user for the filename */
config_path = getFilename();
/* Instantiate the parser */
if(ifstream(config_path.c_str())) {
sick_config_file = ConfigFile(config_path);
}
else {
cerr << "Invalid filename!" << endl;
return;
}
/* Use the ConfigFile class to extract the various parameters for
* the sick configuration.
*
* NOTE: The third parameter specifies the value to use, if the second
* parameter is not found in the file.
*/
if(!sick_config_file.readInto(motor_spd,CONFIG_OPT_MOTOR_SPD_STR)) {
cerr << "ERROR: Invalid config file - " << CONFIG_OPT_MOTOR_SPD_STR << " needs to be specified!" << endl;
return;
}
if(!sick_config_file.readInto(scan_res,CONFIG_OPT_SCAN_RES_STR)) {
cerr << "ERROR: Invalid config file - " << CONFIG_OPT_SCAN_RES_STR << " needs to be specified!" << endl;
return;
}
if(!sick_config_file.readInto(scan_areas_str,CONFIG_OPT_SCAN_AREA_STR)) {
cerr << "ERROR: Invalid config file - " << CONFIG_OPT_SCAN_AREA_STR << " needs to be specified!" << endl;
return;
}
/* Extract the start/stop pairs and angle res for the scanning sectors */
if (!parseScanAreasStr(scan_areas_str,start_angs,stop_angs,num_sectors)) {
cerr << "ERROR: Parser failed to extract scan areas!" << endl;
return;
}
/* Set the global parameters - we pass them all at once to ensure a feasible config */
cout << endl << "\tAttempting to configure the Sick LD..." << endl;
try {
sick_ld->SetSickGlobalParamsAndScanAreas(motor_spd,scan_res,start_angs,stop_angs,num_sectors);
}
catch(SickConfigException &sick_config_exception) {
cerr << "ERROR: Couldn't set requested configuration!" << endl;
return;
}
catch(...) {
exit(-1);
}
cout << "\t\tConfiguration Successfull!!!" << endl;
}
/**
* Print the current Sick LD configuration
*/
void printConfig() {
cout << endl;
sick_ld->PrintSickStatus();
sick_ld->PrintSickIdentity();
sick_ld->PrintSickGlobalConfig();
sick_ld->PrintSickEthernetConfig();
sick_ld->PrintSickSectorConfig();
}
/**
* Parses scan areas string in order extract desired sector configuration
*/
bool parseScanAreasStr(string& areas, double * start_angs, double * stop_angs, int& num_pairs) {
unsigned long i; // number of sectors found so far
unsigned int start_pos = 0; // starting position of a sector in 'areas'
unsigned int end_pos = 0; // ending position of a sector in 'areas'
unsigned int split = 0; // position of the delimiter inside a sector
string pair; // a string of 'areas' that contains one start and one stop angle
/* Get the beginning and end of the first scan sector */
start_pos = areas.find('[',start_pos); // Find the next [, starting at start_pos
end_pos = areas.find(']',start_pos);
/* Keep getting sectors until we either run out of open
* brackets or we exceed the number of allowed sectors
*/
for(i=0; (start_pos != (unsigned int)string::npos) && (i <= SickLD::SICK_MAX_NUM_MEASURING_SECTORS); i++) {
pair = areas.substr(start_pos+1,end_pos-(start_pos+1));
/* Eliminate any padding before first value */
try {
pair = pair.substr(pair.find_first_not_of(' '));
}
catch(...) {
cerr << "ERROR: There was an problem parsing your scan areas! Check your config file." << endl;
return false;
}
split = pair.find(' ');
/* Catch a lack of ' ' inside the sector definition;
* alternative is to let it fail at pair.substr(split)
*/
if(split == (unsigned int)string::npos) {
cerr << "ERROR: Invalid sector definition." << endl;
return false;
}
/* Get the number from the beginning to the delimiter */
if(!parseNumStr(pair.substr(0,split),start_angs[i])) {
cerr << "ERROR: Invalid start angle found." << endl;
return false;
}
/* Get the number from the delimiter to the end */
if(!parseNumStr(pair.substr(split),stop_angs[i])) {
cerr << "ERROR: Invalid stop angle found." << endl;
return false;
}
start_pos = end_pos; // Shift to the end of the current sector
/* Try to find another sector */
start_pos = areas.find("[", start_pos);
end_pos = areas.find("]", start_pos);
}
num_pairs = i;
/* Check if we broke out because of too many loops */
if(num_pairs > SickLD::SICK_MAX_NUM_MEASURING_SECTORS) {
cerr << "ERROR: Too many scan areas found (max " << SickLD::SICK_MAX_NUM_MEASURING_SECTORS << ")" << endl;
return false;
}
/* Or, we might not have even entered the loop */
if(num_pairs == 0) {
cerr << "ERROR: No scan areas found! Check brackets in your config file." << endl;
return false;
}
/* Success! */
return true;
}
/**
* Parses entry string into a double, and saves it in num.
*/
bool parseNumStr(const string& entry, double& num)
{
string num_str = entry.substr(entry.find_first_not_of(' '));
istringstream input_stream(num_str.c_str());
if(!(input_stream >> num)) {
cerr << "ERROR: Invalid angle value: " + num_str << endl;
return false;
}
/* Success! */
return true;
}

View File

@ -0,0 +1,113 @@
/*!
* \file main.cc
* \brief Illustrates a variety of ways to configure the flash
* parameters on the Sick LD device as well as how to set
* the unit's clock.
*
* Code by Jason C. Derenick and Thomas H. Miller.
* Contact derenick(at)lehigh(dot)edu
*
* The Sick LIDAR Matlab/C++ Toolbox
* Copyright (c) 2008, Jason C. Derenick and Thomas H. Miller
* All rights reserved.
*
* This software is released under a BSD Open-Source License.
* See http://sicktoolbox.sourceforge.net
*/
#include <stdlib.h>
#include <string>
#include <iostream>
#include <sicktoolbox/SickLD.hh>
using namespace std;
using namespace SickToolbox;
int main (int argc, char *argv[]) {
/* A string for the IP address */
string sick_ip_addr(DEFAULT_SICK_IP_ADDRESS);
/* Check the num of args */
if(argc > 2 || (argc == 2 && strcasecmp(argv[1],"--help") == 0)) {
cerr << "Usage: ld_more_config [SICK IP ADDRESS]" << endl
<< "Ex. ld_more_config 192.168.1.11" << endl;
return -1;
}
/* Assign the IP address */
if(argc == 2) {
sick_ip_addr = argv[1];
}
/* Define the object */
SickLD sick_ld(sick_ip_addr);
/*
* Initialize the Sick LD
*/
try {
sick_ld.Initialize();
}
catch(...) {
cerr << "Initialize failed! Are you using the correct IP address?" << endl;
return -1;
}
try {
/* Assign absolute and then relative time */
//uint16_t new_sick_time = 0;
//sick_ld.SetSickTimeAbsolute(1500,new_sick_time);
//cout << "\tNew sick time: " << new_sick_time << endl;
//sick_ld.SetSickTimeRelative(-500,new_sick_time);
//cout << "\tNew sick time: " << new_sick_time << endl;
/* Configure the Sick LD sensor ID */
//sick_ld.PrintSickGlobalConfig();
//sick_ld.SetSickSensorID(16);
//sick_ld.PrintSickGlobalConfig();
/* Configure the sick motor speed */
//sick_ld.PrintSickGlobalConfig();
//sick_ld.SetSickMotorSpeed(10);
//sick_ld.PrintSickGlobalConfig();
/* Configure the sick scan resolution */
//sick_ld.PrintSickGlobalConfig();
//sick_ld.SetSickScanResolution(0.5);
//sick_ld.PrintSickGlobalConfig();
/* Configure all the global parameters */
//double start_angle = 45;
//double stop_angle = 315;
//sick_ld.PrintSickGlobalConfig();
//sick_ld.PrintSickSectorConfig();
//sick_ld.SetSickGlobalParamsAndScanAreas(10,0.5,&start_angle,&stop_angle,1);
//sick_ld.PrintSickGlobalConfig();
//sick_ld.PrintSickSectorConfig();
}
catch(...) {
cerr << "An error occurred!" << endl;
}
/*
* Uninitialize the device
*/
try {
sick_ld.Uninitialize();
}
catch(...) {
cerr << "Uninitialize failed!" << endl;
return -1;
}
/* Success! */
return 0;
}

View File

@ -0,0 +1,124 @@
/*!
* \file main.cc
* \brief Illustrates how to work with the Sick LD
* using multiple scan areas/sectors.
*
* Code by Jason C. Derenick and Thomas H. Miller.
* Contact derenick(at)lehigh(dot)edu
*
* The Sick LIDAR Matlab/C++ Toolbox
* Copyright (c) 2008, Jason C. Derenick and Thomas H. Miller
* All rights reserved.
*
* This software is released under a BSD Open-Source License.
* See http://sicktoolbox.sourceforge.net
*/
#include <stdlib.h>
#include <string>
#include <iostream>
#include <sicktoolbox/SickLD.hh>
/* Define the number of active sectors */
#define NUM_ACTIVE_SECTORS (3)
using namespace std;
using namespace SickToolbox;
int main (int argc, char *argv[]) {
/* A string for the IP address */
string sick_ip_addr(DEFAULT_SICK_IP_ADDRESS);
/* Check the num of args */
if(argc > 2 || (argc == 2 && strcasecmp(argv[1],"--help") == 0)) {
cerr << "Usage: ld_multi_sector [SICK IP ADDRESS]" << endl
<< "Ex. ld_multi_sector 192.168.1.11" << endl;
return -1;
}
/* Assign the IP address */
if(argc == 2) {
sick_ip_addr = argv[1];
}
/* Define the temporal scan area (3 active sectors/scan areas)
* NOTE: This scan configuration will persist until the power
* is cycled or until it is reset w/ different params.
*/
double sector_start_angs[NUM_ACTIVE_SECTORS] = {45,270,345};
double sector_stop_angs[NUM_ACTIVE_SECTORS] = {90,315,15};
/* Define the destination buffers */
double range_values[SickLD::SICK_MAX_NUM_MEASUREMENTS] = {0};
unsigned int reflect_values[SickLD::SICK_MAX_NUM_MEASUREMENTS] = {0};
/* Some buffer for additional info we can get from the Sick LD */
unsigned int num_values[NUM_ACTIVE_SECTORS] = {0};
unsigned int data_offsets[NUM_ACTIVE_SECTORS] = {0};
unsigned int sector_ids[NUM_ACTIVE_SECTORS] = {0};
/* Define the object */
SickLD sick_ld(sick_ip_addr);
/* Initialize the Sick LD */
try {
sick_ld.Initialize();
}
catch(...) {
cerr << "Initialize failed! Are you using the correct IP address?" << endl;
return -1;
}
try {
/* Set the temporary scan areas */
sick_ld.SetSickTempScanAreas(sector_start_angs,sector_stop_angs,NUM_ACTIVE_SECTORS);
/* Print the sector configuration */
sick_ld.PrintSickSectorConfig();
/* Request some measurements */
for (unsigned int i = 0; i < 10; i++) {
/* Acquire the most recent range and reflectivity (echo amplitude) values */
sick_ld.GetSickMeasurements(range_values,reflect_values,num_values,sector_ids,data_offsets);
/* Print out some data for each sector */
for (unsigned int i = 0; i < NUM_ACTIVE_SECTORS; i++) {
cout << "\t[Sector ID: " << sector_ids[i]
<< ", Num Meas: " << num_values[i]
<< ", 1st Range Val: " << range_values[data_offsets[i]]
<< ", 1st Reflect Val: " << reflect_values[data_offsets[i]]
<< "]" << endl;
}
cout << endl;
}
}
/* Catch any exception! */
catch(...) {
cerr << "An error occurred!" << endl;
}
/*
* Uninitialize the device
*/
try {
sick_ld.Uninitialize();
}
catch(...) {
cerr << "Uninitialize failed!" << endl;
return -1;
}
/* Success !*/
return 0;
}

View File

@ -0,0 +1,105 @@
/*!
* \file main.cc
* \brief A simple application illustrating the use of
* the Sick LD C++ driver using a single sector.
*
* Code by Jason C. Derenick and Thomas H. Miller.
* Contact derenick(at)lehigh(dot)edu
*
* The Sick LIDAR Matlab/C++ Toolbox
* Copyright (c) 2008, Jason C. Derenick and Thomas H. Miller
* All rights reserved.
*
* This software is released under a BSD Open-Source License.
* See http://sicktoolbox.sourceforge.net
*/
#include <stdlib.h>
#include <string>
#include <iostream>
#include <sicktoolbox/SickLD.hh>
/* Use the namespace */
using namespace std;
using namespace SickToolbox;
int main (int argc, char *argv[]) {
/* A string for the IP address */
string sick_ip_addr(DEFAULT_SICK_IP_ADDRESS);
/* Check the num of args */
if(argc > 2 || (argc == 2 && strcasecmp(argv[1],"--help") == 0)) {
cerr << "Usage: ld_single_sector [SICK IP ADDRESS]" << endl
<< "Ex. ld_single_sector 192.168.1.11" << endl;
return -1;
}
/* Assign the IP address */
if(argc == 2) {
sick_ip_addr = argv[1];
}
/* Define the data buffers */
double values[SickLD::SICK_MAX_NUM_MEASUREMENTS] = {0};
unsigned int num_values = 0;
/* Define the bounds for a single sector */
double sector_start_ang = 90;
double sector_stop_ang = 270;
/* Define the object */
SickLD sick_ld(sick_ip_addr);
/*
* Initialize the Sick LD
*/
try {
sick_ld.Initialize();
}
catch(...) {
cerr << "Initialize failed! Are you using the correct IP address?" << endl;
return -1;
}
try {
/* Set the desired sector configuration */
sick_ld.SetSickTempScanAreas(&sector_start_ang,&sector_stop_ang,1);
/* Print the sector configuration */
sick_ld.PrintSickSectorConfig();
/* Acquire some range measurements */
for (unsigned int i = 0; i < 10; i++) {
/* Here we only want the range values so the second arg is NULL */
sick_ld.GetSickMeasurements(values,NULL,&num_values);
cout << "\t Num. Values: " << num_values << endl;
}
}
/* Catch any exceptions */
catch(...) {
cerr << "An error occurred!" << endl;
}
/*
* Uninitialize the device
*/
try {
sick_ld.Uninitialize();
}
catch(...) {
cerr << "Uninitialize failed!" << endl;
return -1;
}
/* Success !*/
return 0;
}

View File

@ -0,0 +1,94 @@
/*!
* \file main.cc
* \brief A simple application using the Sick LMS 1xx driver.
*
* Code by Jason C. Derenick and Christopher R. Mansley.
* Contact jasonder(at)seas(dot)upenn(dot)edu
*
* The Sick LIDAR Matlab/C++ Toolbox
* Copyright (c) 2009, Jason C. Derenick and Christopher R. Mansley
* All rights reserved.
*
* This software is released under a BSD Open-Source License.
* See http://sicktoolbox.sourceforge.net
*/
#include <stdlib.h>
#include <string>
#include <iostream>
#include <sicktoolbox/SickLMS1xx.hh>
using namespace std;
using namespace SickToolbox;
int main(int argc, char* argv[])
{
/*
* Instantiate an instance
*/
SickLMS1xx sick_lms_1xx;
/*
* Initialize the Sick LMS 2xx
*/
try {
sick_lms_1xx.Initialize();
}
catch(...) {
cerr << "Initialize failed! Are you using the correct IP address?" << endl;
return -1;
}
try {
unsigned int status = 1;
unsigned int num_measurements = 0;
unsigned int range_1_vals[SickLMS1xx::SICK_LMS_1XX_MAX_NUM_MEASUREMENTS];
unsigned int range_2_vals[SickLMS1xx::SICK_LMS_1XX_MAX_NUM_MEASUREMENTS];
//sick_lms_1xx.SetSickScanFreqAndRes(SickLMS1xx::SICK_LMS_1XX_SCAN_FREQ_25,
//SickLMS1xx::SICK_LMS_1XX_SCAN_RES_25);
//sick_lms_1xx.SetSickScanDataFormat(SickLMS1xx::SICK_LMS_1XX_DIST_DOUBLE_PULSE,
// SickLMS1xx::SICK_LMS_1XX_REFLECT_NONE);
sick_lms_1xx.SetSickScanDataFormat(SickLMS1xx::SICK_LMS_1XX_SCAN_FORMAT_DIST_DOUBLE_PULSE_REFLECT_16BIT);
for (int i = 0; i < 1000; i++) {
sick_lms_1xx.GetSickMeasurements(range_1_vals,range_2_vals,range_1_vals,range_2_vals,num_measurements,&status);
std::cout << i << ": " << num_measurements << " " << status << std::endl;
}
}
catch(SickConfigException sick_exception) {
std::cout << sick_exception.what() << std::endl;
}
catch(SickIOException sick_exception) {
std::cout << sick_exception.what() << std::endl;
}
catch(SickTimeoutException sick_exception) {
std::cout << sick_exception.what() << std::endl;
}
catch(...) {
cerr << "An Error Occurred!" << endl;
return -1;
}
/*
* Uninitialize the device
*/
try {
sick_lms_1xx.Uninitialize();
}
catch(...) {
cerr << "Uninitialize failed!" << endl;
return -1;
}
/* Success! */
return 0;
}

View File

@ -0,0 +1,14 @@
=================================================
Sick LIDAR Matlab/C++ Toolbox
=================================================
Example: lms_config
Note: This example is COMPATIBLE w/ ALL Sick 2xx LIDAR units! :o)
Desc: This example provides a simple shell-like configuration
utility for working w/ Sick LMS 2xx LIDARs. It can be
used for setting measuring units, measuring mode, and
sensitivity. It can also display the current LMS config.
Example call (from build dir): ./lms_config /dev/ttyUSB0 9600

View File

@ -0,0 +1,627 @@
/*!
* \file main.cc
* \brief A simple config utility for Sick LMS 2xx LIDARs.
*
* Code by Jason C. Derenick and Thomas H. Miller.
* Contact derenick(at)lehigh(dot)edu
*
* The Sick LIDAR Matlab/C++ Toolbox
* Copyright (c) 2008, Jason C. Derenick and Thomas H. Miller
* All rights reserved.
*
* This software is released under a BSD Open-Source License.
* See http://sicktoolbox.sourceforge.net
*/
/* Implementation dependencies */
#include <stdlib.h>
#include <string>
#include <sstream>
#include <iostream>
#include <signal.h>
#include <stdlib.h>
#include <sicktoolbox/SickLMS2xx.hh>
#define INVALID_OPTION_STRING " Invalid option!!! :o("
#define PROMPT_STRING "lms2xx?> "
using namespace std;
using namespace SickToolbox;
/**
* \fn sigintHandler
* \brief Callback for SIGINT interrupt. Used for uninitialization.
* \param signal Signal ID
*/
void sigintHandler(int signal);
/**
* \fn strToInt
* \brief Utility function for converting string to int
* \param input_str Input string to convert
*/
int strToInt(string input_str);
/**
* \fn getUserOption
* \brief Utility function for grabbing user input
* \param is_null_input Output parameter indicating whether
* user entered NULL input
*/
int getUserOption(bool &is_null_input);
/**
* \fn writeToEEPROM
* \brief Confirms the user actually wants to perform write
*/
bool writeToEEPROM();
/**
* \fn setMeasuringUnits
* \brief Prompts the user and sets the desired measuring
* units via the driver interface.
*/
void setMeasuringUnits();
/**
* \fn setMeasuringMode
* \brief Prompts the user and sets the desired measuring
* mode via the driver interface.
*/
void setMeasuringMode();
/**
* \fn setAvailabilityLevel
* \brief Prompts the user and sets the desired availability
* level via the driver interface.
*/
void setAvailabilityLevel();
/**
* \fn setSensitivityLevel
* \brief Prompts the user and sets the desired sensitivity
* level via the driver interface.
*/
void setSensitivityLevel();
/* A pointer to the Sick obj */
SickLMS2xx *sick_lms_2xx = NULL;
int main(int argc, char * argv[]) {
string device_str; // Device path of the Sick LMS 2xx
SickLMS2xx::sick_lms_2xx_baud_t desired_baud = SickLMS2xx::SICK_BAUD_38400;
/* Check for a device path. If it's not present, print a usage statement. */
if ((argc != 2 && argc != 3) || (argc == 2 && strcasecmp(argv[1],"--help") == 0)) {
cout << "Usage: lms2xx_config PATH [BAUD RATE]" << endl
<< "Ex: lms2xx_config /dev/ttyUSB0 9600" << endl;
return -1;
}
/* Only device path is given */
if (argc == 2) {
device_str = argv[1];
}
/* Device path and baud are given */
if (argc == 3) {
device_str = argv[1];
if ((desired_baud = SickLMS2xx::StringToSickBaud(argv[2])) == SickLMS2xx::SICK_BAUD_UNKNOWN) {
cerr << "Invalid baud value! Valid values are: 9600, 19200, 38400, and 500000" << endl;
return -1;
}
}
/* Instantiate the SickLMS2xx class with the device path string. */
sick_lms_2xx = new SickLMS2xx(device_str);
cout << endl;
cout << "The Sick LIDAR C++/Matlab Toolbox " << endl;
cout << "Sick LMS 2xx Config Utility " << endl;
/* Initialize the device */
try {
sick_lms_2xx->Initialize(desired_baud);
}
catch(...) {
cerr << "Initialize failed! Are you using the correct device path?" << endl;
return -1;
}
/* Register the signal handler */
signal(SIGINT,sigintHandler);
cout << "NOTE - Configuring the Sick LMS - REQUIRES - writing to the device's EEPROM." << endl;
cout << " The number of times this can be done is finite (a few thousand)." << endl;
cout << " Thus, you should configure sparingly." << endl;
cout << endl;
do {
cout << "Enter your choice: (Ctrl-c to exit)" << endl;
cout << " [1] Set measuring units"<< endl;
cout << " [2] Set measuring mode"<< endl;
cout << " [3] Set availability level" << endl;
cout << " [4] Set sensitivity level" << endl;
cout << " [5] Show detailed configuration" << endl;
cout << PROMPT_STRING;
bool is_null_input;
switch(getUserOption(is_null_input)) {
case 1:
setMeasuringUnits();
break;
case 2:
setMeasuringMode();
break;
case 3:
setAvailabilityLevel();
break;
case 4:
setSensitivityLevel();
break;
case 5:
sick_lms_2xx->PrintSickConfig();
break;
default:
if (!is_null_input) {
cerr << INVALID_OPTION_STRING << endl;
}
}
cout << endl;
} while(true);
/* Success! */
return 0;
}
/**
* Handle the SIGINT signal
*/
void sigintHandler( int signal ) {
cout << endl;
cout << "Quitting..." << endl;
/* Unitialize the device */
try {
sick_lms_2xx->Uninitialize();
delete sick_lms_2xx;
}
catch(...) {
cerr << "Uninitialize failed!" << endl;
exit(-1);
}
cout << endl;
cout << "Thanks for using the Sick LIDAR Matlab/C++ Toolbox!" << endl;
cout << "Bye Bye :o)" << endl;
exit(0);
}
/**
* Converts ascii string to an integer
*/
int strToInt( string input_str ) {
int int_val;
istringstream input_stream(input_str);
input_stream >> int_val;
return int_val;
}
/**
* Reads in user input string and returns numeric
* representation
*/
int getUserOption( bool &is_null_input ) {
string user_input_str;
getline(cin,user_input_str);
// Check whether its null input
is_null_input = true;
if (user_input_str.length() > 0) {
is_null_input = false;
}
return strToInt(user_input_str);
}
/**
* Prompts the user to confirm requested operation
*/
bool writeToEEPROM( ) {
string user_input_str;
do {
cout << "This will attempt to write to EEPROM. Continue [y/n]? ";
getline(cin,user_input_str);
// Check whether its null input
if (user_input_str == "Y" || user_input_str == "y") {
return true;
}
else if (user_input_str == "N" || user_input_str == "n") {
return false;
}
else {
cerr << "Please answer [y/n]!" << endl;
}
} while (true);
}
/**
* Sets the measuring units of the device
*/
void setMeasuringUnits() {
bool keep_running = true;
do {
cout << endl;
cout << "Select the desired units:" << endl;
cout << " [1] Centimeters (cm)"<< endl;
cout << " [2] Millimeters (mm)"<< endl;
cout << " [3] Back to main"<< endl;
cout << PROMPT_STRING;
try {
bool is_null_input;
switch(getUserOption(is_null_input)) {
case 1:
if (writeToEEPROM()) {
cout << " Setting Sick LMS units to (cm)" << endl;
sick_lms_2xx->SetSickMeasuringUnits(SickLMS2xx::SICK_MEASURING_UNITS_CM);
cout << " Done!" << endl;
}
break;
case 2:
if (writeToEEPROM()) {
cout << " Setting Sick LMS units to (mm)" << endl;
sick_lms_2xx->SetSickMeasuringUnits(SickLMS2xx::SICK_MEASURING_UNITS_MM);
cout << " Done!" << endl;
}
break;
case 3:
keep_running = !keep_running;
break;
default:
if (!is_null_input) {
cerr << INVALID_OPTION_STRING << endl;
}
}
}
catch( SickException &sick_exception ) {
cerr << "A Sick exception occurred!" << endl;
exit(-1);
}
catch(...) {
cerr << "An unknown exception occurred!" << endl;
exit(-1);
}
} while (keep_running);
}
/**
* Sets the measuring mode of the device
*/
void setMeasuringMode() {
bool keep_running = true;
do {
cout << endl;
cout << "Select the desired measuring mode (see telegram listing for descriptions):" << endl;
cout << " [1] Measurement range 8m/80m; field A, field B, and dazzle" << endl;
cout << " [2] Measurement range 8m/80m; reflector bits in 8 levels" << endl;
cout << " [3] Measurement range 8m/80m; field A, field B and field C" << endl;
cout << " [4] Measurement range 16m/theoretically 160m; reflector bits in 4 levels" << endl;
cout << " [5] Measurement range 16m/theoretically 160m; field A and field B" << endl;
cout << " [6] Measurement range 32m/theoretically 320m; reflector bits in 2 levels" << endl;
cout << " [7] Measurement range 32m/theoretically 320m; field A" << endl;
cout << " [8] Measurement range 32m/theoretically 320m; Immediate" << endl;
cout << " [9] Reflectivity/Intensity values" << endl;
cout << " [10] Back to main" << endl;
cout << PROMPT_STRING;
try {
bool is_null_input;
switch(getUserOption(is_null_input)) {
case 1:
if (writeToEEPROM()) {
cout << " Setting Sick LMS Meas. Mode to: Measurement range 8m/80m; field A, field B, and dazzle" << endl;
sick_lms_2xx->SetSickMeasuringMode(SickLMS2xx::SICK_MS_MODE_8_OR_80_FA_FB_DAZZLE);
cout << " Done!" << endl;
}
break;
case 2:
if (writeToEEPROM()) {
cout << " Setting Sick LMS Meas. Mode to: Measurement range 8m/80m; reflector bits in 8 levels" << endl;
sick_lms_2xx->SetSickMeasuringMode(SickLMS2xx::SICK_MS_MODE_8_OR_80_REFLECTOR);
cout << " Done!" << endl;
}
break;
case 3:
if (writeToEEPROM()) {
cout << " Setting Sick LMS Meas. Mode to: Measurement range 8m/80m; field A, field B and field C" << endl;
sick_lms_2xx->SetSickMeasuringMode(SickLMS2xx::SICK_MS_MODE_8_OR_80_FA_FB_FC);
cout << " Done!" << endl;
}
break;
case 4:
if (writeToEEPROM()) {
cout << " Setting Sick LMS Meas. Mode to: Measurement range 16m/theoretically 160m; reflector bits in 4 levels" << endl;
sick_lms_2xx->SetSickMeasuringMode(SickLMS2xx::SICK_MS_MODE_16_REFLECTOR);
cout << " Done!" << endl;
}
break;
case 5:
if (writeToEEPROM()) {
cout << " Setting Sick LMS Meas. Mode to: Measurement range 16m/theoretically 160m; field A and field B" << endl;
sick_lms_2xx->SetSickMeasuringMode(SickLMS2xx::SICK_MS_MODE_16_FA_FB);
cout << " Done!" << endl;
}
break;
case 6:
if (writeToEEPROM()) {
cout << " Setting Sick LMS Meas. Mode to: Measurement range 32m/theoretically 320m; reflector bit in 2 levels" << endl;
sick_lms_2xx->SetSickMeasuringMode(SickLMS2xx::SICK_MS_MODE_32_REFLECTOR);
cout << " Done!" << endl;
}
break;
case 7:
if (writeToEEPROM()) {
cout << " Setting Sick LMS Meas. Mode to: Measurement range 32m/theoretically 320m; field A" << endl;
sick_lms_2xx->SetSickMeasuringMode(SickLMS2xx::SICK_MS_MODE_32_FA);
cout << " Done!" << endl;
}
break;
case 8:
if (writeToEEPROM()) {
cout << " Setting Sick LMS Meas. Mode to: Measurement range 32m/theoretically 320m; Immediate" << endl;
sick_lms_2xx->SetSickMeasuringMode(SickLMS2xx::SICK_MS_MODE_32_IMMEDIATE);
cout << " Done!" << endl;
}
break;
case 9:
if (writeToEEPROM()) {
cout << " Setting Sick LMS Meas. Mode to: Reflectivity/Intensity" << endl;
sick_lms_2xx->SetSickMeasuringMode(SickLMS2xx::SICK_MS_MODE_REFLECTIVITY);
cout << " Done!" << endl;
}
break;
case 10:
keep_running = !keep_running;
break;
default:
if (!is_null_input) {
cerr << INVALID_OPTION_STRING << endl;
}
}
}
catch( SickException &sick_exception ) {
cerr << "A Sick exception occurred!" << endl;
exit(-1);
}
catch(...) {
cerr << "An unknown exception occurred!" << endl;
exit(-1);
}
} while (keep_running);
}
/**
* Sets the measuring mode of the device
*/
void setAvailabilityLevel() {
bool keep_running = true;
do {
cout << endl;
cout << "Select the desired availability (see telegram listing for descriptions):" << endl;
cout << " [1] Restore to factory default" << endl;
cout << " [2] High" << endl;
cout << " [3] High w/ Real-time indices" << endl;
cout << " [4] High w/ No effect dazzle" << endl;
cout << " [5] High w/ Real-time indices and No effect dazzle" << endl;
cout << " [6] Real-time indices" << endl;
cout << " [7] Real-time indices w/ No effect dazzle" << endl;
cout << " [8] No effect dazzle" << endl;
cout << " [9] Back to main" << endl;
cout << PROMPT_STRING;
try {
bool is_null_input;
switch(getUserOption(is_null_input)) {
case 1:
if (writeToEEPROM()) {
cout << " Setting Sick LMS Availability to: Factory settings" << endl;
sick_lms_2xx->SetSickAvailability();
cout << " Done!" << endl;
}
break;
case 2:
if (writeToEEPROM()) {
cout << " Setting Sick LMS Availability to: High" << endl;
sick_lms_2xx->SetSickAvailability(SickLMS2xx::SICK_FLAG_AVAILABILITY_HIGH);
cout << " Done!" << endl;
}
break;
case 3:
if (writeToEEPROM()) {
cout << " Setting Sick LMS Availability to: High w/ Real-time indices" << endl;
sick_lms_2xx->SetSickAvailability(SickLMS2xx::SICK_FLAG_AVAILABILITY_HIGH | SickLMS2xx::SICK_FLAG_AVAILABILITY_REAL_TIME_INDICES);
cout << " Done!" << endl;
}
break;
case 4:
if (writeToEEPROM()) {
cout << " Setting Sick LMS Availability to: High w/ No effect dazzle" << endl;
sick_lms_2xx->SetSickAvailability(SickLMS2xx::SICK_FLAG_AVAILABILITY_HIGH | SickLMS2xx::SICK_FLAG_AVAILABILITY_DAZZLE_NO_EFFECT);
cout << " Done!" << endl;
}
break;
case 5:
if (writeToEEPROM()) {
cout << " Setting Sick LMS Availability to: High w/ Real-time indices and No effect dazzle" << endl;
sick_lms_2xx->SetSickAvailability(SickLMS2xx::SICK_FLAG_AVAILABILITY_HIGH | SickLMS2xx::SICK_FLAG_AVAILABILITY_REAL_TIME_INDICES | SickLMS2xx::SICK_FLAG_AVAILABILITY_DAZZLE_NO_EFFECT);
cout << " Done!" << endl;
}
break;
case 6:
if (writeToEEPROM()) {
cout << " Setting Sick LMS Availability to: Real-time indices" << endl;
sick_lms_2xx->SetSickAvailability(SickLMS2xx::SICK_FLAG_AVAILABILITY_REAL_TIME_INDICES);
cout << " Done!" << endl;
}
break;
case 7:
if (writeToEEPROM()) {
cout << " Setting Sick LMS Availability to: Real-time indices w/ No effect dazzle" << endl;
sick_lms_2xx->SetSickAvailability(SickLMS2xx::SICK_FLAG_AVAILABILITY_REAL_TIME_INDICES | SickLMS2xx::SICK_FLAG_AVAILABILITY_DAZZLE_NO_EFFECT);
cout << " Done!" << endl;
}
break;
case 8:
if (writeToEEPROM()) {
cout << " Setting Sick LMS Availability to: No effect dazzle" << endl;
sick_lms_2xx->SetSickAvailability(SickLMS2xx::SICK_FLAG_AVAILABILITY_DAZZLE_NO_EFFECT);
cout << " Done!" << endl;
}
break;
case 9:
keep_running = !keep_running;
break;
default:
if (!is_null_input) {
cerr << INVALID_OPTION_STRING << endl;
}
}
}
catch( SickException &sick_exception ) {
cerr << "A Sick exception occurred!" << endl;
exit(-1);
}
catch(...) {
cerr << "An unknown exception occurred!" << endl;
exit(-1);
}
} while (keep_running);
}
/**
* Sets the Sick LMS sensitivity level
*/
void setSensitivityLevel() {
bool keep_running = true;
do {
cout << endl;
cout << "Select the desired sensitivity level:" << endl;
cout << " [1] High (42m @ 10% reflectivity)"<< endl;
cout << " [2] Standard (30m @ 10% reflectivity, factory setting)"<< endl;
cout << " [3] Medium (25m @ 10% reflectivity)"<< endl;
cout << " [4] Low (20m @ 10% reflectivity)"<< endl;
cout << " [5] Back to main"<< endl;
cout << PROMPT_STRING;
try {
bool is_null_input;
switch(getUserOption(is_null_input)) {
case 1:
if (writeToEEPROM()) {
cout << " Setting Sick LMS Sensitivity to: High" << endl;
sick_lms_2xx->SetSickSensitivity(SickLMS2xx::SICK_SENSITIVITY_HIGH);
cout << " Done!" << endl;
}
break;
case 2:
if (writeToEEPROM()) {
cout << " Setting Sick LMS Sensitivity to: Standard (Factory setting)" << endl;
sick_lms_2xx->SetSickSensitivity();
cout << " Done!" << endl;
}
break;
case 3:
if (writeToEEPROM()) {
cout << " Setting Sick LMS Sensitivity to: Medium" << endl;
sick_lms_2xx->SetSickSensitivity(SickLMS2xx::SICK_SENSITIVITY_MEDIUM);
cout << " Done!" << endl;
}
break;
case 4:
if (writeToEEPROM()) {
cout << " Setting Sick LMS Sensitivity to: Low" << endl;
sick_lms_2xx->SetSickSensitivity(SickLMS2xx::SICK_SENSITIVITY_LOW);
cout << " Done!" << endl;
}
break;
case 5:
keep_running = !keep_running;
break;
default:
if (!is_null_input) {
cerr << INVALID_OPTION_STRING << endl;
}
}
}
catch( SickException &sick_exception ) {
cerr << "A Sick exception occurred!" << endl;
exit(-1);
}
catch(...) {
cerr << "An unknown exception occurred!" << endl;
exit(-1);
}
} while (keep_running);
}

View File

@ -0,0 +1,11 @@
=================================================
Sick LIDAR Matlab/C++ Toolbox
=================================================
Example: lms_mean_values
Note: This example is COMPATIBLE w/ ALL Sick 2xx LIDAR units! :o)
Desc: This example illustrates grabbing mean values from the Sick LMS.
Example call (from build dir): ./lms_mean_values /dev/ttyUSB0 9600

View File

@ -0,0 +1,114 @@
/*!
* \file main.cc
* \brief A simple example illustrating how to acquire
* mean values from the Sick LMS 2xx.
*
* Code by Jason C. Derenick and Thomas H. Miller.
* Contact derenick(at)lehigh(dot)edu
*
* The Sick LIDAR Matlab/C++ Toolbox
* Copyright (c) 2008, Jason C. Derenick and Thomas H. Miller
* All rights reserved.
*
* This software is released under a BSD Open-Source License.
* See http://sicktoolbox.sourceforge.net
*/
#include <stdlib.h>
#include <string>
#include <iostream>
#include <sicktoolbox/SickLMS2xx.hh>
using namespace std;
using namespace SickToolbox;
int main(int argc, char* argv[])
{
string device_str;
SickLMS2xx::sick_lms_2xx_baud_t desired_baud = SickLMS2xx::SICK_BAUD_38400;
unsigned int values[SickLMS2xx::SICK_MAX_NUM_MEASUREMENTS] = {0}; // Uses macro defined in SickLMS2xx.hh
unsigned int num_values; // Holds the number of measurements returned
/* Check for a device path. If it's not present, print a usage statement. */
if ((argc != 2 && argc != 3) || (argc == 2 && strcasecmp(argv[1],"--help") == 0)) {
cout << "Usage: lms2xx_mean_values PATH [BAUD RATE]" << endl
<< "Ex: lms2xx_mean_values /dev/ttyUSB0 9600" << endl;
return -1;
}
/* Only device path is given */
if (argc == 2) {
device_str = argv[1];
}
/* Device path and baud are given */
if (argc == 3) {
device_str = argv[1];
if ((desired_baud = SickLMS2xx::StringToSickBaud(argv[2])) == SickLMS2xx::SICK_BAUD_UNKNOWN) {
cerr << "Invalid baud value! Valid values are: 9600, 19200, 38400, and 500000" << endl;
return -1;
}
}
/*
* Instantiate an instance
*/
SickLMS2xx sick_lms_2xx(device_str);
/*
* Initialize the Sick LMS 2xx
*/
try {
sick_lms_2xx.Initialize(desired_baud);
}
catch(...) {
cerr << "Initialize failed! Are you using the correct device path?" << endl;
return -1;
}
/*
* Acquire a few scans from the Sick LMS
*/
try {
for (unsigned int i=0; i < 10; i++) {
/*
* The first argument is an input to the driver
* telling it the number of raw scans over which
* the Sick should average. (i.e. here, the Sick
* will average over 5 scans before returning
* the resulting mean values)
*/
sick_lms_2xx.GetSickMeanValues(5,values,num_values);
cout << "\t Num. Values: " << num_values << endl;
}
}
/* Catch anything else and exit */
catch(...) {
cerr << "An error occurred!" << endl;
}
/*
* Uninitialize the device
*/
try {
sick_lms_2xx.Uninitialize();
}
catch(...) {
cerr << "Uninitialize failed!" << endl;
return -1;
}
/* Success! */
return 0;
}

View File

@ -0,0 +1,12 @@
=================================================
Sick LIDAR Matlab/C++ Toolbox
=================================================
Example: lms_partial_scan
Note: This example is NOT COMPATIBLE w/ LMS {211,221,291}-S14 LIDARs!
Desc: This example illustrates grabbing partial scans using the
Sick LMS driver.
Example call (from build dir): ./lms_partial_scan /dev/ttyUSB0 9600

View File

@ -0,0 +1,140 @@
/*!
* \file main.cc
* \brief Illustrates how to acquire partial scans
* from the Sick LMS as well as telegram indices.
*
* Code by Jason C. Derenick and Thomas H. Miller.
* Contact derenick(at)lehigh(dot)edu
*
* The Sick LIDAR Matlab/C++ Toolbox
* Copyright (c) 2008, Jason C. Derenick and Thomas H. Miller
* All rights reserved.
*
* This software is released under a BSD Open-Source License.
* See http://sicktoolbox.sourceforge.net
*/
#include <stdlib.h>
#include <string>
#include <iomanip>
#include <iostream>
#include <sicktoolbox/SickLMS2xx.hh>
using namespace std;
using namespace SickToolbox;
int main(int argc, char* argv[]) {
string device_str;
SickLMS2xx::sick_lms_2xx_baud_t desired_baud = SickLMS2xx::SICK_BAUD_38400;
unsigned int values[SickLMS2xx::SICK_MAX_NUM_MEASUREMENTS] = {0}; // Uses macro defined in SickLMS2xx.hh
unsigned int num_values = 0; // Holds the number of measurements returned
unsigned int scan_idx = 0; // Holds the idx for the returned partial scan
unsigned int telegram_idx = 0; // Holds the idx of the telegram associated w/ scan
/* Check for a device path. If it's not present, print a usage statement. */
if ((argc != 2 && argc != 3) || (argc == 2 && strcasecmp(argv[1],"--help") == 0)) {
cout << "Usage: lms2xx_partial_scan PATH [BAUD RATE]" << endl
<< "Ex: lms2xx_partial_scan /dev/ttyUSB0 9600" << endl;
return -1;
}
/* Only device path is given */
if (argc == 2) {
device_str = argv[1];
}
/* Device path and baud are given */
if (argc == 3) {
device_str = argv[1];
if ((desired_baud = SickLMS2xx::StringToSickBaud(argv[2])) == SickLMS2xx::SICK_BAUD_UNKNOWN) {
cerr << "Invalid baud value! Valid values are: 9600, 19200, 38400, and 500000" << endl;
return -1;
}
}
/*
* Instantiate an instance
*/
SickLMS2xx sick_lms_2xx(device_str);
/*
* Initialize the Sick LMS 2xx
*/
try {
sick_lms_2xx.Initialize(desired_baud);
}
catch(...) {
cerr << "Initialize failed! Are you using the correct device path?" << endl;
return -1;
}
/*
* Ensure real-time indices are set
*/
if (sick_lms_2xx.GetSickAvailability() & SickLMS2xx::SICK_FLAG_AVAILABILITY_REAL_TIME_INDICES) {
try {
/*
* Set the device variant to 100/0.25
*
* NOTE: Setting the variant this way ensures that the
* partial scans will start at angles that are a
* multiple of 0.25 deg.
*
*/
sick_lms_2xx.SetSickVariant(SickLMS2xx::SICK_SCAN_ANGLE_100,SickLMS2xx::SICK_SCAN_RESOLUTION_25);
/*
* Acquire some partial scans from Sick
*/
for (unsigned int i=0; i < 12; i++) {
/*
* NOTE: Notice that here we are also obtaining the telegram idx. In a
* proper implementation, this value would be used to ensure the
* temporal consistency (acting as a sequence number) of the newly
* obtained partial scan. Here we simply just print it out.
*
* Also, we don't want Field A,B, or C outputs... so we pass in
* NULL for these params.
*/
sick_lms_2xx.GetSickPartialScan(values,num_values,scan_idx,NULL,NULL,NULL,&telegram_idx);
cout << "\t Start angle: " << setw(4) << 0.25*scan_idx << ", Num. Values: " << num_values << ", Msg Idx: " << telegram_idx << endl;
}
}
/* Catch anything else and exit */
catch(...) {
cerr << "An error occurred!" << endl;
}
}
else {
cout << "Please set the Sick LMS to an availability w/ real-time indices..." << endl;
cout << "Hint: Use the lms_config utility/example! :o)"<< endl;
}
/*
* Uninitialize the device
*/
try {
sick_lms_2xx.Uninitialize();
}
catch(...) {
cerr << "Uninitialize failed!" << endl;
return -1;
}
/* Success! */
return 0;
}

View File

@ -0,0 +1,12 @@
=================================================
Sick LIDAR Matlab/C++ Toolbox
=================================================
Example: lms_real_time_indices
Note: This example is COMPATIBLE w/ ALL Sick 2xx LIDAR units! :o)
Desc: This example provides a simple program template for grabbing
data as well as real-time indices from a Sick LMS 2xx LIDAR.
Example call (from build dir): ./lms_real_time_indices /dev/ttyUSB0 9600

View File

@ -0,0 +1,125 @@
/*!
* \file main.cc
* \brief Illustrates how to use the Sick Toolbox C++ interface
* to acquire scan data along with real-time indices from
* a Sick LMS 2xx.
*
* Code by Jason C. Derenick and Thomas H. Miller.
* Contact derenick(at)lehigh(dot)edu
*
* The Sick LIDAR Matlab/C++ Toolbox
* Copyright (c) 2008, Jason C. Derenick and Thomas H. Miller
* All rights reserved.
*
* This software is released under a BSD Open-Source License.
* See http://sicktoolbox.sourceforge.net
*/
#include <stdlib.h>
#include <string>
#include <iostream>
#include <sicktoolbox/SickLMS2xx.hh>
using namespace std;
using namespace SickToolbox;
int main(int argc, char* argv[])
{
string device_str;
SickLMS2xx::sick_lms_2xx_baud_t desired_baud = SickLMS2xx::SICK_BAUD_38400;
unsigned int values[SickLMS2xx::SICK_MAX_NUM_MEASUREMENTS] = {0}; // Uses macro defined in SickLMS2xx.hh
unsigned int num_values = 0; // Holds the number of measurements returned
unsigned int telegram_idx = 0;
unsigned int real_time_idx = 0;
/* Check for a device path. If it's not present, print a usage statement. */
if ((argc != 2 && argc != 3) || (argc == 2 && strcasecmp(argv[1],"--help") == 0)) {
cout << "Usage: lms2xx_real_time_indices PATH [BAUD RATE]" << endl
<< "Ex: lms2xx_real_time_indices /dev/ttyUSB0 9600" << endl;
return -1;
}
/* Only device path is given */
if (argc == 2) {
device_str = argv[1];
}
/* Device path and baud are given */
if (argc == 3) {
device_str = argv[1];
if ((desired_baud = SickLMS2xx::StringToSickBaud(argv[2])) == SickLMS2xx::SICK_BAUD_UNKNOWN) {
cerr << "Invalid baud value! Valid values are: 9600, 19200, 38400, and 500000" << endl;
return -1;
}
}
/*
* Instantiate an instance
*/
SickLMS2xx sick_lms_2xx(device_str);
/*
* Initialize the Sick LMS 2xx
*/
try {
sick_lms_2xx.Initialize(desired_baud);
}
catch(...) {
cerr << "Initialize failed! Are you using the correct device path?" << endl;
return -1;
}
/*
* Ensure real-time indices are enabled
*/
if (sick_lms_2xx.GetSickAvailability() & SickLMS2xx::SICK_FLAG_AVAILABILITY_REAL_TIME_INDICES) {
try {
/*
* Acquire a few scans from the Sick LMS
*/
for (unsigned int i=0; i < 10; i++) {
/* We don't want Fields A,B, or C, so we pass NULL */
sick_lms_2xx.GetSickScan(values,num_values,NULL,NULL,NULL,&telegram_idx,&real_time_idx);
cout << "\t Num. Values: " << num_values << ", Msg Idx: " << telegram_idx
<< ", Real-time Idx: " << real_time_idx << endl;
}
}
/* Catch anything else and exit */
catch(...) {
cerr << "An error occurred!" << endl;
return -1;
}
}
else {
cout << "Please set the Sick LMS to an availability w/ real-time indices..." << endl;
cout << "Hint: Use the lms_config utility/example! :o)"<< endl;
}
/*
* Uninitialize the device
*/
try {
sick_lms_2xx.Uninitialize();
}
catch(...) {
cerr << "Uninitialize failed!" << endl;
return -1;
}
/* Success! */
return 0;
}

View File

@ -0,0 +1,12 @@
=================================================
Sick LIDAR Matlab/C++ Toolbox
=================================================
Example: lms_set_variant
Note: This example is NOT COMPATIBLE w/ LMS {211,221,291}-S14 LIDARs!
Desc: This example illustrates the proper way to switch the Sick LMS
variant (i.e. the Sick's FOV and scan resolution).
Example call (from build dir): ./lms_set_variant /dev/ttyUSB0 9600

View File

@ -0,0 +1,155 @@
/*!
* \file main.cc
* \brief Illustrates how to set the device variant and then
* acquire measured values
*
* Note: This example WILL NOT WORK for LMS 211-S14, 221-S14,
* 291-S14 models as they do not support variant switching.
*
* Code by Jason C. Derenick and Thomas H. Miller.
* Contact derenick(at)lehigh(dot)edu
*
* The Sick LIDAR Matlab/C++ Toolbox
* Copyright (c) 2008, Jason C. Derenick and Thomas H. Miller
* All rights reserved.
*
* This software is released under a BSD Open-Source License.
* See http://sicktoolbox.sourceforge.net
*/
/* Implementation dependencies */
#include <stdlib.h>
#include <string>
#include <iostream>
#include <sicktoolbox/SickLMS2xx.hh>
/* Use the namespace */
using namespace std;
using namespace SickToolbox;
int main(int argc, char * argv[]) {
string device_str;
SickLMS2xx::sick_lms_2xx_baud_t desired_baud = SickLMS2xx::SICK_BAUD_38400;
/* Check for a device path. If it's not present, print a usage statement. */
if ((argc != 2 && argc != 3) || (argc == 2 && strcasecmp(argv[1],"--help") == 0)) {
cout << "Usage: lms2xx_set_variant PATH [BAUD RATE]" << endl
<< "Ex: lms2xx_set_variant /dev/ttyUSB0 9600" << endl;
return -1;
}
/* Only device path is given */
if (argc == 2) {
device_str = argv[1];
}
/* Device path and baud are given */
if (argc == 3) {
device_str = argv[1];
if ((desired_baud = SickLMS2xx::StringToSickBaud(argv[2])) == SickLMS2xx::SICK_BAUD_UNKNOWN) {
cerr << "Invalid baud value! Valid values are: 9600, 19200, 38400, and 500000" << endl;
return -1;
}
}
/* Instantiate the SickLMS2xx class with the device path string. */
SickLMS2xx sick_lms_2xx(device_str);
/* Define some buffers to hold the returned measurements */
unsigned int values[SickLMS2xx::SICK_MAX_NUM_MEASUREMENTS] = {0};
unsigned int num_values = 0;
/*
* Initialize the Sick LMS 2xx
*/
try {
sick_lms_2xx.Initialize(desired_baud);
}
catch(...) {
cerr << "Initialize failed! Are you using the correct device path?" << endl;
return -1;
}
/*
* Check whether device is LMS Fast
*/
if (!sick_lms_2xx.IsSickLMS2xxFast()) {
try {
/*
* Set the device variant to 100/0.25
*
* NOTE: If an invalid variant definition is
* given a SickConfigException will be
* thrown stating so.
*
*/
cout << "\tSetting variant to 100/0.25" << std::endl << flush;
sick_lms_2xx.SetSickVariant(SickLMS2xx::SICK_SCAN_ANGLE_100,SickLMS2xx::SICK_SCAN_RESOLUTION_25);
/*
* Acquire some measurements from Sick LMS 2xx using 100/0.25
*/
cout << "\tAcquiring some measurements..." << endl;
for(unsigned int i = 0; i < 10; i++) {
/* Acquire the most recent scan from the Sick */
sick_lms_2xx.GetSickScan(values,num_values);
/* Display the number of measurements */
cout << "\t Num. Values: " << num_values << endl;
}
/*
* Set the device variant to 180/0.5
*/
cout << std::endl << "\tSetting variant to 180/0.50" << endl;
sick_lms_2xx.SetSickVariant(SickLMS2xx::SICK_SCAN_ANGLE_180,SickLMS2xx::SICK_SCAN_RESOLUTION_50);
/*
* Acquire some measurements from Sick LMS 2xx using 180/0.50
*/
cout << "\tAcquiring some measurements..." << endl;
for(unsigned int i = 0; i < 10; i++) {
/* Acquire the most recent scan from the Sick */
sick_lms_2xx.GetSickScan(values,num_values);
/* Display the number of measured values */
cout << "\t Num. Values: " << num_values << endl;
}
}
catch(...) {
cerr << "An error occurred!" << endl;
}
}
else {
cerr << "Oops... Your Sick is an LMS Fast!" << endl;
cerr << "It doesn't support the variant command." << endl;
}
/*
* Uninitialize the device
*/
try {
sick_lms_2xx.Uninitialize();
}
catch(...) {
cerr << "Uninitialize failed!" << endl;
return -1;
}
/* Success! */
return 0;
}

View File

@ -0,0 +1,13 @@
=================================================
Sick LIDAR Matlab/C++ Toolbox
=================================================
Example: lms_simple_app
Note: This example is COMPATIBLE w/ ALL Sick 2xx LIDAR units! :o)
Desc: This example provides a simple program template for grabbing
data from a Sick LMS 2xx LIDAR. It illustrates the simplest
use of the Sick LIDAR Toolkit w/ C++.
Example call (from build dir): ./lms_simple_app /dev/ttyUSB0 9600

View File

@ -0,0 +1,104 @@
/*!
* \file main.cc
* \brief A simple application using the Sick LMS 2xx driver.
*
* Code by Jason C. Derenick and Thomas H. Miller.
* Contact derenick(at)lehigh(dot)edu
*
* The Sick LIDAR Matlab/C++ Toolbox
* Copyright (c) 2008, Jason C. Derenick and Thomas H. Miller
* All rights reserved.
*
* This software is released under a BSD Open-Source License.
* See http://sicktoolbox.sourceforge.net
*/
#include <stdlib.h>
#include <string>
#include <iostream>
#include <sicktoolbox/SickLMS2xx.hh>
using namespace std;
using namespace SickToolbox;
int main(int argc, char* argv[])
{
string device_str;
SickLMS2xx::sick_lms_2xx_baud_t desired_baud = SickLMS2xx::SICK_BAUD_38400;
unsigned int values[SickLMS2xx::SICK_MAX_NUM_MEASUREMENTS] = {0}; // Uses macro defined in SickLMS2xx.hh
unsigned int num_values = 0; // Holds the number of measurements returned
/* Check for a device path. If it's not present, print a usage statement. */
if ((argc != 2 && argc != 3) || (argc == 2 && strcasecmp(argv[1],"--help") == 0)) {
cout << "Usage: lms2xx_simple_app PATH [BAUD RATE]" << endl
<< "Ex: lms2xx_simple_app /dev/ttyUSB0 9600" << endl;
return -1;
}
/* Only device path is given */
if (argc == 2) {
device_str = argv[1];
}
/* Device path and baud are given */
if (argc == 3) {
device_str = argv[1];
if ((desired_baud = SickLMS2xx::StringToSickBaud(argv[2])) == SickLMS2xx::SICK_BAUD_UNKNOWN) {
cerr << "Invalid baud value! Valid values are: 9600, 19200, 38400, and 500000" << endl;
return -1;
}
}
/*
* Instantiate an instance
*/
SickLMS2xx sick_lms_2xx(device_str);
/*
* Initialize the Sick LMS 2xx
*/
try {
sick_lms_2xx.Initialize(desired_baud);
}
catch(...) {
cerr << "Initialize failed! Are you using the correct device path?" << endl;
return -1;
}
/*
* Acquire a few scans from the Sick LMS
*/
try {
for (unsigned int i=0; i < 10; i++) {
sick_lms_2xx.GetSickScan(values,num_values);
cout << "\t Num. Values: " << num_values << endl;
}
}
/* Catch anything else and exit */
catch(...) {
cerr << "An error occurred!" << endl;
}
/*
* Uninitialize the device
*/
try {
sick_lms_2xx.Uninitialize();
}
catch(...) {
cerr << "Uninitialize failed!" << endl;
return -1;
}
/* Success! */
return 0;
}

View File

@ -0,0 +1,12 @@
=================================================
Sick LIDAR Matlab/C++ Toolbox
=================================================
Example: lms_stream_range_and_reflect
Note: This example is COMPATIBLE w/ ONLY Sick 291-S14 (LMS FAST) LIDAR units!
Desc: This example provides a simple program template for streaming
range and reflectivity data from a Sick LMS 291-S14 LIDAR.
Example call (from build dir): ./lms_stream_range_and_reflect /dev/ttyUSB0 9600

View File

@ -0,0 +1,117 @@
/*!
* \file main.cc
* \brief A simple program illustrating how to stream range
* and reflectivity returns from a Sick LMS 291-S14.
*
* Code by Jason C. Derenick and Thomas H. Miller.
* Contact derenick(at)lehigh(dot)edu
*
* The Sick LIDAR Matlab/C++ Toolbox
* Copyright (c) 2008, Jason C. Derenick and Thomas H. Miller
* All rights reserved.
*
* This software is released under a BSD Open-Source License.
* See http://sicktoolbox.sourceforge.net
*/
#include <stdlib.h>
#include <string>
#include <iostream>
#include <sicktoolbox/SickLMS2xx.hh>
using namespace std;
using namespace SickToolbox;
int main(int argc, char* argv[]) {
string device_str;
SickLMS2xx::sick_lms_2xx_baud_t desired_baud = SickLMS2xx::SICK_BAUD_38400;
unsigned int num_range_values;
unsigned int num_reflect_values;
unsigned int range_values[SickLMS2xx::SICK_MAX_NUM_MEASUREMENTS] = {0};
unsigned int reflect_values[SickLMS2xx::SICK_MAX_NUM_MEASUREMENTS] = {0};
/* Check for a device path. If it's not present, print a usage statement. */
if ((argc != 2 && argc != 3) || (argc == 2 && strcasecmp(argv[1],"--help") == 0)) {
cout << "Usage: lms2xx_stream_range_and_reflect PATH [BAUD RATE]" << endl
<< "Ex: lms2xx_stream_range_and_reflect /dev/ttyUSB0 9600" << endl;
return -1;
}
/* Only device path is given */
if (argc == 2) {
device_str = argv[1];
}
/* Device path and baud are given */
if (argc == 3) {
device_str = argv[1];
if ((desired_baud = SickLMS2xx::StringToSickBaud(argv[2])) == SickLMS2xx::SICK_BAUD_UNKNOWN) {
cerr << "Invalid baud value! Valid values are: 9600, 19200, 38400, and 500000" << endl;
return -1;
}
}
/*
* Instantiate driver instance
*/
SickLMS2xx sick_lms_2xx(device_str);
/*
* Initialize the Sick LMS 2xx
*/
try {
sick_lms_2xx.Initialize(desired_baud);
}
catch(...) {
cerr << "Initialize failed! Are you using the correct device path?" << endl;
return -1;
}
/*
* Ensure it is an LMS Fast model
*/
if (sick_lms_2xx.IsSickLMS2xxFast()) {
/*
* Grab range and reflectivity data from the Sick LMS Fast
*/
try {
for (unsigned int i=0; i < 10; i++) {
sick_lms_2xx.GetSickScan(range_values,reflect_values,num_range_values,num_reflect_values);
cout << "Num. Range Vals: " << num_range_values << " Num. Reflect Vals: " << num_reflect_values << endl;
}
}
catch (...) {
cerr << "An error occurred!" << endl;
}
}
else {
cerr << "Oops... Your Sick is NOT an LMS Fast!" << endl;
cerr << "It doesn't support this kind of stream." << endl;
}
/*
* Uninitialize the device
*/
try {
sick_lms_2xx.Uninitialize();
}
catch(...) {
cerr << "Uninitialize failed!" << endl;
return -1;
}
/* Success! */
return 0;
}

View File

@ -0,0 +1,12 @@
=================================================
Sick LIDAR Matlab/C++ Toolbox
=================================================
Example: lms_subrange
Note: This example is COMPATIBLE w/ ALL Sick 2xx LIDAR units! :o)
Desc: This example illustrates how to acquire a scan subrange from
the Sick LMS.
Example call (from build dir): ./lms_subrange /dev/ttyUSB0 9600

View File

@ -0,0 +1,109 @@
/*!
* \file main.cc
* \brief A simple program illustrating how to acquire a scan
* subrange from a Sick LMS 2xx.
*
* Code by Jason C. Derenick and Thomas H. Miller.
* Contact derenick(at)lehigh(dot)edu
*
* The Sick LIDAR Matlab/C++ Toolbox
* Copyright (c) 2008, Jason C. Derenick and Thomas H. Miller
* All rights reserved.
*
* This software is released under a BSD Open-Source License.
* See http://sicktoolbox.sourceforge.net
*/
#include <stdlib.h>
#include <string>
#include <iostream>
#include <sicktoolbox/SickLMS2xx.hh>
using namespace std;
using namespace SickToolbox;
int main(int argc, char* argv[])
{
string device_str;
SickLMS2xx::sick_lms_2xx_baud_t desired_baud = SickLMS2xx::SICK_BAUD_38400;
unsigned int values[SickLMS2xx::SICK_MAX_NUM_MEASUREMENTS] = {0}; // Uses macro defined in SickLMS2xx.hh
unsigned int num_values; // Holds the number of measurements returned
/* Check for a device path. If it's not present, print a usage statement. */
if ((argc != 2 && argc != 3) || (strcasecmp(argv[1],"--help") == 0)) {
cout << "Usage: lms2xx_subrange PATH [BAUD RATE]" << endl
<< "Ex: lms2xx_subrange /dev/ttyUSB0 9600" << endl;
return -1;
}
/* Only device path is given */
if (argc == 2) {
device_str = argv[1];
}
/* Device path and baud are given */
if (argc == 3) {
device_str = argv[1];
if ((desired_baud = SickLMS2xx::StringToSickBaud(argv[2])) == SickLMS2xx::SICK_BAUD_UNKNOWN) {
cerr << "Invalid baud value! Valid values are: 9600, 19200, 38400, and 500000" << endl;
return -1;
}
}
/*
* Instantiate an instance
*/
SickLMS2xx sick_lms_2xx(device_str);
/*
* Initialize the Sick LMS 2xx
*/
try {
sick_lms_2xx.Initialize(desired_baud);
}
catch(...) {
cerr << "Initialize failed! Are you using the correct device path?" << endl;
return -1;
}
try {
/*
* Acquire a few scans from the Sick LMS
*/
for (unsigned int i=0; i < 10; i++) {
/*
* Acquire the first ten measurements of a scan from the Sick
*/
sick_lms_2xx.GetSickScanSubrange(1,10,values,num_values);
cout << "\t Num. Values: " << num_values << endl;
}
}
catch(...) {
cerr << "An error occurred!" << endl;
}
/*
* Uninitialize the device
*/
try {
sick_lms_2xx.Uninitialize();
}
catch(...) {
cerr << "Uninitialize failed!" << endl;
return -1;
}
/* Success! */
return 0;
}

View File

@ -0,0 +1,241 @@
# Doxygen 1.5.1
#---------------------------------------------------------------------------
# Project related configuration options
#---------------------------------------------------------------------------
PROJECT_NAME = $(PROJECT)-$(VERSION)
PROJECT_NUMBER =
OUTPUT_DIRECTORY = $(DOCDIR)
CREATE_SUBDIRS = NO
OUTPUT_LANGUAGE = English
USE_WINDOWS_ENCODING = NO
BRIEF_MEMBER_DESC = YES
REPEAT_BRIEF = YES
ABBREVIATE_BRIEF =
ALWAYS_DETAILED_SEC = NO
INLINE_INHERITED_MEMB = NO
FULL_PATH_NAMES = YES
STRIP_FROM_PATH = $(SRCDIR)
STRIP_FROM_INC_PATH = $(SRCDIR)
SHORT_NAMES = YES
JAVADOC_AUTOBRIEF = NO
MULTILINE_CPP_IS_BRIEF = NO
DETAILS_AT_TOP = NO
INHERIT_DOCS = YES
SEPARATE_MEMBER_PAGES = NO
TAB_SIZE = 8
ALIASES =
OPTIMIZE_OUTPUT_FOR_C = NO
OPTIMIZE_OUTPUT_JAVA = NO
BUILTIN_STL_SUPPORT = NO
DISTRIBUTE_GROUP_DOC = NO
SUBGROUPING = YES
#---------------------------------------------------------------------------
# Build related configuration options
#---------------------------------------------------------------------------
EXTRACT_ALL = YES
EXTRACT_PRIVATE = NO
EXTRACT_STATIC = NO
EXTRACT_LOCAL_CLASSES = YES
EXTRACT_LOCAL_METHODS = NO
HIDE_UNDOC_MEMBERS = NO
HIDE_UNDOC_CLASSES = NO
HIDE_FRIEND_COMPOUNDS = NO
HIDE_IN_BODY_DOCS = NO
INTERNAL_DOCS = NO
CASE_SENSE_NAMES = YES
HIDE_SCOPE_NAMES = NO
SHOW_INCLUDE_FILES = YES
INLINE_INFO = YES
SORT_MEMBER_DOCS = YES
SORT_BRIEF_DOCS = NO
SORT_BY_SCOPE_NAME = NO
GENERATE_TODOLIST = YES
GENERATE_TESTLIST = YES
GENERATE_BUGLIST = YES
GENERATE_DEPRECATEDLIST= YES
ENABLED_SECTIONS =
MAX_INITIALIZER_LINES = 30
SHOW_USED_FILES = YES
SHOW_DIRECTORIES = NO
FILE_VERSION_FILTER =
#---------------------------------------------------------------------------
# configuration options related to warning and progress messages
#---------------------------------------------------------------------------
QUIET = NO
WARNINGS = YES
WARN_IF_UNDOCUMENTED = YES
WARN_IF_DOC_ERROR = YES
WARN_NO_PARAMDOC = NO
WARN_FORMAT = "$file:$line: $text"
WARN_LOGFILE =
#---------------------------------------------------------------------------
# configuration options related to the input files
#---------------------------------------------------------------------------
INPUT = $(SRCDIR)
FILE_PATTERNS = *.cc *.hh
RECURSIVE = YES
EXCLUDE = $(SRCDIR)/c++/examples
EXCLUDE_SYMLINKS = NO
EXCLUDE_PATTERNS =
EXAMPLE_PATH =
EXAMPLE_PATTERNS =
EXAMPLE_RECURSIVE = NO
IMAGE_PATH =
INPUT_FILTER =
FILTER_PATTERNS =
FILTER_SOURCE_FILES = NO
#---------------------------------------------------------------------------
# configuration options related to source browsing
#---------------------------------------------------------------------------
SOURCE_BROWSER = NO
INLINE_SOURCES = NO
STRIP_CODE_COMMENTS = NO
REFERENCED_BY_RELATION = YES
REFERENCES_RELATION = YES
REFERENCES_LINK_SOURCE = YES
USE_HTAGS = NO
VERBATIM_HEADERS = YES
#---------------------------------------------------------------------------
# configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
ALPHABETICAL_INDEX = YES
COLS_IN_ALPHA_INDEX = 5
IGNORE_PREFIX =
#---------------------------------------------------------------------------
# configuration options related to the HTML output
#---------------------------------------------------------------------------
GENERATE_HTML = $(GENERATE_HTML)
HTML_OUTPUT = html
HTML_FILE_EXTENSION = .html
HTML_HEADER =
HTML_FOOTER =
HTML_STYLESHEET =
HTML_ALIGN_MEMBERS = YES
GENERATE_HTMLHELP = $(GENERATE_CHM)
CHM_FILE = ../$(PROJECT).chm
HHC_LOCATION = $(HHC_PATH)
GENERATE_CHI = $(GENERATE_CHI)
BINARY_TOC = NO
TOC_EXPAND = NO
DISABLE_INDEX = NO
ENUM_VALUES_PER_LINE = 4
GENERATE_TREEVIEW = YES
TREEVIEW_WIDTH = 250
#---------------------------------------------------------------------------
# configuration options related to the LaTeX output
#---------------------------------------------------------------------------
GENERATE_LATEX = $(GENERATE_LATEX)
LATEX_OUTPUT = latex
LATEX_CMD_NAME = latex
MAKEINDEX_CMD_NAME = makeindex
COMPACT_LATEX = NO
PAPER_TYPE = $(PAPER_SIZE)
EXTRA_PACKAGES =
LATEX_HEADER =
PDF_HYPERLINKS = NO
USE_PDFLATEX = NO
LATEX_BATCHMODE = YES
LATEX_HIDE_INDICES = NO
#---------------------------------------------------------------------------
# configuration options related to the RTF output
#---------------------------------------------------------------------------
GENERATE_RTF = $(GENERATE_RTF)
RTF_OUTPUT = rtf
COMPACT_RTF = NO
RTF_HYPERLINKS = NO
RTF_STYLESHEET_FILE =
RTF_EXTENSIONS_FILE =
#---------------------------------------------------------------------------
# configuration options related to the man page output
#---------------------------------------------------------------------------
GENERATE_MAN = $(GENERATE_MAN)
MAN_OUTPUT = man
MAN_EXTENSION = .1
MAN_LINKS = NO
#---------------------------------------------------------------------------
# configuration options related to the XML output
#---------------------------------------------------------------------------
GENERATE_XML = $(GENERATE_XML)
XML_OUTPUT = xml
XML_SCHEMA =
XML_DTD =
XML_PROGRAMLISTING = YES
#---------------------------------------------------------------------------
# configuration options for the AutoGen Definitions output
#---------------------------------------------------------------------------
GENERATE_AUTOGEN_DEF = NO
#---------------------------------------------------------------------------
# configuration options related to the Perl module output
#---------------------------------------------------------------------------
GENERATE_PERLMOD = NO
PERLMOD_LATEX = NO
PERLMOD_PRETTY = YES
PERLMOD_MAKEVAR_PREFIX =
#---------------------------------------------------------------------------
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = NO
EXPAND_ONLY_PREDEF = NO
SEARCH_INCLUDES = YES
INCLUDE_PATH =
INCLUDE_FILE_PATTERNS =
PREDEFINED =
EXPAND_AS_DEFINED =
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------
# Configuration::additions related to external references
#---------------------------------------------------------------------------
TAGFILES =
GENERATE_TAGFILE = $(DOCDIR)/$(PROJECT).tag
ALLEXTERNALS = NO
EXTERNAL_GROUPS = YES
PERL_PATH = $(PERL_PATH)
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
CLASS_DIAGRAMS = YES
HIDE_UNDOC_RELATIONS = YES
HAVE_DOT = $(HAVE_DOT)
CLASS_GRAPH = YES
COLLABORATION_GRAPH = YES
GROUP_GRAPHS = YES
UML_LOOK = NO
TEMPLATE_RELATIONS = NO
INCLUDE_GRAPH = YES
INCLUDED_BY_GRAPH = YES
CALL_GRAPH = NO
CALLER_GRAPH = NO
GRAPHICAL_HIERARCHY = YES
DIRECTORY_GRAPH = YES
DOT_IMAGE_FORMAT = png
DOT_PATH = $(DOT_PATH)
DOTFILE_DIRS =
MAX_DOT_GRAPH_WIDTH = 1024
MAX_DOT_GRAPH_HEIGHT = 1024
MAX_DOT_GRAPH_DEPTH = 0
DOT_TRANSPARENT = NO
DOT_MULTI_TARGETS = NO
GENERATE_LEGEND = YES
DOT_CLEANUP = YES
#---------------------------------------------------------------------------
# Configuration::additions related to the search engine
#---------------------------------------------------------------------------
SEARCHENGINE = NO

View File

@ -0,0 +1,471 @@
/*!
* \file SickBufferMonitor.hh
* \brief Defines an abstract class for interfacing with a Sick LIDAR.
*
* Code by Jason C. Derenick and Thomas H. Miller.
* Contact derenick(at)lehigh(dot)edu
*
* The Sick LIDAR Matlab/C++ Toolbox
* Copyright (c) 2008, Jason C. Derenick and Thomas H. Miller
* All rights reserved.
*
* This software is released under a BSD Open-Source License.
* See http://sicktoolbox.sourceforge.net
*/
#ifndef SICK_BUFFER_MONITOR
#define SICK_BUFFER_MONITOR
/* Dependencies */
#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include "SickException.hh"
/* Associate the namespace */
namespace SickToolbox {
/**
* \class SickBufferMonitor
*/
template < class SICK_MONITOR_CLASS, class SICK_MSG_CLASS >
class SickBufferMonitor {
public:
/** A standard constructor */
SickBufferMonitor( SICK_MONITOR_CLASS * const monitor_instance ) throw( SickThreadException );
/** A method for setting the target data stream */
void SetDataStream( const unsigned int sick_fd ) throw( SickThreadException );
/** Start the buffer monitor for the device */
void StartMonitor( const unsigned int sick_fd ) throw( SickThreadException );
/** Acquire the most recent message buffered by the monitor */
bool GetNextMessageFromMonitor( SICK_MSG_CLASS &sick_message ) throw( SickThreadException );
/** Stop the buffer monitor for the device */
void StopMonitor( ) throw( SickThreadException );
/** Locks access to the data stream */
void AcquireDataStream( ) throw( SickThreadException );
/** Acquire the next message from raw byte stream */
void GetNextMessageFromDataStream( SICK_MSG_CLASS &sick_message );
/** Unlock access to the data stream */
void ReleaseDataStream( ) throw( SickThreadException );
/** A standard destructor */
~SickBufferMonitor( ) throw( SickThreadException );
protected:
/** Sick data stream file descriptor */
unsigned int _sick_fd;
/** Reads n bytes into the destination buffer */
void _readBytes( uint8_t * const dest_buffer, const int num_bytes_to_read, const unsigned int timeout_value = 0 ) const throw ( SickTimeoutException, SickIOException );
private:
/** The current monitor instance */
SICK_MONITOR_CLASS *_sick_monitor_instance;
/** A flag to indicate the monitor should continue running */
bool _continue_grabbing;
/** Buffer monitor thread ID */
pthread_t _monitor_thread_id;
/** A mutex for guarding the message container */
pthread_mutex_t _container_mutex;
/** A mutex for locking the data stream */
pthread_mutex_t _stream_mutex;
/** A container to hold the most recent message */
SICK_MSG_CLASS _recv_msg_container;
/** Locks access to the message container */
void _acquireMessageContainer( ) throw( SickThreadException );
/** Unlocks access to the message container */
void _releaseMessageContainer( ) throw( SickThreadException );
/** Entry point for the monitor thread */
static void * _bufferMonitorThread( void * thread_args );
};
/**
* \brief Primary constructor
* \param device_instance A pointer to the current driver instance
*/
template < class SICK_MONITOR_CLASS, class SICK_MSG_CLASS >
SickBufferMonitor< SICK_MONITOR_CLASS, SICK_MSG_CLASS >::SickBufferMonitor( SICK_MONITOR_CLASS * const monitor_instance ) throw( SickThreadException ) :
_sick_monitor_instance(monitor_instance), _continue_grabbing(true), _monitor_thread_id(0) {
/* Initialize the shared message buffer mutex */
if (pthread_mutex_init(&_container_mutex,NULL) != 0) {
throw SickThreadException("SickBufferMonitor::SickBufferMonitor: pthread_mutex_init() failed!");
}
/* Initialize the shared data stream mutex */
if (pthread_mutex_init(&_stream_mutex,NULL) != 0) {
throw SickThreadException("SickBufferMonitor::SickBufferMonitor: pthread_mutex_init() failed!");
}
}
/**
* \brief A method for setting/changing the current data stream
* \param sick_fd The data stream file descriptor
*/
template < class SICK_MONITOR_CLASS, class SICK_MSG_CLASS >
void SickBufferMonitor< SICK_MONITOR_CLASS, SICK_MSG_CLASS >::SetDataStream( const unsigned int sick_fd ) throw ( SickThreadException ) {
try {
/* Attempt to acquire the data stream */
AcquireDataStream();
/* Assign the data stream fd */
_sick_fd = sick_fd;
/* Attempt to release the data stream */
ReleaseDataStream();
}
/* Handle thread exception */
catch(SickThreadException &sick_thread_exception) {
std::cerr << sick_thread_exception.what() << std::endl;
}
/* A safety net */
catch(...) {
std::cerr << "SickBufferMonitor::SetDataStream: Unknown exception!" << std::endl;
throw;
}
}
/**
* \brief Creates and starts the buffer monitor thread
* \return True upon success, False otherwise
*/
template < class SICK_MONITOR_CLASS, class SICK_MSG_CLASS >
void SickBufferMonitor< SICK_MONITOR_CLASS, SICK_MSG_CLASS >::StartMonitor( const unsigned int sick_fd ) throw ( SickThreadException ) {
/* Assign the fd associated with the data stream */
_sick_fd = sick_fd;
/* Start the buffer monitor */
if (pthread_create(&_monitor_thread_id,NULL,SickBufferMonitor< SICK_MONITOR_CLASS, SICK_MSG_CLASS >::_bufferMonitorThread,_sick_monitor_instance) != 0) {
throw SickThreadException("SickBufferMonitor::StartMonitor: pthread_create() failed!");
}
/* Set the flag to continue grabbing data */
_continue_grabbing = true;
}
/**
* \brief Checks the message container for the next available Sick message
* \param &sick_message The message object that is to be populated with the results
* \return True if the current contents were acquired, false otherwise
*/
template < class SICK_MONITOR_CLASS, class SICK_MSG_CLASS >
bool SickBufferMonitor< SICK_MONITOR_CLASS, SICK_MSG_CLASS >::GetNextMessageFromMonitor( SICK_MSG_CLASS &sick_message ) throw( SickThreadException ) {
bool acquired_message = false;
try {
/* Acquire a lock on the message buffer */
_acquireMessageContainer();
/* Check whether the object is populated */
if (_recv_msg_container.IsPopulated()) {
/* Copy the shared message */
sick_message = _recv_msg_container;
_recv_msg_container.Clear();
/* Set the flag indicating success */
acquired_message = true;
}
/* Release message container */
_releaseMessageContainer();
}
/* Handle a thread exception */
catch(SickThreadException &sick_thread_exception) {
std::cerr << sick_thread_exception.what() << std::endl;
throw;
}
/* Handle an unknown exception */
catch(...) {
std::cerr << "SickBufferMonitor::CheckMessageContainer: Unknown exception!" << std::endl;
throw;
}
/* Return the flag */
return acquired_message;
}
/**
* \brief Cancels the buffer monitor thread
* \return True if the thread was properly canceled, false otherwise
*/
template < class SICK_MONITOR_CLASS, class SICK_MSG_CLASS >
void SickBufferMonitor< SICK_MONITOR_CLASS, SICK_MSG_CLASS >::StopMonitor( ) throw ( SickThreadException ) {
try {
/* Return results from the thread */
void *monitor_result = NULL;
/* Tell the thread to quit working */
AcquireDataStream();
_continue_grabbing = false;
ReleaseDataStream();
/* Wait for the buffer monitor to exit */
if (pthread_join(_monitor_thread_id,&monitor_result) != 0) {
throw SickThreadException("SickBufferMonitor::StopMonitor: pthread_join() failed!");
}
}
/* Handle thread exception */
catch(SickThreadException &sick_thread_exception) {
std::cerr << sick_thread_exception.what() << std::endl;
}
/* A safety net */
catch(...) {
std::cerr << "SickBufferMonitor::StopMonitor: Unknown exception!" << std::endl;
throw;
}
}
/**
* \brief Acquires a lock on the data stream
*/
template < class SICK_MONITOR_CLASS, class SICK_MSG_CLASS >
void SickBufferMonitor< SICK_MONITOR_CLASS, SICK_MSG_CLASS >::AcquireDataStream( ) throw( SickThreadException ) {
/* Attempt to lock the stream mutex */
if (pthread_mutex_lock(&_stream_mutex) != 0) {
throw SickThreadException("SickBufferMonitor::AcquireDataStream: pthread_mutex_lock() failed!");
}
}
/**
* \brief Releases a lock on the data stream
*/
template < class SICK_MONITOR_CLASS, class SICK_MSG_CLASS >
void SickBufferMonitor< SICK_MONITOR_CLASS, SICK_MSG_CLASS >::ReleaseDataStream( ) throw( SickThreadException ) {
/* Attempt to lock the stream mutex */
if (pthread_mutex_unlock(&_stream_mutex) != 0) {
throw SickThreadException("SickBufferMonitor::ReleaseDataStream: pthread_mutex_unlock() failed!");
}
}
/**
* \brief The destructor (kills the mutex)
*/
template < class SICK_MONITOR_CLASS, class SICK_MSG_CLASS >
SickBufferMonitor< SICK_MONITOR_CLASS, SICK_MSG_CLASS >::~SickBufferMonitor( ) throw( SickThreadException ) {
/* Destroy the message container mutex */
if (pthread_mutex_destroy(&_container_mutex) != 0) {
throw SickThreadException("SickBufferMonitor::~SickBufferMonitor: pthread_mutex_destroy() failed!");
}
/* Destroy the data stream container mutex */
if (pthread_mutex_destroy(&_stream_mutex) != 0) {
throw SickThreadException("SickBufferMonitor::~SickBufferMonitor: pthread_mutex_destroy() failed!");
}
}
/**
* \brief Locks access to the message container
*/
template < class SICK_MONITOR_CLASS, class SICK_MSG_CLASS >
void SickBufferMonitor< SICK_MONITOR_CLASS, SICK_MSG_CLASS >::_acquireMessageContainer( ) throw( SickThreadException ) {
/* Lock the mutex */
if (pthread_mutex_lock(&_container_mutex) != 0) {
throw SickThreadException("SickBufferMonitor::_acquireMessageContainer: pthread_mutex_lock() failed!");
}
}
/**
* \brief Unlocks access to the message container
*/
template < class SICK_MONITOR_CLASS, class SICK_MSG_CLASS >
void SickBufferMonitor< SICK_MONITOR_CLASS, SICK_MSG_CLASS >::_releaseMessageContainer( ) throw( SickThreadException ) {
/* Unlock the mutex */
if (pthread_mutex_unlock(&_container_mutex) != 0) {
throw SickThreadException("SickBufferMonitor::_releaseMessageContainer: pthread_mutex_unlock() failed!");
}
}
/**
* \brief Attempt to read a certain number of bytes from the stream
* \param *dest_buffer A pointer to the destination buffer
* \param num_bytes_to_read The number of bytes to read into the buffer
* \param timeout_value The number of microseconds allowed between subsequent bytes in a message
* \return True if the number of requested bytes were successfully read
*/
template< class SICK_MONITOR_CLASS, class SICK_MSG_CLASS >
void SickBufferMonitor< SICK_MONITOR_CLASS, SICK_MSG_CLASS >::_readBytes( uint8_t * const dest_buffer, const int num_bytes_to_read, const unsigned int timeout_value ) const
throw ( SickTimeoutException, SickIOException ) {
/* Some helpful variables */
int num_bytes_read = 0;
int total_num_bytes_read = 0;
int num_active_files = 0;
struct timeval timeout_val; // This structure will be used for setting our timeout values
fd_set file_desc_set; // File descriptor set for monitoring I/O
/* Attempt to fetch the bytes */
while ( total_num_bytes_read < num_bytes_to_read ) {
/* Initialize and set the file descriptor set for select */
FD_ZERO(&file_desc_set);
FD_SET(_sick_fd,&file_desc_set);
/* Setup the timeout structure */
memset(&timeout_val,0,sizeof(timeout_val)); // Initialize the buffer
timeout_val.tv_usec = timeout_value; // Wait for specified time before throwing a timeout
/* Wait for the OS to tell us that data is waiting! */
num_active_files = select(getdtablesize(),&file_desc_set,0,0,(timeout_value > 0) ? &timeout_val : 0);
/* Figure out what to do based on the output of select */
if (num_active_files > 0) {
/* A file is ready for reading!
*
* NOTE: The following conditional is just a sanity check. Since
* the file descriptor set only contains the sick device fd,
* it likely unnecessary to use FD_ISSET
*/
if (FD_ISSET(_sick_fd,&file_desc_set)) {
/* Read a single byte from the stream! */
num_bytes_read = read(_sick_fd,&dest_buffer[total_num_bytes_read],1);
/* Decide what to do based on the output of read */
if (num_bytes_read > 0) { //Update the number of bytes read so far
total_num_bytes_read += num_bytes_read;
}
else {
/* If this happens, something is wrong */
throw SickIOException("SickBufferMonitor::_readBytes: read() failed!");
}
}
}
else if (num_active_files == 0) {
/* A timeout has occurred! */
throw SickTimeoutException("SickBufferMonitor::_readBytes: select() timeout!");
}
else {
/* An error has occurred! */
throw SickIOException("SickBufferMonitor::_readBytes: select() failed!");
}
}
}
/**
* \brief The monitor thread
* \param *args The thread arguments
*/
template < class SICK_MONITOR_CLASS, class SICK_MSG_CLASS >
void * SickBufferMonitor< SICK_MONITOR_CLASS, SICK_MSG_CLASS >::_bufferMonitorThread( void * thread_args ) {
/* Declare a Sick LD receive object */
SICK_MSG_CLASS curr_message;
/* Acquire the Sick device instance */
SICK_MONITOR_CLASS *buffer_monitor = (SICK_MONITOR_CLASS *)thread_args;
/* The main thread control loop */
for (;;) {
try {
/* Reset the sick message object */
curr_message.Clear();
/* Acquire the most recent message */
buffer_monitor->AcquireDataStream();
if (!buffer_monitor->_continue_grabbing) { // should the thread continue grabbing
buffer_monitor->ReleaseDataStream();
break;
}
buffer_monitor->GetNextMessageFromDataStream(curr_message);
buffer_monitor->ReleaseDataStream();
/* Update message container contents */
buffer_monitor->_acquireMessageContainer();
buffer_monitor->_recv_msg_container = curr_message;
buffer_monitor->_releaseMessageContainer();
}
/* Make sure there wasn't a serious error reading from the buffer */
catch(SickIOException &sick_io_exception) {
std::cerr << sick_io_exception.what() << std::endl;
}
/* Catch any thread exceptions */
catch(SickThreadException &sick_thread_exception) {
std::cerr << sick_thread_exception.what() << std::endl;
}
/* A failsafe */
catch(...) {
std::cerr << "SickBufferMonitor::_bufferMonitorThread: Unknown exception!" << std::endl;
}
/* sleep a bit! */
usleep(1000);
}
/* Thread is done */
return NULL;
}
} /* namespace SickToolbox */
#endif /* SICK_BUFFER_MONITOR */

View File

@ -0,0 +1,186 @@
/* c++/drivers/base/src/SickConfig.hh. Generated from SickConfig.hh.in by configure. */
/* c++/drivers/base/src/SickConfig.hh.in. Generated from configure.ac by autoheader. */
/* Define if building universal (internal helper macro) */
/* #undef AC_APPLE_UNIVERSAL_BUILD */
/* Define to 1 if you have the <arpa/inet.h> header file. */
#define HAVE_ARPA_INET_H 1
/* Define to 1 if you have the <dlfcn.h> header file. */
#define HAVE_DLFCN_H 1
/* Define to 1 if you have the <fcntl.h> header file. */
#define HAVE_FCNTL_H 1
/* Define to 1 if you have the `gettimeofday' function. */
#define HAVE_GETTIMEOFDAY 1
/* Define if you have gnuplot */
/* #undef HAVE_GNUPLOT */
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
/* Define if you have linux/serial.h */
#define HAVE_LINUX_SERIAL_H 1
/* Define to 1 if you have the <memory.h> header file. */
#define HAVE_MEMORY_H 1
/* Define to 1 if you have the `memset' function. */
#define HAVE_MEMSET 1
/* Define to 1 if you have the <netinet/in.h> header file. */
#define HAVE_NETINET_IN_H 1
/* Define if you have POSIX threads libraries and header files. */
#define HAVE_PTHREAD 1
/* Define to 1 if you have the `select' function. */
#define HAVE_SELECT 1
/* Define to 1 if you have the `socket' function. */
#define HAVE_SOCKET 1
/* Define to 1 if stdbool.h conforms to C99. */
#define HAVE_STDBOOL_H 1
/* Define to 1 if you have the <stdint.h> header file. */
#define HAVE_STDINT_H 1
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
/* Define to 1 if you have the `strcasecmp' function. */
#define HAVE_STRCASECMP 1
/* Define to 1 if you have the <strings.h> header file. */
#define HAVE_STRINGS_H 1
/* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H 1
/* Define to 1 if you have the <sys/ioctl.h> header file. */
#define HAVE_SYS_IOCTL_H 1
/* Define to 1 if you have the <sys/select.h> header file. */
#define HAVE_SYS_SELECT_H 1
/* Define to 1 if you have the <sys/socket.h> header file. */
#define HAVE_SYS_SOCKET_H 1
/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/time.h> header file. */
#define HAVE_SYS_TIME_H 1
/* Define to 1 if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the <termios.h> header file. */
#define HAVE_TERMIOS_H 1
/* Define to 1 if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1
/* Define to 1 if the system has the type `_Bool'. */
#define HAVE__BOOL 1
/* Define to the sub-directory in which libtool stores uninstalled libraries.
*/
#define LT_OBJDIR ".libs/"
/* Name of package */
#define PACKAGE "sicktoolbox"
/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT "jasonder@seas.upenn.edu"
/* Define to the full name of this package. */
#define PACKAGE_NAME "SickToolbox"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "SickToolbox 1.1"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "sicktoolbox"
/* Define to the home page for this package. */
#define PACKAGE_URL ""
/* Define to the version of this package. */
#define PACKAGE_VERSION "1.1"
/* Define to necessary symbol if this constant uses a non-standard name on
your system. */
/* #undef PTHREAD_CREATE_JOINABLE */
/* Define as the return type of signal handlers (`int' or `void'). */
#define RETSIGTYPE void
/* Define to the type of arg 1 for `select'. */
#define SELECT_TYPE_ARG1 int
/* Define to the type of args 2, 3 and 4 for `select'. */
#define SELECT_TYPE_ARG234 (fd_set *)
/* Define to the type of arg 5 for `select'. */
#define SELECT_TYPE_ARG5 (struct timeval *)
/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
#define TIME_WITH_SYS_TIME 1
/* Version number of package */
#define VERSION "1.1"
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
significant byte first (like Motorola and SPARC, unlike Intel). */
#if defined AC_APPLE_UNIVERSAL_BUILD
# if defined __BIG_ENDIAN__
# define WORDS_BIGENDIAN 1
# endif
#else
# ifndef WORDS_BIGENDIAN
/* # undef WORDS_BIGENDIAN */
# endif
#endif
/* Define for Solaris 2.5.1 so the uint32_t typedef from <sys/synch.h>,
<pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
#define below would cause a syntax error. */
/* #undef _UINT32_T */
/* Define for Solaris 2.5.1 so the uint8_t typedef from <sys/synch.h>,
<pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
#define below would cause a syntax error. */
/* #undef _UINT8_T */
/* Define to empty if `const' does not conform to ANSI C. */
/* #undef const */
/* Define to `__inline__' or `__inline' if that's what the C compiler
calls it, or to nothing if 'inline' is not supported under any name. */
#ifndef __cplusplus
/* #undef inline */
#endif
/* Define to the type of a signed integer type of width exactly 16 bits if
such a type exists and the standard includes do not define it. */
/* #undef int16_t */
/* Define to the type of an unsigned integer type of width exactly 16 bits if
such a type exists and the standard includes do not define it. */
/* #undef uint16_t */
/* Define to the type of an unsigned integer type of width exactly 32 bits if
such a type exists and the standard includes do not define it. */
/* #undef uint32_t */
/* Define to the type of an unsigned integer type of width exactly 8 bits if
such a type exists and the standard includes do not define it. */
/* #undef uint8_t */

View File

@ -0,0 +1,244 @@
/*!
* \file SickException.hh
* \brief Contains some simple exception classes.
*
* Code by Jason C. Derenick and Thomas H. Miller.
* Contact derenick(at)lehigh(dot)edu
*
* The Sick LIDAR Matlab/C++ Toolbox
* Copyright (c) 2008, Jason C. Derenick and Thomas H. Miller
* All rights reserved.
*
* This software is released under a BSD Open-Source License.
* See http://sicktoolbox.sourceforge.net
*/
#ifndef SICK_EXCEPTION
#define SICK_EXCEPTION
/* Definition dependencies */
#include <string>
#include <exception>
/* Associate the namespace */
namespace SickToolbox {
/** \class SickException
* \brief Provides a base exception class from
* which to derive other Sick exceptions
*/
class SickException : std::exception {
public:
/**
* \brief A standard constructor
* \param general_str A descriptive "general" string
*/
SickException( const std::string general_str ) {
_detailed_msg = general_str;
}
/**
* \brief A standard constructor
* \param general_str A descriptive "general" string
* \param detailed_str A more detailed description
*/
SickException( const std::string general_str, const std::string detailed_str ) {
_detailed_msg = general_str + " " + detailed_str;
}
/**
* \brief From the standard exception library
*/
virtual const char* what( ) const throw() {
return _detailed_msg.c_str();
}
/**
* \brief A destructor
*/
~SickException() throw() {}
private:
/** The string identifier */
std::string _detailed_msg;
};
/**
* \class SickTimeoutException
* \brief Makes handling timeouts much easier
*/
class SickTimeoutException : public SickException {
public:
/**
* \brief A constructor
*/
SickTimeoutException() :
SickException("A Timeout Occurred!") { }
/**
* \brief A constructor
* \param detailed_str A more detailed description
*/
SickTimeoutException( const std::string detailed_str ) :
SickException("A Timeout Occurred -",detailed_str) { }
/**
* \brief A destructor
*/
~SickTimeoutException() throw() { }
};
/**
* \class SickIOException
* \brief Thrown instance where the driver can't
* read,write,drain,flush,... the buffers
*/
class SickIOException : public SickException {
public:
/**
* \brief A constructor
*/
SickIOException() :
SickException("ERROR: I/O exception!") { }
/**
* \brief Another constructor
* \param detailed_str A more detailed description
*/
SickIOException( const std::string detailed_str ) :
SickException("ERROR: I/O exception -",detailed_str) { }
/**
* \brief A destructor
*/
~SickIOException() throw() { }
};
/**
* \class SickBadChecksumException
* \brief Thrown when a received message has an
* invalid checksum
*/
class SickBadChecksumException : public SickException {
public:
/**
* \brief A constructor
*/
SickBadChecksumException() :
SickException("ERROR: Bad Checksum!") { }
/**
* \brief Another constructor
* \param detailed_str A more detailed description
*/
SickBadChecksumException( const std::string detailed_str ) :
SickException("ERROR: Bad Checksum -",detailed_str) { }
/**
* \brief A destructor
*/
~SickBadChecksumException() throw() { }
};
/**
* \class SickThreadException
* \brief Thrown when error occurs during thread
* initialization, and uninitialization
*/
class SickThreadException : public SickException {
public:
/**
* \brief A constructor
*/
SickThreadException() :
SickException("ERROR: Sick thread exception!") { }
/**
* \brief Another constructor
* \param detailed_str A more detailed description
*/
SickThreadException( const std::string detailed_str ) :
SickException("ERROR: Sick thread exception -",detailed_str) { }
/**
* \brief A destructor
*/
~SickThreadException() throw() { }
};
/**
* \class SickConfigException
* \brief Thrown when the driver detects (or the Sick reports)
* an invalid config
*/
class SickConfigException : public SickException {
public:
/**
* \brief A constructor
*/
SickConfigException() :
SickException("ERROR: Config exception!") { }
/**
* \brief Another constructor
* \param detailed_str A more detailed description
*/
SickConfigException( const std::string detailed_str ) :
SickException("ERROR: Config exception -",detailed_str) { }
/**
* \brief A destructor
*/
~SickConfigException() throw() { }
};
/**
* \class SickErrorException
* \brief Thrown when Sick returns an error code
* or an unexpected response.
*/
class SickErrorException : public SickException {
public:
/**
* \brief A constructor
*/
SickErrorException() :
SickException("ERROR: Sick returned error code!") { };
/**
* \brief Another constructor
* \param detailed_str A more detailed description
*/
SickErrorException( const std::string detailed_str ) :
SickException("ERROR: Sick error -", detailed_str) { }
/**
* \brief A destructor
*/
~SickErrorException() throw() { }
};
} /* namespace SickToolbox */
#endif /* SICK_EXCEPTION */

View File

@ -0,0 +1,805 @@
/*!
* \file SickLD.hh
* \brief Defines the SickLD class for working with the
* Sick LD-OEM/LD-LRS long range LIDARs.
*
* Code by Jason C. Derenick and Thomas H. Miller.
* Contact derenick(at)lehigh(dot)edu
*
* The Sick LIDAR Matlab/C++ Toolbox
* Copyright (c) 2008, Jason C. Derenick and Thomas H. Miller
* All rights reserved.
*
* This software is released under a BSD Open-Source License.
* See http://sicktoolbox.sourceforge.net
*/
#ifndef SICK_LD_HH
#define SICK_LD_HH
/* Macros */
#define DEFAULT_SICK_IP_ADDRESS "192.168.1.10" ///< Default Sick LD INet 4 address
#define DEFAULT_SICK_TCP_PORT (49152) ///< Default TCP port
#define DEFAULT_SICK_MESSAGE_TIMEOUT (unsigned int)(5e6) ///< The max time to wait for a message reply (usecs)
#define DEFAULT_SICK_CONNECT_TIMEOUT (unsigned int)(1e6) ///< The max time to wait before considering a connection attempt as failed (usecs)
#define DEFAULT_SICK_NUM_SCAN_PROFILES (0) ///< Setting this value to 0 will tell the Sick LD to stream measurements when measurement data is requested (NOTE: A profile is a single scans worth of range measurements)
#define DEFAULT_SICK_SIGNAL_SET (0) ///< Default Sick signal configuration
/**
* \def SWAP_VALUES(x,y,t)
* \brief A simple macro for swapping two values.
*/
#define SWAP_VALUES(x,y,t) (t=x,x=y,y=t);
/* Definition dependencies */
#include <string>
#include <vector>
#include <pthread.h>
#include <arpa/inet.h>
#include "SickLIDAR.hh"
#include "SickLDBufferMonitor.hh"
#include "SickLDMessage.hh"
#include "SickException.hh"
/**
* \namespace SickToolbox
* \brief Encapsulates the Sick LIDAR Matlab/C++ toolbox
*/
namespace SickToolbox {
/**
* \class SickLD
* \brief Provides a simple driver interface for working with the
* Sick LD-OEM/Sick LD-LRS long-range models via Ethernet.
*/
class SickLD : public SickLIDAR< SickLDBufferMonitor, SickLDMessage > {
public:
/* Some constants for the developer/end-user */
static const uint16_t SICK_MAX_NUM_MEASUREMENTS = 2881; ///< Maximum number of measurements per sector
static const uint16_t SICK_MAX_NUM_SECTORS = 8; ///< Maximum number of scan sectors (NOTE: This value must be even)
static const uint16_t SICK_MAX_NUM_MEASURING_SECTORS = 4; ///< Maximum number of active/measuring scan sectors
static const uint16_t SICK_MAX_SCAN_AREA = 360; ///< Maximum area that can be covered in a single scan (deg)
static const uint16_t SICK_MIN_MOTOR_SPEED = 5; ///< Minimum motor speed in Hz
static const uint16_t SICK_MAX_MOTOR_SPEED = 20; ///< Maximum motor speed in Hz
static const uint16_t SICK_MIN_VALID_SENSOR_ID = 1; ///< The lowest value the Sick will accept as a Sensor ID
static const uint16_t SICK_MAX_VALID_SENSOR_ID = 254; ///< The largest value the Sick will accept as a Sensor ID
static const uint16_t SICK_MAX_MEAN_PULSE_FREQUENCY = 10800; ///< Max mean pulse frequence of the current device configuration (in Hz) (see page 22 of the operator's manual)
static const uint16_t SICK_MAX_PULSE_FREQUENCY = 14400; ///< Max pulse frequency of the device (in Hz) (see page 22 of the operator's manual)
static const uint16_t SICK_NUM_TICKS_PER_MOTOR_REV = 5760; ///< Odometer ticks per revolution of the Sick LD scan head
static constexpr double SICK_MAX_SCAN_ANGULAR_RESOLUTION = 0.125; ///< Minimum valid separation between laser pulses in active scan ares (deg)
static constexpr double SICK_DEGREES_PER_MOTOR_STEP = 0.0625; ///< Each odometer tick is equivalent to rotating the scan head this many degrees
/* Sick LD sensor modes of operation */
static const uint8_t SICK_SENSOR_MODE_IDLE = 0x01; ///< The Sick LD is powered but idle
static const uint8_t SICK_SENSOR_MODE_ROTATE = 0x02; ///< The Sick LD prism is rotating, but laser is off
static const uint8_t SICK_SENSOR_MODE_MEASURE = 0x03; ///< The Sick LD prism is rotating, and the laser is on
static const uint8_t SICK_SENSOR_MODE_ERROR = 0x04; ///< The Sick LD is in error mode
static const uint8_t SICK_SENSOR_MODE_UNKNOWN = 0xFF; ///< The Sick LD is in an unknown state
/* Sick LD motor modes */
static const uint8_t SICK_MOTOR_MODE_OK = 0x00; ///< Motor is functioning properly
static const uint8_t SICK_MOTOR_MODE_SPIN_TOO_HIGH = 0x09; ///< Motor spin too low (i.e. rotational velocity too low)
static const uint8_t SICK_MOTOR_MODE_SPIN_TOO_LOW = 0x04; ///< Motor spin too high (i.e. rotational velocity too fast)
static const uint8_t SICK_MOTOR_MODE_ERROR = 0x0B; ///< Motor stops or coder error
static const uint8_t SICK_MOTOR_MODE_UNKNOWN = 0xFF; ///< Motor is in an unknown state
/* Sick LD service codes */
static const uint8_t SICK_STAT_SERV_CODE = 0x01; ///< Status service code
static const uint8_t SICK_CONF_SERV_CODE = 0x02; ///< Configuration service code
static const uint8_t SICK_MEAS_SERV_CODE = 0x03; ///< Measurement service code
static const uint8_t SICK_WORK_SERV_CODE = 0x04; ///< Working service code
static const uint8_t SICK_ROUT_SERV_CODE = 0x06; ///< Routing service code
static const uint8_t SICK_FILE_SERV_CODE = 0x07; ///< File service code
static const uint8_t SICK_MONR_SERV_CODE = 0x08; ///< Monitor service code
/* Sick LD status services (service code 0x01) */
static const uint8_t SICK_STAT_SERV_GET_ID = 0x01; ///< Request the Sick LD ID
static const uint8_t SICK_STAT_SERV_GET_STATUS = 0x02; ///< Request status information
static const uint8_t SICK_STAT_SERV_GET_SIGNAL = 0x04; ///< Reads the value of the switch and LED port
static const uint8_t SICK_STAT_SERV_SET_SIGNAL = 0x05; ///< Sets the switches and LEDs
static const uint8_t SICK_STAT_SERV_LD_REGISTER_APPLICATION = 0x06; ///< Registers the ID data for the application firmware
/* Sick LD status service GET_IDENTIFICATION request codes */
static const uint8_t SICK_STAT_SERV_GET_ID_SENSOR_PART_NUM = 0x00; ///< Request the sensor's part number
static const uint8_t SICK_STAT_SERV_GET_ID_SENSOR_NAME = 0x01; ///< Request the sensor's name
static const uint8_t SICK_STAT_SERV_GET_ID_SENSOR_VERSION = 0x02; ///< Request the sensor's version
static const uint8_t SICK_STAT_SERV_GET_ID_SENSOR_SERIAL_NUM = 0x03; ///< Request the sensor's serial number
static const uint8_t SICK_STAT_SERV_GET_ID_SENSOR_EDM_SERIAL_NUM = 0x04; ///< Request the edm??? serial number
static const uint8_t SICK_STAT_SERV_GET_ID_FIRMWARE_PART_NUM = 0x10; ///< Requess the firmware's part number
static const uint8_t SICK_STAT_SERV_GET_ID_FIRMWARE_NAME = 0x11; ///< Request the firmware's name
static const uint8_t SICK_STAT_SERV_GET_ID_FIRMWARE_VERSION = 0x12; ///< Request the firmware's version
static const uint8_t SICK_STAT_SERV_GET_ID_APP_PART_NUM = 0x20; ///< Request the application part number
static const uint8_t SICK_STAT_SERV_GET_ID_APP_NAME = 0x21; ///< Request the application name
static const uint8_t SICK_STAT_SERV_GET_ID_APP_VERSION = 0x22; ///< Request the application version
/* Sick LD configuration services (service code 0x02) */
static const uint8_t SICK_CONF_SERV_SET_CONFIGURATION = 0x01; ///< Set the Sick LD configuration
static const uint8_t SICK_CONF_SERV_GET_CONFIGURATION = 0x02; ///< Read the Sick LD configuration information
static const uint8_t SICK_CONF_SERV_SET_TIME_ABSOLUTE = 0x03; ///< Set the internal clock to a timestamp value
static const uint8_t SICK_CONF_SERV_SET_TIME_RELATIVE = 0x04; ///< Correct the internal clock by some value
static const uint8_t SICK_CONF_SERV_GET_SYNC_CLOCK = 0x05; ///< Read the internal time of the LD-OEM/LD-LRS
static const uint8_t SICK_CONF_SERV_SET_FILTER = 0x09; ///< Set the filter configuration
static const uint8_t SICK_CONF_SERV_SET_FUNCTION = 0x0A; ///< Assigns a measurement function to an angle range
static const uint8_t SICK_CONF_SERV_GET_FUNCTION = 0x0B; ///< Returns the configuration of the given sector
/* Sick LD configuration filter codes */
static const uint8_t SICK_CONF_SERV_SET_FILTER_NEARFIELD = 0x01; ///< Code for identifying filter type: nearfield suppression
/* Sick LD nearfield suppression configuration codes */
static const uint8_t SICK_CONF_SERV_SET_FILTER_NEARFIELD_OFF = 0x00; ///< Used to set nearfield suppression off
static const uint8_t SICK_CONF_SERV_SET_FILTER_NEARFIELD_ON = 0x01; ///< Used to set nearfield suppression on
/* Sick LD measurement services (service code 0x03) */
static const uint8_t SICK_MEAS_SERV_GET_PROFILE = 0x01; ///< Requests n profiles of a defined format
static const uint8_t SICK_MEAS_SERV_CANCEL_PROFILE = 0x02; ///< Stops profile output
/* Sick LD working services (service code 0x04) */
static const uint8_t SICK_WORK_SERV_RESET = 0x01; ///< Sick LD enters a reset sequence
static const uint8_t SICK_WORK_SERV_TRANS_IDLE = 0x02; ///< Sick LD enters IDLE mode (motor stops and laser is turned off)
static const uint8_t SICK_WORK_SERV_TRANS_ROTATE = 0x03; ///< Sick LD enters ROTATE mode (motor starts and rotates with a specified speed in Hz, laser is off)
static const uint8_t SICK_WORK_SERV_TRANS_MEASURE = 0x04; ///< Sick LD enters MEASURE mode (laser starts with next revolution)
/* Sick LD working service DO_RESET request codes */
static const uint8_t SICK_WORK_SERV_RESET_INIT_CPU = 0x00; ///< Sick LD does a complete reset (Reinitializes the CPU)
static const uint8_t SICK_WORK_SERV_RESET_KEEP_CPU = 0x01; ///< Sick LD does a partial reset (CPU is not reinitialized)
static const uint8_t SICK_WORK_SERV_RESET_HALT_APP = 0x02; ///< Sick LD does a minimal reset (Application is halted and device enters IDLE state)
/* Sick LD working service TRANS_MEASURE return codes */
static const uint8_t SICK_WORK_SERV_TRANS_MEASURE_RET_OK = 0x00; ///< Sick LD is ready to stream/obtain scan profiles
static const uint8_t SICK_WORK_SERV_TRANS_MEASURE_RET_ERR_MAX_PULSE = 0x01; ///< Sick LD reports config yields a max laser pulse frequency that is too high
static const uint8_t SICK_WORK_SERV_TRANS_MEASURE_RET_ERR_MEAN_PULSE = 0x02; ///< Sick LD reports config yields a max mean pulse frequency that is too high
static const uint8_t SICK_WORK_SERV_TRANS_MEASURE_RET_ERR_SECT_BORDER = 0x03; ///< Sick LD reports sector borders are not configured correctly
static const uint8_t SICK_WORK_SERV_TRANS_MEASURE_RET_ERR_SECT_BORDER_MULT = 0x04; ///< Sick LD reports sector borders are not a multiple of the step angle
/* Sick LD interface routing services (service code 0x06) */
static const uint8_t SICK_ROUT_SERV_COM_ATTACH = 0x01; ///< Attach a master (host) communications interface
static const uint8_t SICK_ROUT_SERV_COM_DETACH = 0x02; ///< Detach a master (host) communications interface
static const uint8_t SICK_ROUT_SERV_COM_INITIALIZE = 0x03; ///< Initialize the interface (Note: using this may not be necessary for some interfaces, e.g. Ethernet)
static const uint8_t SICK_ROUT_SERV_COM_OUTPUT = 0x04; ///< Output data to the interface
static const uint8_t SICK_ROUT_SERV_COM_DATA = 0x05; ///< Forward data received on specified interface to master interface
/* Sick LD file services (service code 0x07) */
static const uint8_t SICK_FILE_SERV_DIR = 0x01; ///< List the stored files in flash memory
static const uint8_t SICK_FILE_SERV_SAVE = 0x02; ///< Saves the data into flash memory
static const uint8_t SICK_FILE_SERV_LOAD = 0x03; ///< Recalls a file from the flash
static const uint8_t SICK_FILE_SERV_DELETE = 0x04; ///< Deletes a file from the flash
/* Sick LD monitor services (service code 0x08) */
static const uint8_t SICK_MONR_SERV_MONITOR_RUN = 0x01; ///< Enable/disable monitor services
static const uint8_t SICK_MONR_SERV_MONITOR_PROFILE_LOG = 0x02; ///< Enable/disable profile logging
/* Sick LD configuration keys */
static const uint8_t SICK_CONF_KEY_RS232_RS422 = 0x01; ///< Key for configuring RS-232/RS-422
static const uint8_t SICK_CONF_KEY_CAN = 0x02; ///< Key for configuring CAN
static const uint8_t SICK_CONF_KEY_ETHERNET = 0x05; ///< Key for configuring Ethernet
static const uint8_t SICK_CONF_KEY_GLOBAL = 0x10; ///< Key for global configuration
/* Sick LD sector configuration codes */
static const uint8_t SICK_CONF_SECTOR_NOT_INITIALIZED = 0x00; ///< Sector is uninitialized
static const uint8_t SICK_CONF_SECTOR_NO_MEASUREMENT = 0x01; ///< Sector has no measurements
static const uint8_t SICK_CONF_SECTOR_RESERVED = 0x02; ///< Sector is reserved by Sick LD
static const uint8_t SICK_CONF_SECTOR_NORMAL_MEASUREMENT = 0x03; ///< Sector is returning measurements
static const uint8_t SICK_CONF_SECTOR_REFERENCE_MEASUREMENT = 0x04; ///< Sector can be used as reference measurement
/* Sick LD profile formats */
static const uint16_t SICK_SCAN_PROFILE_RANGE = 0x39FF; ///< Request sector scan data w/o any echo data
/*
* SICK_SCAN_PROFILE_RANGE format (0x39FF) interpretation:
* (See page 32 of telegram listing for fieldname definitions)
*
* Field Name | Send
* --------------------
* PROFILESENT | YES
* PROFILECOUNT | YES
* LAYERNUM | YES
* SECTORNUM | YES
* DIRSTEP | YES
* POINTNUM | YES
* TSTART | YES
* STARTDIR | YES
* DISTANCE-n | YES
* DIRECTION-n | NO
* ECHO-n | NO
* TEND | YES
* ENDDIR | YES
* SENSTAT | YES
*/
/* Sick LD profile formats */
static const uint16_t SICK_SCAN_PROFILE_RANGE_AND_ECHO = 0x3DFF; ///< Request sector scan data w/ echo data
/*
* SICK_SCAN_PROFILE_RANGE format (0x3DFF) interpretation:
* (See page 32 of telegram listing for fieldname definitions)
*
* Field Name | Send
* --------------------
* PROFILESENT | YES
* PROFILECOUNT | YES
* LAYERNUM | YES
* SECTORNUM | YES
* DIRSTEP | YES
* POINTNUM | YES
* TSTART | YES
* STARTDIR | YES
* DISTANCE-n | YES
* DIRECTION-n | NO
* ECHO-n | YES
* TEND | YES
* ENDDIR | YES
* SENSTAT | YES
*/
/* Masks for working with the Sick LD signals
*
* NOTE: Although the Sick LD manual defines the flag
* values for red and green LEDs the operation
* of these LEDs are reserved. So they can't
* be set by the device driver.
*/
static const uint8_t SICK_SIGNAL_LED_YELLOW_A = 0x01; ///< Mask for first yellow LED
static const uint8_t SICK_SIGNAL_LED_YELLOW_B = 0x02; ///< Mask for second yellow LED
static const uint8_t SICK_SIGNAL_LED_GREEN = 0x04; ///< Mask for green LED
static const uint8_t SICK_SIGNAL_LED_RED = 0x08; ///< Mask for red LED
static const uint8_t SICK_SIGNAL_SWITCH_0 = 0x10; ///< Mask for signal switch 0
static const uint8_t SICK_SIGNAL_SWITCH_1 = 0x20; ///< Mask for signal switch 1
static const uint8_t SICK_SIGNAL_SWITCH_2 = 0x40; ///< Mask for signal switch 2
static const uint8_t SICK_SIGNAL_SWITCH_3 = 0x80; ///< Mask for signal switch 3
/**
* \struct sick_ld_config_global_tag
* \brief A structure to aggregate the data used to configure the
* Sick LD global parameter values.
*/
/**
* \typedef sick_ld_config_global_t
* \brief Adopt c-style convention
*/
typedef struct sick_ld_config_global_tag {
uint16_t sick_sensor_id; ///< The single word sensor ID for the Sick unit
uint16_t sick_motor_speed; ///< Nominal motor speed value: 0x0005 to 0x0014 (5 to 20)
double sick_angle_step; ///< Difference between two laser pulse positions in 1/16th deg. (NOTE: this value must be a divisor of 5760 and be greater than 1)
} sick_ld_config_global_t;
/**
* \struct sick_ld_config_ethernet_tag
* \brief A structure to aggregate the data used to configure
* the Sick LD unit for Ethernet.
*
* \todo Eventually add similar config structures for the other protocols.
*/
/**
* \typedef sick_ld_config_ethernet_t
* \brief Adopt c-style convention
*/
typedef struct sick_ld_config_ethernet_tag {
uint16_t sick_ip_address[4]; ///< IP address in numerical form w/ leftmost part at sick_ip_address[0]
uint16_t sick_subnet_mask[4]; ///< Subnet mask for the network to which the Sick LD is assigned
uint16_t sick_gateway_ip_address[4]; ///< The address of the local gateway
uint16_t sick_node_id; ///< Single word address of the Sick LD
uint16_t sick_transparent_tcp_port; ///< The TCP/IP transparent port associated with the Sick LD
} sick_ld_config_ethernet_t;
/**
* \struct sick_ld_config_sector_tag
* \brief A structure to aggregate data used to define the
* Sick LD's sector configuration.
*/
/**
* \typedef sick_ld_config_sector_t
* \brief Adopt c-style convention
*/
typedef struct sick_ld_config_sector_tag {
uint8_t sick_num_active_sectors; ///< Number of active sectors (sectors that are actually being scanned)
uint8_t sick_num_initialized_sectors; ///< Number of sectors configured w/ a function other than "not initialized"
uint8_t sick_active_sector_ids[SICK_MAX_NUM_SECTORS]; ///< IDs of all active sectors
uint8_t sick_sector_functions[SICK_MAX_NUM_SECTORS]; ///< Function values associated w/ each of the Sick LD's sectors
double sick_sector_start_angles[SICK_MAX_NUM_SECTORS]; ///< Start angles for each initialized sector (deg)
double sick_sector_stop_angles[SICK_MAX_NUM_SECTORS]; ///< Stop angles for each sector (deg)
} sick_ld_config_sector_t;
/**
* \struct sick_ld_identity_tag
* \brief A structure to aggregate the fields that collectively
* define the identity of a Sick LD unit.
*/
/**
* \typedef sick_ld_identity_t
* \brief Adopt c-style convention
*/
typedef struct sick_ld_identity_tag {
std::string sick_part_number; ///< The Sick LD's part number
std::string sick_name; ///< The name assigned to the Sick
std::string sick_version; ///< The Sick LD's version number
std::string sick_serial_number; ///< The Sick LD's serial number
std::string sick_edm_serial_number; ///< The Sick LD's edm??? serial number
std::string sick_firmware_part_number; ///< The Sick LD's firmware part number
std::string sick_firmware_name; ///< The Sick LD's firmware name
std::string sick_firmware_version; ///< The Sick LD's firmware version
std::string sick_application_software_part_number; ///< The Sick LD's app. software part number
std::string sick_application_software_name; ///< The Sick LD's app. software name
std::string sick_application_software_version; ///< The Sick LD's app. software version
} sick_ld_identity_t;
/**
* \struct sick_ld_sector_data_tag
* \brief A structure to aggregate the fields that collectively
* define a sector in the scan area of the Sick LD unit.
*/
/**
* \typedef sick_ld_sector_data_t
* \brief Adopt c-style convention
*/
typedef struct sick_ld_sector_data_tag {
unsigned int sector_num; ///< The sector number in the scan area
unsigned int num_data_points; ///< The number of data points in the scan area
unsigned int timestamp_start; ///< The timestamp (in ms) corresponding to the time the first measurement in the sector was taken
unsigned int timestamp_stop; ///< The timestamp (in ms) corresponding to the time the last measurement in the sector was taken
unsigned int echo_values[SICK_MAX_NUM_MEASUREMENTS]; ///< The corresponding echo/reflectivity values
double angle_step; ///< The angle step used for the given sector (this should be the same for all sectors)
double angle_start; ///< The angle at which the first measurement in the sector was acquired
double angle_stop; ///< The angle at which the last measurement in the sector was acquired
double range_values[SICK_MAX_NUM_MEASUREMENTS]; ///< The corresponding range values (NOTE: The size of this array is intended to be large enough to accomodate various sector configs.)
double scan_angles[SICK_MAX_NUM_MEASUREMENTS]; ///< The scan angles corresponding to the respective measurements
} sick_ld_sector_data_t;
/**
* \struct sick_ld_scan_profile_tag
* \brief A structure to aggregate the fields that collectively
* define the profile of a single scan acquired from the
* Sick LD unit.
*/
/**
* \typedef sick_ld_scan_profile_t
* \brief Adopt c-style convention
*/
typedef struct sick_ld_scan_profile_tag {
unsigned int profile_number; ///< The number of profiles sent to the host (i.e. the current profile number)
unsigned int profile_counter; ///< The number of profiles gathered by the Sick LD
unsigned int layer_num; ///< The layer number associated with a scan (this will always be 0)
unsigned int sensor_status; ///< The status of the Sick LD sensor
unsigned int motor_status; ///< The status of the Sick LD motor
unsigned int num_sectors; ///< The number of sectors returned in the profile
sick_ld_sector_data_t sector_data[SICK_MAX_NUM_SECTORS]; ///< The sectors associated with the scan profile
} sick_ld_scan_profile_t;
/** Primary constructor */
SickLD( const std::string sick_ip_address = DEFAULT_SICK_IP_ADDRESS,
const uint16_t sick_tcp_port = DEFAULT_SICK_TCP_PORT );
/** Initializes the Sick LD unit (use scan areas defined in flash) */
void Initialize( ) throw( SickIOException, SickThreadException, SickTimeoutException, SickErrorException );
/** Gets the sensor and motor mode of the unit */
void GetSickStatus( unsigned int &sick_sensor_mode, unsigned int &sick_motor_mode )
throw( SickIOException, SickTimeoutException );
/** Sets the temporal scan configuration (until power is cycled) */
void SetSickTempScanAreas( const double * active_sector_start_angles, const double * const active_sector_stop_angles,
const unsigned int num_active_sectors )
throw( SickTimeoutException, SickIOException, SickConfigException );
/** Sets the internal clock of the Sick LD unit */
void SetSickTimeAbsolute( const uint16_t absolute_clock_time, uint16_t &new_sick_clock_time )
throw( SickErrorException, SickTimeoutException, SickIOException, SickConfigException );
/** Sets the internal clock of the Sick LD using the relative given time value */
void SetSickTimeRelative( const int16_t time_delta, uint16_t &new_sick_clock_time )
throw( SickErrorException, SickTimeoutException, SickIOException, SickConfigException );
/** Gets the internal clock time of the Sick LD unit */
void GetSickTime( uint16_t &sick_time )
throw( SickIOException, SickTimeoutException, SickErrorException );
/** Sets the signal LEDs and switches */
void SetSickSignals( const uint8_t sick_signal_flags = DEFAULT_SICK_SIGNAL_SET )
throw( SickIOException, SickTimeoutException, SickErrorException );
/** Query the Sick for its current signal settings */
void GetSickSignals( uint8_t &sick_signal_flags ) throw( SickIOException, SickTimeoutException );
/** Enables nearfield suppressive filtering (in flash) */
void EnableNearfieldSuppression( ) throw( SickErrorException, SickTimeoutException, SickIOException );
/** Disables nearfield suppressive filtering (in flash) */
void DisableNearfieldSuppression( ) throw( SickErrorException, SickTimeoutException, SickIOException );
/** Acquires measurements and related data for all active sectors */
void GetSickMeasurements( double * const range_measurements,
unsigned int * const echo_measurements = NULL,
unsigned int * const num_measurements = NULL,
unsigned int * const sector_ids = NULL,
unsigned int * const sector_data_offsets = NULL,
double * const sector_step_angles = NULL,
double * const sector_start_angles = NULL,
double * const sector_stop_angles = NULL,
unsigned int * const sector_start_timestamps = NULL,
unsigned int * const sector_stop_timestamps = NULL )
throw( SickErrorException, SickIOException, SickTimeoutException, SickConfigException );
/** Attempts to set a new senor ID for the device (in flash) */
void SetSickSensorID( const unsigned int sick_sensor_id )
throw( SickErrorException, SickTimeoutException, SickIOException );
/** Attempts to set a new motor speed for the device (in flash) */
void SetSickMotorSpeed( const unsigned int sick_motor_speed )
throw( SickErrorException, SickTimeoutException, SickIOException );
/** Attempts to set a new scan resolution for the device (in flash) */
void SetSickScanResolution( const double sick_step_angle )
throw( SickTimeoutException, SickIOException, SickConfigException );
/** Attempts to set the global params and the active scan sectors for the device (in flash) */
void SetSickGlobalParamsAndScanAreas( const unsigned int sick_motor_speed,
const double sick_step_angle,
const double * const active_sector_start_angles,
const double * const active_sector_stop_angles,
const unsigned int num_active_sectors )
throw( SickTimeoutException, SickIOException, SickConfigException, SickErrorException );
/** Attempts to set the active scan sectors for the device (in flash) */
void SetSickScanAreas( const double * const active_sector_start_angles,
const double * const active_sector_stop_angles,
const unsigned int num_active_sectors )
throw( SickTimeoutException, SickIOException, SickConfigException, SickErrorException );
/** Resets the Sick LD using the given reset level */
void ResetSick( const unsigned int reset_level = SICK_WORK_SERV_RESET_INIT_CPU )
throw( SickErrorException, SickTimeoutException, SickIOException, SickConfigException );
/** Returns the number of active/measuring sectors */
unsigned int GetSickNumActiveSectors( ) const;
/** Acquire the Sick LD's sensor ID */
unsigned int GetSickSensorID( ) const;
/** Acquire the Sick LD's current motor speed in Hz */
unsigned int GetSickMotorSpeed( ) const;
/** Acquire the Sick LD's current scan resolution */
double GetSickScanResolution( ) const;
/** Acquire the current IP address of the Sick */
std::string GetSickIPAddress( ) const;
/** Acquire the subnet mask for the Sick */
std::string GetSickSubnetMask( ) const;
/** Acquire the IP address of the Sick gateway */
std::string GetSickGatewayIPAddress( ) const;
/** Acquire the Sick LD's part number */
std::string GetSickPartNumber( ) const;
/** Acquire the Sick LD's name */
std::string GetSickName( ) const;
/** Acquire the Sick LD's version number */
std::string GetSickVersion( ) const;
/** Acquire the Sick LD's serial number */
std::string GetSickSerialNumber( ) const;
/** Acquire the Sick LD's EDM serial number */
std::string GetSickEDMSerialNumber( ) const;
/** Acquire the Sick LD's firmware part number */
std::string GetSickFirmwarePartNumber( ) const;
/** Acquire the Sick LD's firmware number */
std::string GetSickFirmwareName( ) const;
/** Acquire the Sick LD's firmware version */
std::string GetSickFirmwareVersion( ) const;
/** Acquire the Sick LD's application software part number */
std::string GetSickAppSoftwarePartNumber( ) const;
/** Acquire the Sick LD's application software name */
std::string GetSickAppSoftwareName( ) const;
/** Acquire the Sick LD's application software version number */
std::string GetSickAppSoftwareVersionNumber( ) const;
/** Acquire the Sick LD's status as a printable string */
std::string GetSickStatusAsString() const;
/** Acquire the Sick LD's identity as a printable string */
std::string GetSickIdentityAsString() const;
/** Acquire the Sick LD's global config as a printable string */
std::string GetSickGlobalConfigAsString() const;
/** Acquire the Sick LD's Ethernet config as a printable string */
std::string GetSickEthernetConfigAsString() const;
/** Acquire the Sick LD's sector config as a printable string */
std::string GetSickSectorConfigAsString() const;
/** Acquire the total scan area (in degrees) being scanned by the Sick LD */
double GetSickScanArea( ) const;
/** Prints the Sick LD's status information */
void PrintSickStatus( ) const;
/** Prints the Sick LD's identity information */
void PrintSickIdentity( ) const;
/** Prints the global configuration parameter values */
void PrintSickGlobalConfig( ) const;
/** Prints the Ethernet configuration parameter values */
void PrintSickEthernetConfig( ) const;
/** Prints the Sick Sector configuration */
void PrintSickSectorConfig( ) const;
/** Uninitializes the Sick LD unit */
void Uninitialize( ) throw( SickIOException, SickTimeoutException, SickErrorException, SickThreadException );
/** Destructor */
~SickLD();
private:
/** The Sick LD IP address */
std::string _sick_ip_address;
/** The Sick LD TCP port number */
uint16_t _sick_tcp_port;
/** Sick LD socket structure */
unsigned int _socket;
/** Sick LD socket address structure */
struct sockaddr_in _sick_inet_address_info;
/** The current sensor mode */
uint8_t _sick_sensor_mode;
/** The mode of the motor */
uint8_t _sick_motor_mode;
/** Indicates whether the Sick LD is currently streaming range data */
bool _sick_streaming_range_data;
/** Indicates whether the Sick LD is currently streaming range and echo data */
bool _sick_streaming_range_and_echo_data;
/** The identity structure for the Sick */
sick_ld_identity_t _sick_identity;
/** The current global configuration for the unit */
sick_ld_config_global_t _sick_global_config;
/** The current Ethernet configuration for the unit */
sick_ld_config_ethernet_t _sick_ethernet_config;
/** The current sector configuration for the unit */
sick_ld_config_sector_t _sick_sector_config;
/** Setup the connection parameters and establish TCP connection! */
void _setupConnection( ) throw( SickIOException, SickTimeoutException );
/** Synchronizes the driver state with the Sick LD (used for initialization) */
void _syncDriverWithSick( ) throw( SickIOException, SickTimeoutException, SickErrorException );
/** Set the function for a particular scan secto */
void _setSickSectorFunction( const uint8_t sector_number, const uint8_t sector_function,
const double sector_angle_stop, const bool write_to_flash = false )
throw( SickErrorException, SickTimeoutException, SickIOException, SickConfigException );
/** Acquires the given Sector's function (i.e. current config) */
void _getSickSectorFunction( const uint8_t sector_num, uint8_t &sector_function, double &sector_stop_angle )
throw( SickErrorException, SickTimeoutException, SickIOException );
/** Sets the Sick LD to IDLE mode */
void _setSickSensorModeToIdle( ) throw( SickErrorException, SickTimeoutException, SickIOException );
/** Sets the Sick LD to ROTATE mode */
void _setSickSensorModeToRotate( ) throw( SickErrorException, SickTimeoutException, SickIOException );
/** Sets the Sick LD to MEASURE mode */
void _setSickSensorModeToMeasure( ) throw( SickErrorException, SickTimeoutException, SickIOException );
/** Sets the Sick LD's sensor mode to IDLE (laser off, motor off) */
void _setSickSensorMode( const uint8_t new_sick_sensor_mode )
throw( SickErrorException, SickTimeoutException, SickIOException );
/** Requests n range measurement profiles from the Sick LD */
void _getSickScanProfiles( const uint16_t profile_format, const uint16_t num_profiles = DEFAULT_SICK_NUM_SCAN_PROFILES )
throw( SickErrorException, SickTimeoutException, SickIOException, SickConfigException );
/** Parses a sequence of bytes and populates the profile_data struct w/ the results */
void _parseScanProfile( uint8_t * const src_buffer, sick_ld_scan_profile_t &profile_data ) const;
/** Cancels the active data stream */
void _cancelSickScanProfiles( ) throw( SickErrorException, SickTimeoutException, SickIOException );
/** Turns nearfield suppression on/off */
void _setSickFilter( const uint8_t suppress_code )
throw( SickErrorException, SickTimeoutException, SickIOException );
/** Stores an image of the Sick LD's identity locally */
void _getSickIdentity( ) throw( SickTimeoutException, SickIOException );
/** Query the Sick for its sensor and motor status */
void _getSickStatus( ) throw( SickTimeoutException, SickIOException );
/** Sets the Sick LD's global configuration (in flash) */
void _setSickGlobalConfig( const uint8_t sick_sensor_id, const uint8_t sick_motor_speed, const double sick_angle_step )
throw( SickErrorException, SickTimeoutException, SickIOException );
/** Query the Sick for its global configuration parameters */
void _getSickGlobalConfig( ) throw( SickErrorException, SickTimeoutException, SickIOException );
/** Query the Sick for its Ethernet configuration parameters */
void _getSickEthernetConfig( ) throw( SickErrorException, SickTimeoutException, SickIOException );
/** Acquires the configuration (function and stop angle) for each sector */
void _getSickSectorConfig( ) throw( SickErrorException, SickTimeoutException, SickIOException );
/** Query the Sick for ID information */
void _getIdentificationString( const uint8_t id_request_code, std::string &id_return_string )
throw( SickTimeoutException, SickIOException );
/** Query the Sick for its sensor part number */
void _getSensorPartNumber( ) throw( SickTimeoutException, SickIOException );
/** Query the Sick for its assigned name */
void _getSensorName( ) throw( SickTimeoutException, SickIOException );
/** Query the Sick for its version number */
void _getSensorVersion( ) throw( SickTimeoutException, SickIOException );
/** Query the Sick for its serial number */
void _getSensorSerialNumber( ) throw( SickTimeoutException, SickIOException );
/** Query the Sick for its EDM unit's serial number */
void _getSensorEDMSerialNumber( ) throw( SickTimeoutException, SickIOException );
/** Query the Sick for the part number of its firmware */
void _getFirmwarePartNumber( ) throw( SickTimeoutException, SickIOException );
/** Query the Sick for the name of its firmware */
void _getFirmwareName( ) throw( SickTimeoutException, SickIOException );
/** Query the Sick for the version of the firmware */
void _getFirmwareVersion( ) throw( SickTimeoutException, SickIOException );
/** Query the part number of the application software */
void _getApplicationSoftwarePartNumber( ) throw( SickTimeoutException, SickIOException );
/** Query the Sick for the application name */
void _getApplicationSoftwareName( ) throw( SickTimeoutException, SickIOException );
/** Query the Sick for the application software version */
void _getApplicationSoftwareVersion( ) throw( SickTimeoutException, SickIOException );
/** Allows setting the global parameters and scan area definition (in flash) */
void _setSickGlobalParamsAndScanAreas( const unsigned int sick_motor_speed, const double sick_step_angle,
const double * const active_sector_start_angles,
const double * const active_sector_stop_angles,
const unsigned int num_active_sectors )
throw( SickTimeoutException, SickIOException, SickConfigException, SickErrorException );
/** Allows setting a temporary (until a device reset) sector configuration on the device */
void _setSickTemporaryScanAreas( const double * const active_sector_start_angles,
const double * const active_sector_stop_angles,
const unsigned int num_active_sectors )
throw( SickTimeoutException, SickIOException, SickConfigException );
/** Sets the sick sector configuration */
void _setSickSectorConfig( const unsigned int * const sector_functions, const double * const sector_stop_angles,
const unsigned int num_sectors, const bool write_to_flash = false )
throw( SickErrorException, SickTimeoutException, SickIOException, SickConfigException );
/** Sets the signals for the device */
void _setSickSignals( const uint8_t sick_signal_flags = DEFAULT_SICK_SIGNAL_SET )
throw( SickIOException, SickTimeoutException, SickErrorException );
/** Send a message, get the reply from the Sick LD and check it */
void _sendMessageAndGetReply( const SickLDMessage &send_message, SickLDMessage &recv_message,
const unsigned int timeout_value = DEFAULT_SICK_MESSAGE_TIMEOUT )
throw( SickIOException, SickTimeoutException );
/** Flushed the TCP receive buffer */
void _flushTCPRecvBuffer( ) throw ( SickIOException, SickThreadException );
/** Teardown the connection to the Sick LD */
void _teardownConnection( ) throw( SickIOException );
/** Generates a device-ready sector set given only an active sector spec. */
void _generateSickSectorConfig( const double * const active_sector_start_angles,
const double * const active_sector_stop_angles,
const unsigned int num_active_sectors,
const double sick_step_angle,
unsigned int * const sector_functions,
double * const sector_stop_angles,
unsigned int &num_sectors ) const;
/** Converts odometry ticks to an equivalent angle */
double _ticksToAngle( const uint16_t ticks ) const;
/** Converts angle to an equivalent representation in odometer ticks */
uint16_t _angleToTicks( const double angle ) const;
/** Computes the mean pulse frequency for the given config */
double _computeMeanPulseFrequency( const double active_scan_area, const double curr_motor_speed,
const double curr_angular_resolution ) const;
/** Computes the total pulse frequency for the given config */
double _computeMaxPulseFrequency( const double total_scan_area, const double curr_motor_speed,
const double curr_angular_resolution ) const;
/** Indicates whether a given sensor ID is valid for the device */
bool _validSickSensorID( const unsigned int sick_sensor_id ) const;
/** Indicates whether a given motor speed is valid for the device */
bool _validSickMotorSpeed( const unsigned int sick_motor_speed ) const;
/** Indicates whether a given motor speed is valid for the device */
bool _validSickScanResolution( const double sick_step_angle, const double * const active_sector_start_angles,
const double * const active_sector_stop_angles, const unsigned int num_active_sectors ) const;
/** Indicates whether the given configuration yields a valid max and mean pulse frequency */
bool _validPulseFrequency( const unsigned int sick_motor_speed, const double sick_step_angle ) const;
/** Indicates whether the given configuration yields a valid max and mean pulse frequency */
bool _validPulseFrequency( const unsigned int sick_motor_speed, const double sick_step_angle,
const double * const active_sector_start_angles,
const double * const active_sector_stop_angles,
const unsigned int num_active_sectors ) const;
/** Returns the scanning area for the device given the current sector configuration */
double _computeScanArea( const double sick_step_angle, const double * const sector_start_angles,
const double * const sector_stop_angles, const unsigned int num_sectors ) const;
/** Reorders given sector angle sets */
void _sortScanAreas( double * const sector_start_angles, double * const sector_stop_angles,
const unsigned int num_sectors ) const;
/** Checks the given sector arguments for overlapping regions yielding an invalid configuration */
bool _validActiveSectors( const double * const sector_start_angles, const double * const sector_stop_angles,
const unsigned int num_active_sectors ) const;
/** Indicates whether the supplied profile format is currently supported by the driver */
bool _supportedScanProfileFormat( const uint16_t profile_format ) const;
/** Prints data corresponding to a single scan sector (data obtained using GET_PROFILE) */
void _printSectorProfileData( const sick_ld_sector_data_t &sector_data ) const;
/** Prints the data corresponding to the given scan profile (for debugging purposes) */
void _printSickScanProfile( const sick_ld_scan_profile_t profile_data, const bool print_sector_data = true ) const;
/** Returns the corresponding work service subcode required to transition the Sick LD to the given sensor mode. */
uint8_t _sickSensorModeToWorkServiceSubcode( const uint8_t sick_sensor_mode ) const;
/** Converts _sick_sensor_mode to a representative string */
std::string _sickSensorModeToString( const uint8_t sick_sensor_mode ) const;
/** Converts _sick_motor_mode to a representative string */
std::string _sickMotorModeToString( const uint8_t sick_motor_mode ) const;
/** Converts the specified trans measurement mode return value to a string */
std::string _sickTransMeasureReturnToString( const uint8_t return_value ) const;
/** Converts the specified reset level to a representative string */
std::string _sickResetLevelToString( const uint16_t reset_level ) const;
/** Converts Sick LD sector configuration word to a representative string */
std::string _sickSectorFunctionToString( const uint16_t sick_sector_function ) const;
/** Converts a given scan profile format to a string for friendlier output */
std::string _sickProfileFormatToString( const uint16_t profile_format ) const;
/** Prints the initialization footer */
void _printInitFooter( ) const;
};
} //namespace SickToolbox
#endif /* SICK_LD_HH */

View File

@ -0,0 +1,50 @@
/*!
* \file SickLDBufferMonitor.hh
* \brief Defines a class for monitoring the receive
* buffer when interfacing w/ a Sick LMS LIDAR.
*
* Code by Jason C. Derenick and Thomas H. Miller.
* Contact derenick(at)lehigh(dot)edu
*
* The Sick LIDAR Matlab/C++ Toolbox
* Copyright (c) 2008, Jason C. Derenick and Thomas H. Miller
* All rights reserved.
*
* This software is released under a BSD Open-Source License.
* See http://sicktoolbox.sourceforge.net
*/
#ifndef SICK_LD_BUFFER_MONITOR_HH
#define SICK_LD_BUFFER_MONITOR_HH
#define DEFAULT_SICK_BYTE_TIMEOUT (35000) ///< Max allowable time between consecutive bytes
/* Definition dependencies */
#include "SickLDMessage.hh"
#include "SickBufferMonitor.hh"
#include "SickException.hh"
/* Associate the namespace */
namespace SickToolbox {
/*!
* \brief A class for monitoring the receive buffer when interfacing with a Sick LD LIDAR
*/
class SickLDBufferMonitor : public SickBufferMonitor< SickLDBufferMonitor, SickLDMessage > {
public:
/** A standard constructor */
SickLDBufferMonitor( );
/** A method for extracting a single message from the stream */
void GetNextMessageFromDataStream( SickLDMessage &sick_message ) throw( SickIOException );
/** A standard destructor */
~SickLDBufferMonitor( );
};
} /* namespace SickToolbox */
#endif /* SICK_LD_BUFFER_MONITOR_HH */

View File

@ -0,0 +1,80 @@
/*!
* \file SickLDMessage.hh
* \brief Defines the class SickLDMessage.
*
* Code by Jason C. Derenick and Thomas H. Miller.
* Contact derenick(at)lehigh(dot)edu
*
* The Sick LIDAR Matlab/C++ Toolbox
* Copyright (c) 2008, Jason C. Derenick and Thomas H. Miller
* All rights reserved.
*
* This software is released under a BSD Open-Source License.
* See http://sicktoolbox.sourceforge.net
*/
#ifndef SICK_LD_MESSAGE_HH
#define SICK_LD_MESSAGE_HH
/* Definition dependencies */
#include <string.h>
#include <arpa/inet.h>
#include "SickMessage.hh"
#define SICK_LD_MSG_HEADER_LEN (8) ///< Sick LD message header length in bytes
#define SICK_LD_MSG_PAYLOAD_MAX_LEN (5816) ///< Sick LD maximum payload length
#define SICK_LD_MSG_TRAILER_LEN (1) ///< Sick LD length of the message trailer
/* Associate the namespace */
namespace SickToolbox {
/**
* \class SickLDMessage
* \brief A class to represent all messages sent to and from the Sick LD unit.
*/
class SickLDMessage : public SickMessage< SICK_LD_MSG_HEADER_LEN, SICK_LD_MSG_PAYLOAD_MAX_LEN, SICK_LD_MSG_TRAILER_LEN > {
public:
/** A standard constructor */
SickLDMessage( );
/** Constructs a packet by using BuildMessage */
SickLDMessage( const uint8_t * const payload_buffer, const unsigned int payload_length );
/** Constructs a packet using ParseMessage() */
SickLDMessage( const uint8_t * const message_buffer );
/** Construct a well-formed raw packet */
void BuildMessage( const uint8_t * const payload_buffer, const unsigned int payload_length );
/** Populates fields from a (well-formed) raw packet */
void ParseMessage( const uint8_t * const message_buffer );
/** Get the length of the service code associated with the message */
uint8_t GetServiceCode( ) const { return _message_buffer[8]; }
/** Get the service sub-code associated with the message */
uint8_t GetServiceSubcode( ) const { return _message_buffer[9]; }
/** Get the checksum for the packet */
uint8_t GetChecksum( ) const { return _message_buffer[_message_length-1]; }
/** A debugging function that prints the contents of the frame. */
void Print( ) const;
/** Destructor */
~SickLDMessage( );
private:
/** Computes the checksum of the frame.
* NOTE: Uses XOR of single bytes over packet payload data.
*/
uint8_t _computeXOR( const uint8_t * const data, const uint32_t length );
};
} /* namespace SickToolbox */
#endif /* SICK_LD_MESSAGE_HH */

View File

@ -0,0 +1,120 @@
/*!
* \file SickLDUtility.hh
* \brief Defines simple utility functions for working with the Sick LD.
*
* Code by Jason C. Derenick and Thomas H. Miller.
* Contact derenick(at)lehigh(dot)edu
*
* The Sick LIDAR Matlab/C++ Toolbox
* Copyright (c) 2008, Jason C. Derenick and Thomas H. Miller
* All rights reserved.
*
* This software is released under a BSD Open-Source License.
* See http://sicktoolbox.sourceforge.net
*/
/* Auto-generated header */
#include "SickConfig.hh"
/**
* \def REVERSE_BYTE_ORDER_16
* \brief Reverses the byte order of the given 16 bit unsigned integer
*/
#define REVERSE_BYTE_ORDER_16( y ) ( ( ( y & 0x00FF ) << 8 ) | ( ( y & 0xFF00 ) >> 8 ) )
/**
* \def REVERSE_BYTE_ORDER_32
* \brief Reverses the byte order of the given 32 bit unsigned integer
*/
#define REVERSE_BYTE_ORDER_32( y ) ( ( ( y & 0x000000FF ) << 24 ) | ( ( y & 0x0000FF00 ) << 8 ) | ( ( y & 0x00FF0000 ) >> 8 ) | ( ( y & 0xFF000000 ) >> 24 ) )
/* Associate the namespace */
namespace SickToolbox {
#ifndef WORDS_BIGENDIAN
/* NOTE: The following functions are necessary since the Sick LD doesn't adopt the
* convention of converting from network byte order.
*/
/**
* \brief Converts host byte order (little-endian) to Sick LD byte order (big-endian)
* \param value The 2-byte value to convert to big-endian
* \return Value in Sick LD byte order (big-endian)
*/
inline uint16_t host_to_sick_ld_byte_order( uint16_t value ) {
return REVERSE_BYTE_ORDER_16(value);
}
/**
* \brief Converts host byte order (little-endian) to Sick LD byte order (big-endian)
* \param value The 4-byte value to convert to big-endian
* \return Value in Sick LD byte order (big-endian)
*/
inline uint32_t host_to_sick_ld_byte_order( uint32_t value ) {
return REVERSE_BYTE_ORDER_32(value);
}
/**
* \brief Converts Sick LD byte order (big-endian) to host byte order (little-endian)
* \param value The 2-byte value to convert to little-endian
* \return Value in host byte order (little-endian)
*/
inline uint16_t sick_ld_to_host_byte_order( uint16_t value ) {
return REVERSE_BYTE_ORDER_16(value);
}
/**
* \brief Converts Sick LD byte order (big-endian) to host byte order (little-endian)
* \param value The 4-byte value to convert to little-endian
* \return Value in host byte order (little-endian)
*/
inline uint32_t sick_ld_to_host_byte_order( uint32_t value ) {
return REVERSE_BYTE_ORDER_32(value);
}
#else // The host has a big-endian architecture
/**
* \brief Converts host byte order (big-endian) to Sick LD byte order (big-endian)
* \param value The 2-byte value to convert to big-endian
* \return Value in Sick LD byte order (big-endian)
*/
inline uint16_t host_to_sick_ld_byte_order( uint16_t value ) {
return value;
}
/**
* \brief Converts host byte order (big-endian) to Sick LD byte order (big-endian)
* \param value The 4-byte value to convert to big-endian
* \return Value in Sick LD byte order (big-endian)
*/
inline uint32_t host_to_sick_ld_byte_order( uint32_t value ) {
return value;
}
/**
* \brief Converts Sick LD byte order (big-endian) to host byte order (big-endian)
* \param value The 2-byte value to convert to big-endian
* \return Value in host byte order (big-endian)
*/
inline uint16_t sick_ld_to_host_byte_order( uint16_t value ) {
return value;
}
/**
* \brief Converts Sick LD byte order (big-endian) to host byte order (big-endian)
* \param value The 4-byte value to convert to big-endian
* \return Value in host byte order (big-endian)
*/
inline uint32_t sick_ld_to_host_byte_order( uint32_t value ) {
return value;
}
#endif /* _LITTLE_ENDIAN_HOST */
/*
* NOTE: Other utility functions can be defined here
*/
} //namespace SickToolbox

View File

@ -0,0 +1,452 @@
/*!
* \file SickLIDAR.hh
* \brief Defines the abstract parent class for defining
* a Sick LIDAR device driver.
*
* Code by Jason C. Derenick and Thomas H. Miller.
* Contact derenick(at)lehigh(dot)edu
*
* The Sick LIDAR Matlab/C++ Toolbox
* Copyright (c) 2008, Jason C. Derenick and Thomas H. Miller
* All rights reserved.
*
* This software is released under a BSD Open-Source License.
* See http://sicktoolbox.sourceforge.net
*/
/**
* \mainpage The Sick LIDAR Matlab/C++ Toolbox
* \author Jason C. Derenick and Thomas H. Miller.
* \version 1.0
*
* The Sick LIDAR Matlab/C++ Toolbox
* Copyright (c) 2008, Jason C. Derenick and Thomas H. Miller
* All rights reserved.
*
* This software is released under a BSD Open-Source License.
* See http://sicktoolbox.sourceforge.net
*/
#ifndef SICK_LIDAR
#define SICK_LIDAR
/* Definition dependencies */
#include <new>
#include <string>
#include <iomanip>
#include <iostream>
#include <fcntl.h>
#include <pthread.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <unistd.h>
#include "SickException.hh"
/* Associate the namespace */
namespace SickToolbox {
/**
* \class SickLIDAR
* \brief Provides an abstract parent for all Sick LIDAR devices
*/
template < class SICK_MONITOR_CLASS, class SICK_MSG_CLASS >
class SickLIDAR {
public:
/** The primary constructor */
SickLIDAR( );
/** Indicates whether device is initialized */
bool IsInitialized() { return _sick_initialized; }
/** A virtual destructor */
virtual ~SickLIDAR( );
protected:
/** Sick device file descriptor */
int _sick_fd;
/** A flag to indicated whether the device is properly initialized */
bool _sick_initialized;
/** A pointer to the driver's buffer monitor */
SICK_MONITOR_CLASS *_sick_buffer_monitor;
/** Indicates whether the Sick buffer monitor is running */
bool _sick_monitor_running;
/** A method for setting up a general connection */
virtual void _setupConnection( ) = 0;
/** A method for tearing down a connection to the Sick */
virtual void _teardownConnection( ) = 0;
/** Starts the driver listening for messages */
void _startListening( ) throw( SickThreadException );
/** Stops the driver from listening */
void _stopListening( ) throw( SickThreadException );
/** Indicates whether there is a monitor currently running */
bool _monitorRunning( ) const { return _sick_monitor_running; }
/** Make the associated file descriptor non blocking */
void _setBlockingIO( ) const throw ( SickIOException );
/** Make the associated file descriptor non blocking */
void _setNonBlockingIO( ) const throw ( SickIOException );
/** Send a message to the Sick LD (allows specifying min time between transmitted bytes) */
void _sendMessage( const SICK_MSG_CLASS &sick_message, const unsigned int byte_interval ) const
throw( SickIOException );
/** Acquire the next message from the message container */
void _recvMessage( SICK_MSG_CLASS &sick_message, const unsigned int timeout_value ) const throw ( SickTimeoutException );
/** Search the stream for a payload with a particular "header" byte string */
void _recvMessage( SICK_MSG_CLASS &sick_message,
const uint8_t * const byte_sequence,
const unsigned int byte_sequence_length,
const unsigned int timeout_value ) const throw ( SickTimeoutException );
/** An inline function for computing elapsed time */
double _computeElapsedTime( const struct timeval &beg_time, const struct timeval &end_time ) const { return ((end_time.tv_sec*1e6)+(end_time.tv_usec))-((beg_time.tv_sec*1e6)+beg_time.tv_usec); }
/** Sends a request to the Sick and acquires looks for the reply */
virtual void _sendMessageAndGetReply( const SICK_MSG_CLASS &send_message,
SICK_MSG_CLASS &recv_message,
const uint8_t * const byte_sequence,
const unsigned int byte_sequence_length,
const unsigned int byte_interval,
const unsigned int timeout_value,
const unsigned int num_tries ) throw( SickTimeoutException, SickIOException);
};
/**
* \brief Initializes the buffer monitor
*/
template< class SICK_MONITOR_CLASS, class SICK_MSG_CLASS >
SickLIDAR< SICK_MONITOR_CLASS, SICK_MSG_CLASS >::SickLIDAR( ) :
_sick_fd(0), _sick_initialized(false), _sick_buffer_monitor(NULL), _sick_monitor_running(false) {
try {
/* Attempt to instantiate a new SickBufferMonitor for the device */
_sick_buffer_monitor = new SICK_MONITOR_CLASS;
}
catch ( std::bad_alloc &allocation_exception ) {
std::cerr << "SickLIDAR::SickLIDAR: Allocation error - " << allocation_exception.what() << std::endl;
}
}
/**
* \brief Destructor tears down buffer monitor
*/
template< class SICK_MONITOR_CLASS, class SICK_MSG_CLASS >
SickLIDAR< SICK_MONITOR_CLASS, SICK_MSG_CLASS >::~SickLIDAR( ) {
/* Deallocate the buffer monitor */
if (_sick_buffer_monitor) {
delete _sick_buffer_monitor;
}
}
/**
* \brief Activates the buffer monitor for the driver
*/
template< class SICK_MONITOR_CLASS, class SICK_MSG_CLASS >
void SickLIDAR< SICK_MONITOR_CLASS, SICK_MSG_CLASS >::_startListening( ) throw( SickThreadException ) {
/* Try to start the monitor */
try {
_sick_buffer_monitor->StartMonitor(_sick_fd);
}
/* Handle a thread exception */
catch(SickThreadException &sick_thread_exception) {
std::cerr << sick_thread_exception.what() << std::endl;
throw;
}
/* Handle a thread exception */
catch(...) {
std::cerr << "SickLIDAR::_startListening: Unknown exception!!!" << std::endl;
throw;
}
/* Set the flag */
_sick_monitor_running = true;
}
/**
* \brief Activates the buffer monitor for the driver
*/
template< class SICK_MONITOR_CLASS, class SICK_MSG_CLASS >
void SickLIDAR< SICK_MONITOR_CLASS, SICK_MSG_CLASS >::_stopListening( ) throw( SickThreadException ) {
/* Try to start the monitor */
try {
_sick_buffer_monitor->StopMonitor();
}
/* Handle a thread exception */
catch(SickThreadException &sick_thread_exception) {
std::cerr << sick_thread_exception.what() << std::endl;
throw;
}
/* Handle a thread exception */
catch(...) {
std::cerr << "SickLIDAR::_stopListening: Unknown exception!!!" << std::endl;
throw;
}
/* Reset the flag */
_sick_monitor_running = false;
}
/**
* \brief A simple method for setting blocking I/O
*/
template< class SICK_MONITOR_CLASS, class SICK_MSG_CLASS >
void SickLIDAR< SICK_MONITOR_CLASS, SICK_MSG_CLASS >::_setBlockingIO( ) const throw( SickIOException ) {
/* Read the flags */
int fd_flags = 0;
if((fd_flags = fcntl(_sick_fd,F_GETFL)) < 0) {
throw SickIOException("SickLIDAR::_setNonBlocking: fcntl failed!");
}
/* Set the new flags */
if(fcntl(_sick_fd,F_SETFL,fd_flags & (~O_NONBLOCK)) < 0) {
throw SickIOException("SickLIDAR::_setNonBlocking: fcntl failed!");
}
}
/**
* \brief A simple method for setting non-blocking I/O
*/
template< class SICK_MONITOR_CLASS, class SICK_MSG_CLASS >
void SickLIDAR< SICK_MONITOR_CLASS, SICK_MSG_CLASS >::_setNonBlockingIO( ) const throw ( SickIOException ) {
/* Read the flags */
int fd_flags = 0;
if((fd_flags = fcntl(_sick_fd,F_GETFL)) < 0) {
throw SickIOException("SickLIDAR::_setNonBlockingIO: fcntl failed!");
}
/* Set the new flags */
if(fcntl(_sick_fd,F_SETFL,fd_flags | O_NONBLOCK) < 0) {
throw SickIOException("SickLIDAR::_setNonBlockingIO: fcntl failed!");
}
}
/**
* \brief Sends a message to the Sick device
* \param &sick_message A reference to the well-formed message that is to be sent to the Sick
* \param byte_interval Minimum time in microseconds between transmitted bytes
*/
template< class SICK_MONITOR_CLASS, class SICK_MSG_CLASS >
void SickLIDAR< SICK_MONITOR_CLASS, SICK_MSG_CLASS >::_sendMessage( const SICK_MSG_CLASS &sick_message, const unsigned int byte_interval ) const
throw( SickIOException ) {
uint8_t message_buffer[SICK_MSG_CLASS::MESSAGE_MAX_LENGTH] = {0};
/* Copy the given message and get the message length */
sick_message.GetMessage(message_buffer);
unsigned int message_length = sick_message.GetMessageLength();
/* Check whether a transmission delay between bytes is requested */
if (byte_interval == 0) {
/* Write the message to the stream */
if ((unsigned int)write(_sick_fd,message_buffer,message_length) != message_length) {
throw SickIOException("SickLIDAR::_sendMessage: write() failed!");
}
}
else {
/* Write the message to the unit one byte at a time */
for (unsigned int i = 0; i < message_length; i++) {
/* Write a single byte to the stream */
if (write(_sick_fd,&message_buffer[i],1) != 1) {
throw SickIOException("SickLIDAR::_sendMessage: write() failed!");
}
/* Some time between bytes (Sick LMS 2xx likes this) */
usleep(byte_interval);
}
}
}
/**
* \brief Attempt to acquire the latest available message from the device
* \param &sick_message A reference to the container that will hold the most recent message
* \param timeout_value The time in secs to wait before throwing a timeout error
* \return True if a new message was received, False otherwise
*/
template< class SICK_MONITOR_CLASS, class SICK_MSG_CLASS >
void SickLIDAR< SICK_MONITOR_CLASS, SICK_MSG_CLASS >::_recvMessage( SICK_MSG_CLASS &sick_message,
const unsigned int timeout_value ) const throw ( SickTimeoutException ) {
/* Timeval structs for handling timeouts */
struct timeval beg_time, end_time;
/* Acquire the elapsed time since epoch */
gettimeofday(&beg_time,NULL);
/* Check the shared object */
while(!_sick_buffer_monitor->GetNextMessageFromMonitor(sick_message)) {
/* Sleep a little bit */
usleep(1000);
/* Check whether the allowed time has expired */
gettimeofday(&end_time,NULL);
if (_computeElapsedTime(beg_time,end_time) > timeout_value) {
throw SickTimeoutException("SickLIDAR::_recvMessage: Timeout occurred!");
}
}
}
/**
* \brief Attempt to acquire a message having a payload beginning w/ the given byte sequence
* \param &sick_message A reference to the container that will hold the most recent message
* \param *byte_sequence The byte sequence that is expected to lead off the payload in the packet (e.g. service codes, etc...)
* \param byte_sequence_length The number of bytes in the given byte_sequence
* \param timeout_value The time in usecs to wait before throwing a timeout error
* \return True if a new message was received, False otherwise
*
* NOTE: This method is intended to be a helper for _sendMessageAndGetReply
*/
template< class SICK_MONITOR_CLASS, class SICK_MSG_CLASS >
void SickLIDAR< SICK_MONITOR_CLASS, SICK_MSG_CLASS >::_recvMessage( SICK_MSG_CLASS &sick_message,
const uint8_t * const byte_sequence,
const unsigned int byte_sequence_length,
const unsigned int timeout_value ) const throw( SickTimeoutException ) {
/* Define a buffer */
uint8_t payload_buffer[SICK_MSG_CLASS::MESSAGE_PAYLOAD_MAX_LENGTH];
/* Timeval structs for handling timeouts */
struct timeval beg_time, end_time;
/* A container for the message */
SICK_MSG_CLASS curr_message;
/* Get the elapsed time since epoch */
gettimeofday(&beg_time,NULL);
/* Check until it is found or a timeout */
for(;;) {
/* Attempt to acquire the message */
unsigned int i = 0;
if (_sick_buffer_monitor->GetNextMessageFromMonitor(curr_message)) {
/* Extract the payload subregion */
curr_message.GetPayloadSubregion(payload_buffer,0,byte_sequence_length-1);
/* Match the byte sequence */
for (i=0; (i < byte_sequence_length) && (payload_buffer[i] == byte_sequence[i]); i++);
/* Our message was found! */
if (i == byte_sequence_length) {
sick_message = curr_message;
break;
}
}
/* Sleep a little bit */
usleep(1000);
/* Check whether the allowed time has expired */
gettimeofday(&end_time,NULL);
if (_computeElapsedTime(beg_time,end_time) > timeout_value) {
throw SickTimeoutException();
}
}
}
/**
* \param sick_send_frame A sick frame to be sent to the LMS
* \param sick_receive_frame A sick frame to hold the response (expected or unexpected) of the LMS
* \param num_tries The number of times to send the frame in the event the LMS fails to reply
* \param timeout The epoch to wait before considering a sent frame lost
* \return True if the message was sent and the expected reply was received
*/
template< class SICK_MONITOR_CLASS, class SICK_MSG_CLASS >
void SickLIDAR< SICK_MONITOR_CLASS, SICK_MSG_CLASS >::_sendMessageAndGetReply( const SICK_MSG_CLASS &send_message,
SICK_MSG_CLASS &recv_message,
const uint8_t * const byte_sequence,
const unsigned int byte_sequence_length,
const unsigned int byte_interval,
const unsigned int timeout_value,
const unsigned int num_tries )
throw( SickTimeoutException, SickIOException ) {
/* Send the message for at most num_tries number of times */
for(unsigned int i = 0; i < num_tries; i++) {
try {
/* Send the frame to the unit */
_sendMessage(send_message,byte_interval);
/* Wait for the reply! */
_recvMessage(recv_message,byte_sequence,byte_sequence_length,timeout_value);
/* message was found! */
break;
}
/* Handle a timeout! */
catch (SickTimeoutException &sick_timeout) {
/* Check if it was found! */
if (i == num_tries - 1) {
throw SickTimeoutException("SickLIDAR::_sendMessageAndGetReply: Attempted max number of tries w/o success!");
}
/* Display the number of tries remaining! */
std::cerr << sick_timeout.what() << " " << num_tries - i - 1 << " tries remaining" << std::endl;
}
/* Handle write buffer exceptions */
catch (SickIOException &sick_io_error) {
std::cerr << sick_io_error.what() << std::endl;
throw;
}
/* A safety net */
catch (...) {
std::cerr << "SickLIDAR::_sendMessageAndGetReply: Unknown exception!!!" << std::endl;
throw;
}
}
}
} /* namespace SickToolbox */
#endif /* SICK_LIDAR */

View File

@ -0,0 +1,335 @@
/*!
* \file SickLMS1xx.hh
* \brief Defines the SickLMS1xx class for working with the
* Sick LMS1xx laser range finders.
*
* Code by Jason C. Derenick and Christopher R. Mansley.
* Contact jasonder(at)seas(dot)upenn(dot)edu
*
* The Sick LIDAR Matlab/C++ Toolbox
* Copyright (c) 2008, Jason C. Derenick and Thomas H. Miller
* All rights reserved.
*
* This software is released under a BSD Open-Source License.
* See http://sicktoolbox.sourceforge.net
*/
#ifndef SICK_LMS_1XX_HH
#define SICK_LMS_1XX_HH
/* Macros */
#define DEFAULT_SICK_LMS_1XX_IP_ADDRESS "192.168.0.1" ///< Default IP Address
#define DEFAULT_SICK_LMS_1XX_TCP_PORT (2111) ///< Sick LMS 1xx TCP/IP Port
#define DEFAULT_SICK_LMS_1XX_CONNECT_TIMEOUT (1000000) ///< Max time for establishing connection (usecs)
#define DEFAULT_SICK_LMS_1XX_MESSAGE_TIMEOUT (5000000) ///< Max time for reply (usecs)
#define DEFAULT_SICK_LMS_1XX_STATUS_TIMEOUT (60000000) ///< Max time it should take to change status
#define SICK_LMS_1XX_SCAN_AREA_MIN_ANGLE (-450000) ///< -45 degrees (1/10000) degree
#define SICK_LMS_1XX_SCAN_AREA_MAX_ANGLE (2250000) ///< 225 degrees (1/10000) degree
/* Definition dependencies */
#include <string>
#include <arpa/inet.h>
#include "SickLIDAR.hh"
#include "SickLMS1xxBufferMonitor.hh"
#include "SickLMS1xxMessage.hh"
#include "SickException.hh"
/**
* \namespace SickToolbox
* \brief Encapsulates the Sick LIDAR Matlab/C++ toolbox
*/
namespace SickToolbox {
/**
* \class SickLMS1xx
* \brief Provides a simple driver interface for working with the
* Sick LD-OEM/Sick LD-LRS long-range models via Ethernet.
*/
class SickLMS1xx : public SickLIDAR< SickLMS1xxBufferMonitor, SickLMS1xxMessage > {
public:
static const int SICK_LMS_1XX_MAX_NUM_MEASUREMENTS = 1082; ///< LMS 1xx max number of measurements
/*!
* \enum sick_lms_1xx_status_t
* \brief Defines the Sick LMS 1xx status.
* This enum lists all of the Sick LMS 1xx status.
*/
enum sick_lms_1xx_status_t {
SICK_LMS_1XX_STATUS_UNKNOWN = 0x00, ///< LMS 1xx status undefined
SICK_LMS_1XX_STATUS_INITIALIZATION = 0x01, ///< LMS 1xx initializing
SICK_LMS_1XX_STATUS_CONFIGURATION = 0x02, ///< LMS 1xx configuration
SICK_LMS_1XX_STATUS_IDLE = 0x03, ///< LMS 1xx is idle
SICK_LMS_1XX_STATUS_ROTATED = 0x04, ///< LMS 1xx mirror rotating
SICK_LMS_1XX_STATUS_IN_PREP = 0x05, ///< LMS 1xx in preparation
SICK_LMS_1XX_STATUS_READY = 0x06, ///< LMS 1xx is ready
SICK_LMS_1XX_STATUS_READY_FOR_MEASUREMENT = 0x07 ///< LMS 1xx is ready to give measurements
};
/*!
* \enum sick_lms_1xx_scan_format_t
* \brief Defines the Sick LMS 1xx scan types
* This enum is for specifiying the desired scan returns.
*/
enum sick_lms_1xx_scan_format_t {
SICK_LMS_1XX_SCAN_FORMAT_DIST_SINGLE_PULSE_REFLECT_NONE = 0x00, ///< Single-pulse dist, no reflect
SICK_LMS_1XX_SCAN_FORMAT_DIST_SINGLE_PULSE_REFLECT_8BIT = 0x01, ///< Single-pulse dist, 8bit reflect
SICK_LMS_1XX_SCAN_FORMAT_DIST_SINGLE_PULSE_REFLECT_16BIT = 0x02, ///< Single-pulse dist, 16bit reflect
SICK_LMS_1XX_SCAN_FORMAT_DIST_DOUBLE_PULSE_REFLECT_NONE = 0x03, ///< Double-pulse dist, no reflect
SICK_LMS_1XX_SCAN_FORMAT_DIST_DOUBLE_PULSE_REFLECT_8BIT = 0x04, ///< Double-pulse dist, 8bit reflect
SICK_LMS_1XX_SCAN_FORMAT_DIST_DOUBLE_PULSE_REFLECT_16BIT = 0x05, ///< Double-pulse dist, 16bit reflect
SICK_LMS_1XX_SCAN_FORMAT_UNKNOWN = 0xFF ///< Unknown format
};
/*!
* \enum sick_lms_1xx_scan_freq_t
* \brief Defines the Sick LMS 1xx scan frequency.
* This enum lists all of the Sick LMS 1xx scan frequencies.
*/
enum sick_lms_1xx_scan_freq_t {
SICK_LMS_1XX_SCAN_FREQ_UNKNOWN = 0x00, ///< LMS 1xx scan freq unknown
SICK_LMS_1XX_SCAN_FREQ_25 = 0x09C4, ///< LMS 1xx scan freq 25Hz
SICK_LMS_1XX_SCAN_FREQ_50 = 0X1388 ///< LMS 1xx scan freq 50Hz
};
/*!
* \enum sick_lms_1xx_scan_res_t
* \brief Defines the Sick LMS 1xx scan resolution.
* This enum lists all of the Sick LMS 1xx scan resolutions.
*/
enum sick_lms_1xx_scan_res_t {
SICK_LMS_1XX_SCAN_RES_UNKNOWN = 0x00, ///< LMS 1xx scab res unknown
SICK_LMS_1XX_SCAN_RES_25 = 0x09C4, ///< LMS 1xx scan res 0.25 deg
SICK_LMS_1XX_SCAN_RES_50 = 0x1388 ///< LMS 1xx scan res 0.50 deg
};
/** Primary constructor */
SickLMS1xx( const std::string sick_ip_address = DEFAULT_SICK_LMS_1XX_IP_ADDRESS,
const uint16_t sick_tcp_port = DEFAULT_SICK_LMS_1XX_TCP_PORT );
/** Initializes the Sick LD unit (use scan areas defined in flash) */
void Initialize( const bool disp_banner = true ) throw( SickIOException, SickThreadException, SickTimeoutException, SickErrorException );
/** Sets the Sick LMS 1xx scan frequency and scan resolution */
void SetSickScanFreqAndRes( const sick_lms_1xx_scan_freq_t scan_freq,
const sick_lms_1xx_scan_res_t scan_res ) throw( SickTimeoutException, SickIOException, SickErrorException );
/** Get the Sick LMS 1xx scan frequency */
sick_lms_1xx_scan_freq_t GetSickScanFreq( ) const throw ( SickIOException );
/** Get the Sick LMS 1xx scan resolution */
sick_lms_1xx_scan_res_t GetSickScanRes( ) const throw ( SickIOException );
/** Get the Sick LMS 1xx scan start angle */
double GetSickStartAngle( ) const throw ( SickIOException );
/** Get the Sick LMS 1xx scan stop angle */
double GetSickStopAngle( ) const throw ( SickIOException );
/** Sets the sick scan data format */
void SetSickScanDataFormat( const sick_lms_1xx_scan_format_t scan_format ) throw( SickTimeoutException, SickIOException, SickThreadException, SickErrorException );
/** Get the Sick Range Measurements */
void GetSickMeasurements( unsigned int * const range_1_vals,
unsigned int * const range_2_vals,
unsigned int * const reflect_1_vals,
unsigned int * const reflect_2_vals,
unsigned int & num_measurements,
unsigned int * const dev_status = NULL ) throw ( SickIOException, SickConfigException, SickTimeoutException );
/** Uninitializes the Sick LD unit */
void Uninitialize( const bool disp_banner = true ) throw( SickIOException, SickTimeoutException, SickErrorException, SickThreadException );
/** Utility function for converting integer to scan frequency */
sick_lms_1xx_scan_freq_t IntToSickScanFreq( const int scan_freq ) const;
/** Utility function for converting scan frequency to integer */
int SickScanFreqToInt( const sick_lms_1xx_scan_freq_t scan_freq ) const;
/** Utility function for converting double to scan resolution */
sick_lms_1xx_scan_res_t DoubleToSickScanRes( const double scan_res ) const;
/** Utility function for converting scan resolution to double */
double SickScanResToDouble( const sick_lms_1xx_scan_res_t scan_res ) const;
/** Destructor */
~SickLMS1xx();
private:
/*!
* \struct sick_lms_1xx_scan_config_tag
* \brief A structure for aggregrating the
* Sick LMS 1xx configuration params.
*/
/*!
* \typedef sick_lms_1xx_scan_config_t
* \brief Adopt c-style convention
*/
typedef struct sick_lms_1xx_scan_config_tag {
sick_lms_1xx_scan_freq_t sick_scan_freq; ///< Sick scan frequency
sick_lms_1xx_scan_res_t sick_scan_res; ///< Sick scan resolution
int32_t sick_start_angle; ///< Sick scan area start angle
int32_t sick_stop_angle; ///< Sick scan area stop angle
} sick_lms_1xx_scan_config_t;
/** The Sick LMS 1xx IP address */
std::string _sick_ip_address;
/** The Sick LMS 1xx TCP port number */
uint16_t _sick_tcp_port;
/** Sick LMS 1xx socket address struct */
struct sockaddr_in _sick_inet_address_info;
/** Sick LMS 1xx configuration struct */
sick_lms_1xx_scan_config_t _sick_scan_config;
/** Sick LMS 1xx current scan data format */
sick_lms_1xx_scan_format_t _sick_scan_format;
/** Sick LMS 1xx configuration struct */
sick_lms_1xx_status_t _sick_device_status;
/** Sick LMS 1xx temperature status */
bool _sick_temp_safe;
/** Sick LMS 1xx streaming status */
bool _sick_streaming;
/** Setup the connection parameters and establish TCP connection! */
void _setupConnection( ) throw( SickIOException, SickTimeoutException );
/** Re-initialized the device */
void _reinitialize( ) throw( SickIOException, SickThreadException, SickTimeoutException, SickErrorException );
/** Teardown the connection to the Sick LD */
void _teardownConnection( ) throw( SickIOException );
/** Acquire the latest Sick LMS's status */
void _updateSickStatus( ) throw( SickTimeoutException, SickIOException );
/** Acquire the Sick LMS's scan config */
void _getSickScanConfig( ) throw( SickTimeoutException, SickIOException );
/** Sets the scan configuration (volatile, does not write to EEPROM) */
void _setSickScanConfig( const sick_lms_1xx_scan_freq_t scan_freq,
const sick_lms_1xx_scan_res_t scan_res,
const int start_angle, const int stop_angle ) throw( SickTimeoutException, SickIOException, SickErrorException );
/** Set access mode for configuring device */
void _setAuthorizedClientAccessMode( ) throw( SickTimeoutException, SickErrorException, SickIOException );
/** Save configuration parameters to EEPROM */
void _writeToEEPROM( ) throw( SickTimeoutException, SickIOException );
/** Send the message w/o waiting for a reply */
void _sendMessage( const SickLMS1xxMessage &send_message ) const throw ( SickIOException );
/** Send the message and grab expected reply */
void _sendMessageAndGetReply( const SickLMS1xxMessage &send_message,
SickLMS1xxMessage &recv_message,
const std::string reply_command_code,
const std::string reply_command,
const unsigned int timeout_value = DEFAULT_SICK_LMS_1XX_MESSAGE_TIMEOUT,
const unsigned int num_tries = 1 ) throw( SickIOException, SickTimeoutException );
/** Receive a message */
void _recvMessage( SickLMS1xxMessage &sick_message ) const throw ( SickTimeoutException );
/** Start device measuring */
void _startMeasuring( ) throw ( SickTimeoutException, SickIOException );
/** Stop device measuring */
void _stopMeasuring( ) throw ( SickTimeoutException, SickIOException );
/** Request a data data stream type */
void _requestDataStream( ) throw ( SickTimeoutException, SickConfigException, SickIOException );
/** Start streaming measurements */
void _startStreamingMeasurements( )throw( SickTimeoutException, SickIOException );
/** Stop streaming measurements */
void _stopStreamingMeasurements( const bool disp_banner = true ) throw( SickTimeoutException, SickIOException );
/** Set device to measuring mode */
void _checkForMeasuringStatus( unsigned int timeout_value = DEFAULT_SICK_LMS_1XX_STATUS_TIMEOUT ) throw( SickTimeoutException, SickIOException );
/** Sets the sick scan data format */
void _setSickScanDataFormat( const sick_lms_1xx_scan_format_t scan_format ) throw( SickTimeoutException, SickIOException, SickThreadException, SickErrorException );
/** Restore device to measuring mode */
void _restoreMeasuringMode( ) throw( SickTimeoutException, SickIOException );
/** Ensures a feasible scan area */
bool _validScanArea( const int start_angle, const int stop_angle ) const;
/** Utility function to convert int to status */
sick_lms_1xx_status_t _intToSickStatus( const int status ) const;
/** Utility function for printing Sick scan config */
void _printSickScanConfig( ) const;
/** Utility function for printing footer after initialization */
void _printInitFooter( ) const;
/** Utility function for returning scan format as string */
std::string _sickScanDataFormatToString( const sick_lms_1xx_scan_format_t scan_format ) const;
/** Utility function for converting sick freq to doubles */
double _convertSickAngleUnitsToDegs( const int sick_angle ) const { return ((double)sick_angle)/10000; }
/** Utility function for converting sick Hz values ints */
unsigned int _convertSickFreqUnitsToHz( const unsigned int sick_freq ) const { return (unsigned int)(((double)sick_freq)/100); }
/** Utility function to convert config error int to str */
std::string _intToSickConfigErrorStr( const int error ) const;
/** Utility function to locate substring in string */
bool _findSubString( const char * const str, const char * const substr, const unsigned int str_length, const unsigned int substr_length,
unsigned int &substr_pos, unsigned int start_pos = 0 ) const;
/** Utility function for extracting next integer from tokenized string */
char * _convertNextTokenToUInt( char * const str_buffer, unsigned int & num_val, const char * const delimeter = " " ) const;
};
/*!
* \typedef sick_lms_1xx_status_t
* \brief Makes working w/ SickLMS1xx::sick_lms_1xx_status_t a bit easier
*/
typedef SickLMS1xx::sick_lms_1xx_status_t sick_lms_1xx_status_t;
/*!
* \typedef sick_lms_1xx_scan_format_t
* \brief Makes working w/ SickLMS1xx::sick_lms_1xx_scan_format_t a bit easier
*/
typedef SickLMS1xx::sick_lms_1xx_scan_format_t sick_lms_1xx_scan_format_t;
/*!
* \typedef sick_lms_1xx_scan_freq_t
* \brief Makes working w/ SickLMS1xx::sick_lms_1xx_scan_freq_t a bit easier
*/
typedef SickLMS1xx::sick_lms_1xx_scan_freq_t sick_lms_1xx_scan_freq_t;
/*!
* \typedef sick_lms_1xx_scan_res_t
* \brief Makes working w/ SickLMS1xx::sick_lms_1xx_scan_res_t a bit easier
*/
typedef SickLMS1xx::sick_lms_1xx_scan_res_t sick_lms_1xx_scan_res_t;
} //namespace SickToolbox
#endif /* SICK_LMS_1XX_HH */

View File

@ -0,0 +1,56 @@
/*!
* \file SickLMS1xxBufferMonitor.hh
* \brief Defines a class for monitoring the receive
* buffer when interfacing w/ a Sick LMS 1xx
* laser range finder unit.
*
* Code by Jason C. Derenick and Christopher R. Mansley.
* Contact jasonder(at)seas(dot)upenn(dot)edu
*
* The Sick LIDAR Matlab/C++ Toolbox
* Copyright (c) 2009, Jason C. Derenick and Christopher R. Mansley
* All rights reserved.
*
* This software is released under a BSD Open-Source License.
* See http://sicktoolbox.sourceforge.net
*/
#ifndef SICK_LMS_1XX_BUFFER_MONITOR_HH
#define SICK_LMS_1XX_BUFFER_MONITOR_HH
#define DEFAULT_SICK_LMS_1XX_BYTE_TIMEOUT (100000) ///< Max allowable time between consecutive bytes
/* Definition dependencies */
#include "SickLMS1xxMessage.hh"
#include "SickBufferMonitor.hh"
#include "SickException.hh"
/* Associate the namespace */
namespace SickToolbox {
/*!
* \brief A class for monitoring the receive buffer when interfacing with a Sick LD LIDAR
*/
class SickLMS1xxBufferMonitor : public SickBufferMonitor< SickLMS1xxBufferMonitor, SickLMS1xxMessage > {
public:
/** A standard constructor */
SickLMS1xxBufferMonitor( );
/** A method for extracting a single message from the stream */
void GetNextMessageFromDataStream( SickLMS1xxMessage &sick_message ) throw( SickIOException );
/** A standard destructor */
~SickLMS1xxBufferMonitor( );
private:
/* A utility function for flushing the receive buffer */
void _flushTCPRecvBuffer( ) const throw ( SickIOException );
};
} /* namespace SickToolbox */
#endif /* SICK_LMS_1XX_BUFFER_MONITOR_HH */

View File

@ -0,0 +1,83 @@
/*!
* \file SickLMS1xx Message.hh
* \brief Defines the class SickLMS1xxMessage.
*
* Code by Jason C. Derenick and Christopher R. Mansley.
* Contact jasonder(at)seas(dot)upenn(dot)edu
*
* The Sick LIDAR Matlab/C++ Toolbox
* Copyright (c) 2009, Jason C. Derenick and Christoper R. Mansley
* All rights reserved.
*
* This software is released under a BSD Open-Source License.
* See http://sicktoolbox.sourceforge.net
*/
#ifndef SICK_LMS_1XX_MESSAGE_HH
#define SICK_LMS_1XX_MESSAGE_HH
/* Macros */
#define SICK_LMS_1XX_MSG_HEADER_LEN (1) ///< Sick LMS 1xx message header length in bytes
#define SICK_LMS_1XX_MSG_PAYLOAD_MAX_LEN (30000) ///< Sick LMS 1xx maximum payload length
#define SICK_LMS_1XX_MSG_TRAILER_LEN (1) ///< Sick LMS 1xx length of the message trailer
/* Definition dependencies */
#include <string.h>
#include <arpa/inet.h>
#include "SickMessage.hh"
#include "SickException.hh"
/* Associate the namespace */
namespace SickToolbox {
/**
* \class SickLMS1xxMessage
* \brief A class to represent all messages sent to and from the Sick LMS 1xx unit.
*/
class SickLMS1xxMessage : public SickMessage< SICK_LMS_1XX_MSG_HEADER_LEN, SICK_LMS_1XX_MSG_PAYLOAD_MAX_LEN, SICK_LMS_1XX_MSG_TRAILER_LEN > {
public:
/** A standard constructor */
SickLMS1xxMessage( );
/** Constructs a packet by using BuildMessage */
SickLMS1xxMessage( const uint8_t * const payload_buffer, const unsigned int payload_length );
/** Constructs a packet using ParseMessage() */
SickLMS1xxMessage( const uint8_t * const message_buffer );
/** Construct a well-formed raw packet */
void BuildMessage( const uint8_t * const payload_buffer, const unsigned int payload_length );
/** Populates fields from a (well-formed) raw packet */
void ParseMessage( const uint8_t * const message_buffer ) throw ( SickIOException );
/** Get the length of the service code associated with the message */
std::string GetCommandType( ) const { return _command_type; }
/** Get the service sub-code associated with the message */
std::string GetCommand( ) const { return _command; }
/** Reset the data associated with this message (for initialization purposes) */
void Clear( );
/** A debugging function that prints the contents of the frame. */
void Print( ) const;
/** Destructor */
~SickLMS1xxMessage( );
private:
/** Command type associated w/ message */
std::string _command_type;
/** Command associated w/ message */
std::string _command;
};
} /* namespace SickToolbox */
#endif /* SICK_LMS_1XX_MESSAGE_HH */

View File

@ -0,0 +1,137 @@
/*!
* \file SickLMS1xxUtility.hh
* \brief Defines simple utility functions for working with the
* Sick LMS 1xx laser range finder units.
*
* Code by Jason C. Derenick and Christopher R. Mansley.
* Contact jasonder(at)seas(dot)upenn(dot)edu
*
* The Sick LIDAR Matlab/C++ Toolbox
* Copyright (c) 2009, Jason C. Derenick and Christopher R. Mansley
* All rights reserved.
*
* This software is released under a BSD Open-Source License.
* See http://sicktoolbox.sourceforge.net
*/
/* Auto-generated header */
#include "SickConfig.hh"
/* Implementation Dependencies */
#include <sstream>
/**
* \def REVERSE_BYTE_ORDER_16
* \brief Reverses the byte order of the given 16 bit unsigned integer
*/
#define REVERSE_BYTE_ORDER_16( y ) ( ( ( y & 0x00FF ) << 8 ) | ( ( y & 0xFF00 ) >> 8 ) )
/**
* \def REVERSE_BYTE_ORDER_32
* \brief Reverses the byte order of the given 32 bit unsigned integer
*/
#define REVERSE_BYTE_ORDER_32( y ) ( ( ( y & 0x000000FF ) << 24 ) | ( ( y & 0x0000FF00 ) << 8 ) | ( ( y & 0x00FF0000 ) >> 8 ) | ( ( y & 0xFF000000 ) >> 24 ) )
/* Associate the namespace */
namespace SickToolbox {
#ifndef WORDS_BIGENDIAN
/* NOTE: The following functions are necessary since the Sick LD doesn't adopt the
* convention of converting from network byte order.
*/
/**
* \brief Converts host byte order (little-endian) to Sick LMS byte order (little-endian)
* \param value The 2-byte value to convert to little-endian
* \return Value in Sick LMS byte order (little-endian)
*/
inline uint16_t host_to_sick_lms_1xx_byte_order( uint16_t value ) {
return value;
}
/**
* \brief Converts host byte order (little-endian) to Sick LMS byte order (little-endian)
* \param value The 4-byte value to convert to little-endian
* \return Value in Sick LMS byte order (little-endian)
*/
inline uint32_t host_to_sick_lms_1xx_byte_order( uint32_t value ) {
return value;
}
/**
* \brief Converts Sick LMS byte order (little-endian) to host byte order (little-endian)
* \param value The 2-byte value to convert to little-endian
* \return Value in host byte order (little-endian)
*/
inline uint16_t sick_lms_1xx_to_host_byte_order( uint16_t value ) {
return value;
}
/**
* \brief Converts Sick LMS byte order (little-endian) to host byte order (little-endian)
* \param value The 4-byte value to convert to little-endian
* \return Value in host byte order (little-endian)
*/
inline uint32_t sick_lms_1xx_to_host_byte_order( uint32_t value ) {
return value;
}
#else // The host has a big-endian architecture
/**
* \brief Converts host byte order (big-endian) to Sick LMS byte order (little-endian)
* \param value The 2-byte value to convert to little-endian
* \return Value in Sick LMS byte order (little-endian)
*/
inline uint16_t host_to_sick_lms_1xx_byte_order( uint16_t value ) {
return REVERSE_BYTE_ORDER_16(value);
}
/**
* \brief Converts host byte order (big-endian) to Sick LMS byte order (little-endian)
* \param value The 4-byte value to convertto little-endian
* \return Value in Sick LMS byte order (little-endian)
*/
inline uint32_t host_to_sick_lms_1xx_byte_order( uint32_t value ) {
return REVERSE_BYTE_ORDER_32(value);
}
/**
* \brief Converts Sick LMS byte order (little-endian) to host byte order (big-endian)
* \param value The 2-byte value to convert to big-endian
* \return Value in host byte order (big-endian)
*/
inline uint16_t sick_lms_1xx_to_host_byte_order( uint16_t value ) {
return REVERSE_BYTE_ORDER_16(value);
}
/**
* \brief Converts Sick LMS byte order (little-endian) to host byte order (big-endian)
* \param value The 4-byte value to convert to big-endian
* \return Value in host byte order (big-endian)
*/
inline uint32_t sick_lms_1xx_to_host_byte_order( uint32_t value ) {
return REVERSE_BYTE_ORDER_32(value);
}
#endif /* _LITTLE_ENDIAN_HOST */
/*
* NOTE: Other utility functions can be defined here
*/
/**
* \brief Utility function for converting int to standard string
* \param value Integer to be converted
* \return String representing the given integer
*/
inline std::string int_to_str( const int value ) {
std::stringstream ss;
ss << value;
return ss.str();
}
} //namespace SickToolbox

View File

@ -0,0 +1,996 @@
/*!
* \file SickLMS2xx.hh
* \brief Definition of class SickLMS2xx.
* Code by Jason C. Derenick and Thomas H. Miller.
* Contact derenick(at)lehigh(dot)edu
*
* The Sick LIDAR Matlab/C++ Toolbox
* Copyright (c) 2008, Jason C. Derenick and Thomas H. Miller
* All rights reserved.
*
* This software is released under a BSD Open-Source License.
* See http://sicktoolbox.sourceforge.net
*/
#ifndef SICK_LMS_2XX_HH
#define SICK_LMS_2XX_HH
/* Implementation dependencies */
#include <string>
#include <iostream>
#include <termios.h>
#include "SickLIDAR.hh"
#include "SickException.hh"
#include "SickLMS2xxBufferMonitor.hh"
#include "SickLMS2xxMessage.hh"
/* Macro definitions */
#define DEFAULT_SICK_LMS_2XX_SICK_BAUD (B9600) ///< Initial baud rate of the LMS (whatever is set in flash)
#define DEFAULT_SICK_LMS_2XX_HOST_ADDRESS (0x80) ///< Client/host default serial address
#define DEFAULT_SICK_LMS_2XX_SICK_ADDRESS (0x00) ///< Sick LMS default serial address
#define DEFAULT_SICK_LMS_2XX_SICK_PASSWORD "SICK_LMS" ///< Password for entering installation mode
#define DEFAULT_SICK_LMS_2XX_SICK_MESSAGE_TIMEOUT (unsigned int)(1e6) ///< The max time to wait for a message reply (usecs)
#define DEFAULT_SICK_LMS_2XX_SICK_SWITCH_MODE_TIMEOUT (unsigned int)(3e6) ///< Can take the Sick LD up to 3 seconds to reply (usecs)
#define DEFAULT_SICK_LMS_2XX_SICK_MEAN_VALUES_MESSAGE_TIMEOUT (unsigned int)(15e6) ///< When using mean values, the Sick can sometimes take more than 10s to respond
#define DEFAULT_SICK_LMS_2XX_SICK_CONFIG_MESSAGE_TIMEOUT (unsigned int)(15e6) ///< The sick can take some time to respond to config commands (usecs)
#define DEFAULT_SICK_LMS_2XX_BYTE_INTERVAL (55) ///< Minimum time in microseconds between transmitted bytes
#define DEFAULT_SICK_LMS_2XX_NUM_TRIES (3) ///< The max number of tries before giving up on a request
/* Associate the namespace */
namespace SickToolbox {
/*!
* \brief A general class for interfacing w/ SickLMS2xx2xx laser range finders
*
* This class implements the basic telegram protocol for SickLMS2xx2xx range finders.
* It allows the setting of such parameters as angular resolution, fov, etc...
*/
class SickLMS2xx : public SickLIDAR< SickLMS2xxBufferMonitor, SickLMS2xxMessage >
{
public:
/** Define the maximum number of measurements */
static const uint16_t SICK_MAX_NUM_MEASUREMENTS = 721; ///< Maximum number of measurements returned by the Sick LMS
/*!
* \enum sick_lms_2xx_type_t
* \brief Defines the Sick LMS 2xx types.
* This enum lists all of the supported Sick LMS models.
*/
enum sick_lms_2xx_type_t {
/* Supported 200 models */
SICK_LMS_TYPE_200_30106, ///< Sick LMS type 200-30106
/* Supported 211 models */
SICK_LMS_TYPE_211_30106, ///< Sick LMS type 211-30106
SICK_LMS_TYPE_211_30206, ///< Sick LMS type 211-30206
SICK_LMS_TYPE_211_S07, ///< Sick LMS type 211-S07
SICK_LMS_TYPE_211_S14, ///< Sick LMS type 211-S14
SICK_LMS_TYPE_211_S15, ///< Sick LMS type 211-S15
SICK_LMS_TYPE_211_S19, ///< Sick LMS type 211-S19
SICK_LMS_TYPE_211_S20, ///< Sick LMS type 211-S20
/* Supported 220 models */
SICK_LMS_TYPE_220_30106, ///< Sick LMS type 220-30106
/* Supported 221 models */
SICK_LMS_TYPE_221_30106, ///< Sick LMS type 221-30106
SICK_LMS_TYPE_221_30206, ///< Sick LMS type 221-30206
SICK_LMS_TYPE_221_S07, ///< Sick LMS type 221-S07
SICK_LMS_TYPE_221_S14, ///< Sick LMS type 221-S14
SICK_LMS_TYPE_221_S15, ///< Sick LMS type 221-S15
SICK_LMS_TYPE_221_S16, ///< Sick LMS type 221-S16
SICK_LMS_TYPE_221_S19, ///< Sick LMS type 221-S19
SICK_LMS_TYPE_221_S20, ///< Sick LMS type 221-S20
/* Supported 291 models */
SICK_LMS_TYPE_291_S05, ///< Sick LMS type 291-S05
SICK_LMS_TYPE_291_S14, ///< Sick LMS type 291-S14 (LMS Fast)
SICK_LMS_TYPE_291_S15, ///< Sick LMS type 291-S15
/* Any unknown model */
SICK_LMS_TYPE_UNKNOWN = 0xFF ///< Unknown sick type
};
/*!
* \enum sick_lms_2xx_variant_t
* \brief Defines the Sick LMS 2xx variant type.
*/
enum sick_lms_2xx_variant_t {
SICK_LMS_VARIANT_2XX_TYPE_6 = 0x00, ///< Standard LMS 2xx type 6 models
SICK_LMS_VARIANT_SPECIAL = 0x01, ///< Special models (i.e. LMS211-/221-S19/-S20
SICK_LMS_VARIANT_UNKNOWN = 0xFF ///< Unknown LMS variant
};
/*!
* \enum sick_lms_2xx_scan_angle_t
* \brief Defines the scan angle for the Sick LMS 2xx.
*/
enum sick_lms_2xx_scan_angle_t {
SICK_SCAN_ANGLE_90 = 90, ///< Scanning angle of 90 degrees
SICK_SCAN_ANGLE_100 = 100, ///< Scanning angle of 100 degrees
SICK_SCAN_ANGLE_180 = 180, ///< Scanning angle of 180 degrees
SICK_SCAN_ANGLE_UNKNOWN = 0xFF ///< Unknown scanning angle
};
/*!
* \enum sick_lms_2xx_scan_resolution_t
* \brief Defines the available resolution settings for the Sick LMS 2xx.
*/
enum sick_lms_2xx_scan_resolution_t {
SICK_SCAN_RESOLUTION_25 = 25, ///< 0.25 degree angular resolution
SICK_SCAN_RESOLUTION_50 = 50, ///< 0.50 degree angular resolution
SICK_SCAN_RESOLUTION_100 = 100, ///< 1.00 degree angular resolution
SICK_SCAN_RESOLUTION_UNKNOWN = 0xFF ///< Unknown angular resolution
};
/*!
* \enum sick_lms_2xx_measuring_units_t
* \brief Defines the available Sick LMS 2xx measured value units.
*/
enum sick_lms_2xx_measuring_units_t {
SICK_MEASURING_UNITS_CM = 0x00, ///< Measured values are in centimeters
SICK_MEASURING_UNITS_MM = 0x01, ///< Measured values are in milimeters
SICK_MEASURING_UNITS_UNKNOWN = 0xFF ///< Unknown units
};
/*!
* \enum sick_lms_2xx_sensitivity_t
* \brief Sick sensitivities. Only valid for Sick LMS 211/221/291!
*/
enum sick_lms_2xx_sensitivity_t {
SICK_SENSITIVITY_STANDARD = 0x00, ///< Standard sensitivity: 30m @ 10% reflectivity
SICK_SENSITIVITY_MEDIUM = 0x01, ///< Medium sensitivity: 25m @ 10% reflectivity
SICK_SENSITIVITY_LOW = 0x02, ///< Low sensitivity: 20m @ 10% reflectivity
SICK_SENSITIVITY_HIGH = 0x03, ///< High sensitivity: 42m @ 10% reflectivity
SICK_SENSITIVITY_UNKNOWN = 0xFF ///< Sensitivity unknown
};
/*!
* \enum sick_lms_2xx_peak_threshold_t
* \brief Sick peak threshold. Only valid for Sick LMS 200/220!
*/
enum sick_lms_2xx_peak_threshold_t {
SICK_PEAK_THRESHOLD_DETECTION_WITH_NO_BLACK_EXTENSION = 0x00, ///< Standard: peak threshold detection, no black extension
SICK_PEAK_THRESHOLD_DETECTION_WITH_BLACK_EXTENSION = 0x01, ///< Peak threshold detection, active black extension
SICK_PEAK_THRESHOLD_NO_DETECTION_WITH_NO_BLACK_EXTENSION = 0x02, ///< No peak threshold detection, no black extension
SICK_PEAK_THRESHOLD_NO_DETECTION_WITH_BLACK_EXTENSION = 0x03, ///< No peak threshold detection, active black extension
SICK_PEAK_THRESHOLD_UNKNOWN = 0xFF ///< Peak threshold unknown
};
/*!
* \enum sick_lms_2xx_status_t
* \brief Defines the status of the Sick LMS 2xx unit.
*/
enum sick_lms_2xx_status_t {
SICK_STATUS_OK = 0x00, ///< LMS is OK
SICK_STATUS_ERROR = 0x01, ///< LMS has encountered an error
SICK_STATUS_UNKNOWN = 0xFF ///< Unknown LMS status
};
/*!
* \enum sick_lms_2xx_measuring_mode_t
* \brief Defines the measurment modes supported by Sick LMS 2xx.
*/
enum sick_lms_2xx_measuring_mode_t {
SICK_MS_MODE_8_OR_80_FA_FB_DAZZLE = 0x00, ///< Measurement range 8m/80m; fields A,B and Dazzle (Default)
SICK_MS_MODE_8_OR_80_REFLECTOR = 0x01, ///< Measurement range 8/80m; reflector bits in 8 levels
SICK_MS_MODE_8_OR_80_FA_FB_FC = 0x02, ///< Measurement range 8/80m; fields A,B, and C
SICK_MS_MODE_16_REFLECTOR = 0x03, ///< Measurement range 16m; reflector bits in 4 levels
SICK_MS_MODE_16_FA_FB = 0x04, ///< Measurement range 16m; fields A and B
SICK_MS_MODE_32_REFLECTOR = 0x05, ///< Measurement range 32m; reflector bit in 2 levels
SICK_MS_MODE_32_FA = 0x06, ///< Measurement range 32m; field A
SICK_MS_MODE_32_IMMEDIATE = 0x0F, ///< Measurement range 32m; immediate data transmission, no flags
SICK_MS_MODE_REFLECTIVITY = 0x3F, ///< Sick LMS 2xx returns reflectivity (echo amplitude) values instead of range measurements
SICK_MS_MODE_UNKNOWN = 0xFF ///< Unknown range
};
/*!
* \enum sick_lms_2xx_operating_mode_t
* \brief Defines the operating modes supported by Sick LMS 2xx.
* See page 41 of the LMS 2xx telegram manual for additional descriptions of these modes.
*/
enum sick_lms_2xx_operating_mode_t {
SICK_OP_MODE_INSTALLATION = 0x00, ///< Installation mode for writing EEPROM
SICK_OP_MODE_DIAGNOSTIC = 0x10, ///< Diagnostic mode for testing purposes
SICK_OP_MODE_MONITOR_STREAM_MIN_VALUE_FOR_EACH_SEGMENT = 0x20, ///< Streams minimum measured values for each segement
SICK_OP_MODE_MONITOR_TRIGGER_MIN_VALUE_ON_OBJECT = 0x21, ///< Sends the min measured values when object is detected
SICK_OP_MODE_MONITOR_STREAM_MIN_VERT_DIST_TO_OBJECT = 0x22, ///< Streams min "vertical distance" to objects
SICK_OP_MODE_MONITOR_TRIGGER_MIN_VERT_DIST_TO_OBJECT = 0x23, ///< Sends min vertical distance to object when detected
SICK_OP_MODE_MONITOR_STREAM_VALUES = 0x24, ///< Streams all measured values in a scan
SICK_OP_MODE_MONITOR_REQUEST_VALUES = 0x25, ///< Sends measured range values on request (i.e. when polled)
SICK_OP_MODE_MONITOR_STREAM_MEAN_VALUES = 0x26, ///< Streams mean values from a sample size of n consecutive scans
SICK_OP_MODE_MONITOR_STREAM_VALUES_SUBRANGE = 0x27, ///< Streams data from given subrange
SICK_OP_MODE_MONITOR_STREAM_MEAN_VALUES_SUBRANGE = 0x28, ///< Streams mean values over requested subrange
SICK_OP_MODE_MONITOR_STREAM_VALUES_WITH_FIELDS = 0x29, ///< Streams measured values with associated flags
SICK_OP_MODE_MONITOR_STREAM_VALUES_FROM_PARTIAL_SCAN = 0x2A, ///< Streams measured values of partial scan directly after measurement
SICK_OP_MODE_MONITOR_STREAM_RANGE_AND_REFLECT_FROM_PARTIAL_SCAN = 0x2B, ///< Streams range and intensity from n partial scans
SICK_OP_MODE_MONITOR_STREAM_MIN_VALUES_FOR_EACH_SEGMENT_SUBRANGE = 0x2C, ///< Streams minimum measured values for each segment in a sub-range
SICK_OP_MODE_MONITOR_NAVIGATION = 0x2E, ///< Sick outputs navigation data records
SICK_OP_MODE_MONITOR_STREAM_RANGE_AND_REFLECT = 0x50, ///< Streams measured range from a scan and sub-range of reflectivity values
SICK_OP_MODE_UNKNOWN = 0xFF ///< Unknown operating mode
};
/*!
* \enum sick_lms_2xx_baud_t
* \brief Defines available Sick LMS 2xx baud rates
*/
enum sick_lms_2xx_baud_t {
SICK_BAUD_9600 = 0x42, ///< 9600 baud
SICK_BAUD_19200 = 0x41, ///< 19200 baud
SICK_BAUD_38400 = 0x40, ///< 38400 baud
SICK_BAUD_500K = 0x48, ///< 500000 baud
SICK_BAUD_UNKNOWN = 0xFF ///< Unknown baud rate
};
/** Define Sick LMS 2xx availability levels */
static const uint8_t SICK_FLAG_AVAILABILITY_DEFAULT = 0x00; ///< Availability unspecified
static const uint8_t SICK_FLAG_AVAILABILITY_HIGH = 0x01; ///< Highest availability (comparable to LMS types 1 to 5)
static const uint8_t SICK_FLAG_AVAILABILITY_REAL_TIME_INDICES = 0x02; ///< Send real-time indices
static const uint8_t SICK_FLAG_AVAILABILITY_DAZZLE_NO_EFFECT = 0x04; ///< Dazzle evalutation has no effect on switching outputs
/*!
* \struct sick_lms_2xx_operating_status_tag
* \brief A structure for aggregating the data that
* collectively defines the operating status
* of the device.
*/
/*!
* \typedef sick_lms_2xx_operating_status_t
* \brief Adopt c-style convention
*/
typedef struct sick_lms_2xx_operating_status_tag {
uint16_t sick_scan_angle; ///< Sick scanning angle (deg)
uint16_t sick_scan_resolution; ///< Sick angular resolution (1/100 deg)
uint16_t sick_num_motor_revs; ///< Sick number of motor revs
uint8_t sick_operating_mode; ///< Sick operating mode
uint8_t sick_measuring_mode; ///< Sick measuring mode
uint8_t sick_laser_mode; ///< Sick laser is on/off
uint8_t sick_device_status; ///< Sick device status {ok,error}
uint8_t sick_measuring_units; ///< Sick measuring units {cm,mm}
uint8_t sick_address; ///< Sick device address
uint8_t sick_variant; ///< Sick variant {special,standard}
} sick_lms_2xx_operating_status_t;
/*!
* \struct sick_lms_2xx_software_status_tag
* \brief A structure for aggregating the data that
* collectively defines the system software
* for the Sick LMS 2xx unit.
*/
/*!
* \typedef sick_lms_2xx_software_status_t
* \brief Adopt c-style convention
*/
typedef struct sick_lms_2xx_software_status_tag {
uint8_t sick_system_software_version[8]; ///< Sick system software version
uint8_t sick_prom_software_version[8]; ///< Sick boot prom software version
} sick_lms_2xx_software_status_t;
/*!
* \struct sick_lms_2xx_restart_status_tag
* \brief A structure for aggregating the data that
* collectively defines the system restart
* config for the Sick LMS 2xx unit
*/
typedef struct sick_lms_2xx_restart_status_tag {
uint16_t sick_restart_time; ///< Sick restart time
uint8_t sick_restart_mode; ///< Sick restart mode
} sick_lms_2xx_restart_status_t;
/*!
* \struct sick_lms_2xx_pollution_status_tag
* \brief A structure for aggregating the data that
* collectively defines the pollution values
* and settings for the device
*/
/*!
* \typedef sick_lms_2xx_pollution_status_t
* \brief Adopt c-style convention
*/
typedef struct sick_lms_2xx_pollution_status_tag {
uint16_t sick_pollution_vals[8]; ///< Calibrating the pollution channels
uint16_t sick_pollution_calibration_vals[8]; ///< Calibrating the pollution channel values
uint16_t sick_reference_pollution_vals[4]; ///< Reference pollution values
uint16_t sick_reference_pollution_calibration_vals[4]; ///< Reference pollution calibration values
} sick_lms_2xx_pollution_status_t;
/*!
* \struct sick_lms_2xx_signal_status_tag
* \brief A structure for aggregating the data that
* collectively define the signal config and
* status.
*/
/*!
* \typedef sick_lms_2xx_signal_status_t
* \brief Adopt c-style convention
*/
typedef struct sick_lms_2xx_signal_status_tag {
uint16_t sick_reference_scale_1_dark_100; ///< Receive signal amplitude in ADC incs when reference signal is switched off (Signal 1, Dark 100%)
uint16_t sick_reference_scale_2_dark_100; ///< Receive signal amplitude in ADC incs when reference signal is switched off (Signal 2, Dark 100%)
uint16_t sick_reference_scale_1_dark_66; ///< Receive signal amplitude in ADC incs when reference signal is switched off (Signal 1, Dark 66%)
uint16_t sick_reference_scale_2_dark_66; ///< Receive signal amplitude in ADC incs when reference signal is switched off (Signal 2, Dark 66%)
uint16_t sick_signal_amplitude; ///< Laser power in % of calibration value
uint16_t sick_current_angle; ///< Angle used for power measurement
uint16_t sick_peak_threshold; ///< Peak threshold in ADC incs for power measurement
uint16_t sick_angle_of_measurement; ///< Angles used to reference target for power measurement
uint16_t sick_signal_amplitude_calibration_val; ///< Calibration of the laser power
uint16_t sick_stop_threshold_target_value; ///< Target value of the stop threshold in ADC incs
uint16_t sick_peak_threshold_target_value; ///< Target value of the peak threshold in ADC incs
uint16_t sick_stop_threshold_actual_value; ///< Actual value of the stop threshold in ADC incs
uint16_t sick_peak_threshold_actual_value; ///< Actual value of the peak threshold in ADC incs
uint16_t sick_reference_target_single_measured_vals; ///< Reference target "single measured values." Low byte: Current number of filtered single measured values. High byte: Max num filtered single measured value since power-on.
uint16_t sick_reference_target_mean_measured_vals; ///< Reference target "mean measured values." Low byte: Current number of filtered mean measured values. High byte: Max num filtered mean measured value since power-on.
} sick_lms_2xx_signal_status_t;
/*!
* \struct sick_lms_2xx_field_status_tag
* \brief A structure for aggregating the data that
* collectively define the signal config and
* status.
*/
/*!
* \typedef sick_lms_2xx_field_status_t
* \brief Adopt c-style convention
*/
typedef struct sick_lms_2xx_field_status_tag {
uint8_t sick_field_evaluation_number; ///< Number of evaluations when the field is infirnged (lies in [1,125])
uint8_t sick_field_set_number; ///< Active field set number
uint8_t sick_multiple_evaluation_offset_field_2; ///< Offset for multiple evaluation of field set 2 (see page 105 of telegram listing)
} sick_lms_2xx_field_status_t;
/*!
* \struct sick_lms_2xx_baud_status_tag
* \brief A structure for aggregating the data that
* collectively define the baud config.
*/
/*!
* \typedef sick_lms_2xx_baud_status_t
* \brief Adopt c-style convention
*/
typedef struct sick_lms_2xx_baud_status_tag {
uint16_t sick_baud_rate; ///< Sick baud as reported by the device
uint8_t sick_permanent_baud_rate; ///< 0 - When power is switched on baud rate is 9600/1 - configured transmission rate is used
} sick_lms_2xx_baud_status_t;
/*!
* \struct sick_lms_2xx_device_config_tag
* \brief A structure for aggregating the data that
* collectively defines the Sick's config.
*/
/*!
* \typedef sick_lms_2xx_device_config_t
* \brief Adopt c-style convention
*/
typedef struct sick_lms_2xx_device_config_tag {
uint16_t sick_blanking; ///< Maximum diameter of objects that are not to be detected (units cm)
uint16_t sick_fields_b_c_restart_times; ///< Restart times for fields B and C
uint16_t sick_dazzling_multiple_evaluation; ///< Number of scans that take place before LMS switches the outputs (only applies to availability level 1)
uint8_t sick_peak_threshold; ///< Peak threshold/black correction (This applies to Sick LMS 200/220 models, when Sick LMS 211/221/291 models are used, this value is sensitivity)
uint8_t sick_stop_threshold; ///< Stop threshold in mV (This only applies to Sick LMS 200/220 models)
uint8_t sick_availability_level; ///< Availability level of the Sick LMS
uint8_t sick_measuring_mode; ///< Measuring mode of the device
uint8_t sick_measuring_units; ///< Measured value and field value units
uint8_t sick_temporary_field; ///< Indicates whether the temporary field is being used
uint8_t sick_subtractive_fields; ///< Indicates whether fields A and B are subtractive
uint8_t sick_multiple_evaluation; ///< Multiple evalutation of scan data
uint8_t sick_restart; ///< Indicates the restart level of the device
uint8_t sick_restart_time; ///< Inidicates the restart time of the device
uint8_t sick_multiple_evaluation_suppressed_objects; ///< Multiple evaluation for objects less than the blanking size
uint8_t sick_contour_a_reference; ///< Contour function A
uint8_t sick_contour_a_positive_tolerance_band; ///< When contour function is active the positive tolerance is defined in (cm)
uint8_t sick_contour_a_negative_tolerance_band; ///< When contour function is active the negative tolerance is defined in (cm)
uint8_t sick_contour_a_start_angle; ///< When contour function is active the start angle of area to be monitored is defined (deg)
uint8_t sick_contour_a_stop_angle; ///< When contour function is active the stop angle of area to be monitored is defined (deg)
uint8_t sick_contour_b_reference; ///< Contour function B
uint8_t sick_contour_b_positive_tolerance_band; ///< When contour function is active the positive tolerance is defined in (cm)
uint8_t sick_contour_b_negative_tolerance_band; ///< When contour function is active the negative tolerance is defined in (cm) uint8_t sick_contour_b_start_angle; ///< When contour function is active the start angle of area to be monitored is defined (deg)
uint8_t sick_contour_b_start_angle; ///< When contour function is active the start angle of area to be monitored is defined (deg)
uint8_t sick_contour_b_stop_angle; ///< When contour function is active the stop angle of area to be monitored is defined (deg)
uint8_t sick_contour_c_reference; ///< Contour function C
uint8_t sick_contour_c_positive_tolerance_band; ///< When contour function is active the positive tolerance is defined in (cm)
uint8_t sick_contour_c_negative_tolerance_band; ///< When contour function is active the negative tolerance is defined in (cm)
uint8_t sick_contour_c_start_angle; ///< When contour function is active the start angle of area to be monitored is defined (deg)
uint8_t sick_contour_c_stop_angle; ///< When contour function is active the stop angle of area to be monitored is defined (deg)
uint8_t sick_pixel_oriented_evaluation; ///< Pixel oriented evaluation
uint8_t sick_single_measured_value_evaluation_mode; ///< Multiple evaluation (min: 1, max: 125)
} sick_lms_2xx_device_config_t;
/*!
* \struct sick_lms_2xx_scan_profile_b0_tag
* \brief A structure for aggregating the data that
* define a scan profile obtained from reply
* B0 (See page 49 Telegram listing)
*/
/*!
* \typedef sick_lms_2xx_scan_profile_b0_t
* \brief Adopt c-style convention
*/
typedef struct sick_lms_2xx_scan_profile_b0_tag {
uint16_t sick_num_measurements; ///< Number of measurements
uint16_t sick_measurements[SICK_MAX_NUM_MEASUREMENTS]; ///< Range/reflectivity measurement buffer
uint8_t sick_field_a_values[SICK_MAX_NUM_MEASUREMENTS]; ///< Reflects the Field A bit value returned w/ range measurement
uint8_t sick_field_b_values[SICK_MAX_NUM_MEASUREMENTS]; ///< Reflects the Field B but value returned w/ range measurement
uint8_t sick_field_c_values[SICK_MAX_NUM_MEASUREMENTS]; ///< Reflects the Field C (or dazzle - depending upon sensor mode) value returned w/ range measurement
uint8_t sick_telegram_index; ///< Telegram index modulo 256
uint8_t sick_real_time_scan_index; ///< If real-time scan indices are requested, this value is set (modulo 256)
uint8_t sick_partial_scan_index; ///< Indicates the start angle of the scan (This is useful for partial scans)
} sick_lms_2xx_scan_profile_b0_t;
/*!
* \struct sick_lms_2xx_scan_profile_b6_tag
* \brief A structure for aggregating the data that
* define a scan profile obtained from reply
* B6 (See page 61 Telegram listing)
*/
/*!
* \typedef sick_lms_2xx_scan_profile_b6_t
* \brief Adopt c-style convention
*/
typedef struct sick_lms_2xx_scan_profile_b6_tag {
uint16_t sick_num_measurements; ///< Number of measurements
uint16_t sick_measurements[SICK_MAX_NUM_MEASUREMENTS]; ///< Range/reflectivity measurement buffer
uint8_t sick_sample_size; ///< Number of scans used in computing the returned mean
uint8_t sick_telegram_index; ///< Telegram index modulo 256
uint8_t sick_real_time_scan_index; ///< If real-time scan indices are requested, this value is set (modulo 256)
} sick_lms_2xx_scan_profile_b6_t;
/*!
* \struct sick_lms_2xx_scan_profile_b7_tag
* \brief A structure for aggregating the data that
* define a scan profile obtained from reply
* B7 (See page 63 Telegram listing)
*/
/*!
* \typedef sick_lms_2xx_scan_profile_b7_t
* \brief Adopt c-style convention
*/
typedef struct sick_lms_2xx_scan_profile_b7_tag {
uint16_t sick_subrange_start_index; ///< Measurement subrange start index
uint16_t sick_subrange_stop_index; ///< Measurement subrange stop index
uint16_t sick_num_measurements; ///< Number of measurements
uint16_t sick_measurements[SICK_MAX_NUM_MEASUREMENTS]; ///< Range/reflectivity measurement buffer
uint8_t sick_field_a_values[SICK_MAX_NUM_MEASUREMENTS]; ///< Reflects the Field A bit value returned w/ range measurement
uint8_t sick_field_b_values[SICK_MAX_NUM_MEASUREMENTS]; ///< Reflects the Field B but value returned w/ range measurement
uint8_t sick_field_c_values[SICK_MAX_NUM_MEASUREMENTS]; ///< Reflects the Field C (or dazzle - depending upon sensor mode) value returned w/ range measurement
uint8_t sick_telegram_index; ///< Telegram index modulo 256
uint8_t sick_real_time_scan_index; ///< If real-time scan indices are requested, this value is set (modulo 256)
uint8_t sick_partial_scan_index; ///< Indicates the start angle of the scan (This is useful for partial scans)
} sick_lms_2xx_scan_profile_b7_t;
/*!
* \struct sick_lms_2xx_scan_profile_bf_tag
* \brief A structure for aggregating the data that
* define a scan profile obtained from reply
* BF (See page 71 Telegram listing)
*/
/*!
* \typedef sick_lms_2xx_scan_profile_bf_t
* \brief Adopt c-style convention
*/
typedef struct sick_lms_2xx_scan_profile_bf_tag {
uint16_t sick_subrange_start_index; ///< Measurement subrange start index
uint16_t sick_subrange_stop_index; ///< Measurement subrange stop index
uint16_t sick_num_measurements; ///< Number of measurements
uint16_t sick_measurements[SICK_MAX_NUM_MEASUREMENTS]; ///< Range/reflectivity measurement buffer
uint8_t sick_sample_size; ///< Number of scans used in computing the returned mean
uint8_t sick_telegram_index; ///< Telegram index modulo 256
uint8_t sick_real_time_scan_index; ///< If real-time scan indices are requested, this value is set (modulo 256)
} sick_lms_2xx_scan_profile_bf_t;
/*!
* \struct sick_lms_2xx_scan_profile_c4_tag
* \brief A structure for aggregating the data that
* define a scan profile obtained from reply
* B4 (See page 79 Telegram listing)
*/
/*!
* \typedef sick_lms_2xx_scan_profile_c4_t
* \brief Adopt c-style convention
*/
typedef struct sick_lms_2xx_scan_profile_c4_tag {
uint16_t sick_num_range_measurements; ///< Number of range measurements
uint16_t sick_num_reflect_measurements; ///< Number of reflectivity measurements
uint16_t sick_range_measurements[SICK_MAX_NUM_MEASUREMENTS]; ///< Range measurement buffer
uint16_t sick_reflect_measurements[SICK_MAX_NUM_MEASUREMENTS]; ///< Reflect measurements buffer
uint16_t sick_reflect_subrange_start_index; ///< Start index of the measured reflectivity value subrange
uint16_t sick_reflect_subrange_stop_index; ///< Stop index of the measured reflectivity value subrange
uint8_t sick_field_a_values[SICK_MAX_NUM_MEASUREMENTS]; ///< Reflects the Field A bit value returned w/ range measurement
uint8_t sick_field_b_values[SICK_MAX_NUM_MEASUREMENTS]; ///< Reflects the Field B but value returned w/ range measurement
uint8_t sick_field_c_values[SICK_MAX_NUM_MEASUREMENTS]; ///< Reflects the Field C (or dazzle - depending upon sensor mode) value returned w/ range measurement
uint8_t sick_telegram_index; ///< Telegram index modulo 256
uint8_t sick_real_time_scan_index; ///< If real-time scan indices are requested, this value is set (modulo 256)
} sick_lms_2xx_scan_profile_c4_t;
/** Constructor */
SickLMS2xx( const std::string sick_device_path );
/** Destructor */
~SickLMS2xx( );
/** Initializes the Sick */
void Initialize( const sick_lms_2xx_baud_t desired_baud_rate, const uint32_t delay = 0 )
throw( SickConfigException, SickTimeoutException, SickIOException, SickThreadException);
/** Uninitializes the Sick */
void Uninitialize( ) throw( SickConfigException, SickTimeoutException, SickIOException, SickThreadException );
/** Gets the Sick LMS 2xx device path */
std::string GetSickDevicePath( ) const;
/** Gets the Sick LMS 2xx device type */
sick_lms_2xx_type_t GetSickType( ) const throw( SickConfigException );
/** Gets the scan angle currently being used by the device */
double GetSickScanAngle( ) const throw( SickConfigException );
/** Gets the scan resolution currently being used by the device */
double GetSickScanResolution( ) const throw( SickConfigException );
/** Set the measurement units of the device (in EEPROM) */
void SetSickMeasuringUnits( const sick_lms_2xx_measuring_units_t sick_units = SICK_MEASURING_UNITS_MM )
throw( SickConfigException, SickTimeoutException, SickIOException, SickThreadException );
/** Get the current measurement units of the device */
SickLMS2xx::sick_lms_2xx_measuring_units_t GetSickMeasuringUnits( ) const throw( SickConfigException );
/** Sets the sensitivity value for the device (in EEPROM). NOTE: Only applies to LMS 211/221/291 models. */
void SetSickSensitivity( const sick_lms_2xx_sensitivity_t sick_sensitivity = SICK_SENSITIVITY_STANDARD )
throw( SickConfigException, SickTimeoutException, SickIOException, SickThreadException );
/** Get the current Sick LMS 2xx sensitivity level. NOTE: Only applies to LMS 211/221/291 models. */
sick_lms_2xx_sensitivity_t GetSickSensitivity( ) const throw( SickConfigException );
/** Sets the peak threshold mode for the device (in EEPROM). NOTE: Only applies to LMS 200/220 models */
void SetSickPeakThreshold( const sick_lms_2xx_peak_threshold_t sick_peak_threshold = SICK_PEAK_THRESHOLD_DETECTION_WITH_NO_BLACK_EXTENSION )
throw( SickConfigException, SickTimeoutException, SickIOException, SickThreadException );
/** Get the current Sick LMS 2xx sensitivity level. NOTE: Only applies to LMS 211/221/291 models. */
sick_lms_2xx_peak_threshold_t GetSickPeakThreshold( ) const throw( SickConfigException );;
/** Sets the measuring mode for the device (in EEPROM). See page 98 of the telegram listing for more details. */
void SetSickMeasuringMode( const sick_lms_2xx_measuring_mode_t sick_measuring_mode = SICK_MS_MODE_8_OR_80_FA_FB_DAZZLE )
throw( SickConfigException, SickTimeoutException, SickIOException, SickThreadException );
/** Get the current Sick LMS 2xx measuring mode */
sick_lms_2xx_measuring_mode_t GetSickMeasuringMode( ) const throw( SickConfigException );
/** Get the current Sick LMS 2xx operating mode */
sick_lms_2xx_operating_mode_t GetSickOperatingMode( ) const throw( SickConfigException );
/** Sets the availability of the device (in EEPROM). See page 98 of the telegram listing for more details. */
void SetSickAvailability( const uint8_t sick_availability_flags = SICK_FLAG_AVAILABILITY_DEFAULT )
throw( SickConfigException, SickTimeoutException, SickIOException, SickThreadException );
/** Gets the current availability flags for the device */
uint8_t GetSickAvailability( ) const throw( SickConfigException );
/** Sets the variant type for the device (in EEPROM) */
void SetSickVariant( const sick_lms_2xx_scan_angle_t scan_angle, const sick_lms_2xx_scan_resolution_t scan_resolution )
throw( SickConfigException, SickTimeoutException, SickIOException, SickThreadException);
/** Gets measurement data from the Sick. NOTE: Data can be either range or reflectivity given the Sick mode. */
void GetSickScan( unsigned int * const measurement_values,
unsigned int & num_measurement_values,
unsigned int * const sick_field_a_values = NULL,
unsigned int * const sick_field_b_values = NULL,
unsigned int * const sick_field_c_values = NULL,
unsigned int * const sick_telegram_index = NULL,
unsigned int * const sick_real_time_scan_index = NULL ) throw( SickConfigException, SickTimeoutException, SickIOException, SickThreadException);
/** Gets range and reflectivity data from the Sick. NOTE: This only applies to Sick LMS 211/221/291-S14! */
void GetSickScan( unsigned int * const range_values,
unsigned int * const reflect_values,
unsigned int & num_range_measurements,
unsigned int & num_reflect_measurements,
unsigned int * const sick_field_a_values = NULL,
unsigned int * const sick_field_b_values = NULL,
unsigned int * const sick_field_c_values = NULL,
unsigned int * const sick_telegram_index = NULL,
unsigned int * const sick_real_time_scan_index = NULL ) throw( SickConfigException, SickTimeoutException, SickIOException, SickThreadException);
/** Gets measurement data from the Sick. NOTE: Data can be either range or reflectivity given the Sick mode. */
void GetSickScanSubrange( const uint16_t sick_subrange_start_index,
const uint16_t sick_subrange_stop_index,
unsigned int * const measurement_values,
unsigned int & num_measurement_values,
unsigned int * const sick_field_a_values = NULL,
unsigned int * const sick_field_b_values = NULL,
unsigned int * const sick_field_c_values = NULL,
unsigned int * const sick_telegram_index = NULL,
unsigned int * const sick_real_time_scan_index = NULL ) throw( SickConfigException, SickTimeoutException, SickIOException, SickThreadException);
/** Gets partial scan measurements from the Sick LMS 2xx. NOTE: Data can be either range or reflectivity depending upon the given Sick mode. */
void GetSickPartialScan( unsigned int * const measurement_values,
unsigned int & num_measurement_values,
unsigned int & partial_scan_index,
unsigned int * const sick_field_a_values = NULL,
unsigned int * const sick_field_b_values = NULL,
unsigned int * const sick_field_c_values = NULL,
unsigned int * const sick_telegram_index = NULL,
unsigned int * const sick_real_time_scan_index = NULL ) throw( SickConfigException, SickTimeoutException, SickIOException, SickThreadException);
/** Gets mean measured values from the Sick LMS */
void GetSickMeanValues( const uint8_t sick_sample_size,
unsigned int * const measurement_values,
unsigned int & num_measurement_values,
unsigned int * const sick_telegram_index = NULL,
unsigned int * const sick_real_time_index = NULL ) throw( SickConfigException, SickTimeoutException, SickIOException, SickThreadException );
/** Gets mean measured values from the Sick LMS */
void GetSickMeanValuesSubrange( const uint8_t sick_sample_size,
const uint16_t sick_subrange_start_index,
const uint16_t sick_subrange_stop_index,
unsigned int * const measurement_values,
unsigned int & num_measurement_values,
unsigned int * const sick_telegram_index = NULL,
unsigned int * const sick_real_time_index = NULL ) throw( SickConfigException, SickTimeoutException, SickIOException, SickThreadException );
/** Acquire the Sick LMS status */
sick_lms_2xx_status_t GetSickStatus( ) throw( SickConfigException, SickTimeoutException, SickIOException, SickThreadException );
/** Indicates whether the Sick is an LMS Fast */
bool IsSickLMS2xxFast( ) const throw( SickConfigException );
/** Resets Sick LMS field values */
void ResetSick( ) throw( SickConfigException, SickTimeoutException, SickIOException, SickThreadException );
/** Get Sick status as a string */
std::string GetSickStatusAsString( ) const;
/** Get Sick software info as a string */
std::string GetSickSoftwareVersionAsString( ) const;
/** Get Sick config as a string */
std::string GetSickConfigAsString( ) const;
/** Print the Sick LMS status */
void PrintSickStatus( ) const;
/** Print the Sick LMS software versions */
void PrintSickSoftwareVersion( ) const;
/** Print the Sick LMS configuration */
void PrintSickConfig( ) const;
/*
* NOTE: The following methods are given to make working with our
* predefined types a bit more manageable.
*/
/** Converts the LMS's type to a corresponding string */
static std::string SickTypeToString( const sick_lms_2xx_type_t sick_type );
/** A utility function for converting integers to lms_sick_scan_angle_t */
static sick_lms_2xx_scan_angle_t IntToSickScanAngle( const int scan_angle_int );
/** A utility function for converting ints to lms_sick_scan_resolution_t */
static sick_lms_2xx_scan_resolution_t IntToSickScanResolution( const int scan_resolution_int );
/** A utility function for converting doubles to lms_sick_scan_resolution_t */
static sick_lms_2xx_scan_resolution_t DoubleToSickScanResolution( const double scan_resolution_double );
/** Converts the given bad, returns a string representing that baud rate. */
static std::string SickBaudToString( const sick_lms_2xx_baud_t baud_rate );
/** A utility function for converting integers to lms_baud_t */
static sick_lms_2xx_baud_t IntToSickBaud( const int baud_int );
/** A utility function for converting baud strings to lms_baud_t */
static sick_lms_2xx_baud_t StringToSickBaud( const std::string baud_str );
/** Converts the LMS's status to a corresponding string */
static std::string SickStatusToString( const sick_lms_2xx_status_t sick_status );
/** Converts the LMS's measuring mode to a corresponding string */
static std::string SickMeasuringModeToString( const sick_lms_2xx_measuring_mode_t sick_measuring_mode );
/** Converts the LMS's measuring mode to a corresponding string */
static std::string SickOperatingModeToString( const sick_lms_2xx_operating_mode_t sick_operating_mode );
/** Converts the LMS's sensitivity to string */
static std::string SickSensitivityToString( const sick_lms_2xx_sensitivity_t sick_sensitivity );
/** Converts the LMS's peak threshold to string */
static std::string SickPeakThresholdToString( const sick_lms_2xx_peak_threshold_t sick_peak_threshold );
/** Converts the LMS's measuring units to a corresponding string */
static std::string SickMeasuringUnitsToString( const sick_lms_2xx_measuring_units_t sick_units );
protected:
/** A path to the device at which the sick can be accessed. */
std::string _sick_device_path;
/** The baud rate at which to communicate with the Sick */
sick_lms_2xx_baud_t _curr_session_baud;
/** The desired baud rate for communicating w/ the Sick */
sick_lms_2xx_baud_t _desired_session_baud;
/** A string representing the type of device */
sick_lms_2xx_type_t _sick_type;
/** The operating parameters of the device */
sick_lms_2xx_operating_status_t _sick_operating_status;
/** The current software version being run on the device */
sick_lms_2xx_software_status_t _sick_software_status;
/** The restart configuration of the device */
sick_lms_2xx_restart_status_t _sick_restart_status;
/** The pollution measurement status */
sick_lms_2xx_pollution_status_t _sick_pollution_status;
/** The signal status of the device */
sick_lms_2xx_signal_status_t _sick_signal_status;
/** The field configuration for the device */
sick_lms_2xx_field_status_t _sick_field_status;
/** The baud configuration of the device */
sick_lms_2xx_baud_status_t _sick_baud_status;
/** The device configuration for the Sick */
sick_lms_2xx_device_config_t _sick_device_config;
/** Used when the device is streaming mean values */
uint8_t _sick_mean_value_sample_size;
/** Used when the device is streaming a scan subrange */
uint16_t _sick_values_subrange_start_index;
/** Used when the device is streaming a scan subrange */
uint16_t _sick_values_subrange_stop_index;
/** Stores information about the original terminal settings */
struct termios _old_term;
/** Opens the terminal for serial communication. */
void _setupConnection() throw( SickIOException, SickThreadException );
void _setupConnection(const uint32_t delay ) throw( SickIOException, SickThreadException );
/** Closes the serial communication terminal. */
void _teardownConnection( ) throw( SickIOException );
/** Sends a message to the LMS and get the expected reply using th 0x80 rule. @todo Check difference in comments? */
void _sendMessageAndGetReply( const SickLMS2xxMessage &sick_send_message,
SickLMS2xxMessage &sick_recv_message,
const unsigned int timeout_value,
const unsigned int num_tries ) throw( SickIOException, SickThreadException, SickTimeoutException );
/** Sends a message to the LMS and get the expected reply using th 0x80 rule. @todo Check difference in comments? */
void _sendMessageAndGetReply( const SickLMS2xxMessage &sick_send_message,
SickLMS2xxMessage &sick_recv_message,
const uint8_t reply_code,
const unsigned int timeout_value,
const unsigned int num_tries ) throw( SickIOException, SickThreadException, SickTimeoutException );
/** Flushes the terminal I/O buffers */
void _flushTerminalBuffer( ) throw ( SickThreadException );
/** Sets the baud rate for communication with the LMS. */
void _setSessionBaud( const sick_lms_2xx_baud_t baud_rate ) throw( SickIOException, SickThreadException, SickTimeoutException );
/** Tests communication wit the LMS at a particular baud rate. */
bool _testSickBaud( const sick_lms_2xx_baud_t baud_rate ) throw( SickIOException, SickThreadException );
/** Changes the terminal's baud rate. */
void _setTerminalBaud( const sick_lms_2xx_baud_t sick_baud ) throw( SickIOException, SickThreadException );
/** Gets the type of Sick LMS */
void _getSickType( ) throw( SickTimeoutException, SickIOException, SickThreadException );
/** Gets the current Sick configuration settings */
void _getSickConfig( ) throw( SickTimeoutException, SickIOException, SickThreadException );
/** Sets the Sick configuration in flash */
void _setSickConfig( const sick_lms_2xx_device_config_t &sick_config ) throw( SickConfigException, SickTimeoutException, SickIOException, SickThreadException );
/** Gets the status of the LMS */
void _getSickStatus( ) throw( SickTimeoutException, SickIOException, SickThreadException );
/** Gets the error status of the Sick LMS */
void _getSickErrors( unsigned int * const num_sick_errors = NULL,
uint8_t * const error_type_buffer = NULL,
uint8_t * const error_num_buffer = NULL ) throw( SickTimeoutException, SickIOException, SickThreadException );
/** Switch Sick LMS to installation mode */
void _setSickOpModeInstallation( )
throw( SickConfigException, SickTimeoutException, SickIOException, SickThreadException);
/** Switch Sick LMS to diagnostic mode */
void _setSickOpModeDiagnostic( )
throw( SickConfigException, SickTimeoutException, SickIOException, SickThreadException);
/** Switch Sick LMS to monitor mode (request range data) */
void _setSickOpModeMonitorRequestValues( )
throw( SickConfigException, SickTimeoutException, SickIOException, SickThreadException);
/** Switch Sick LMS to monitor mode (stream range) */
void _setSickOpModeMonitorStreamValues( )
throw( SickConfigException, SickTimeoutException, SickIOException, SickThreadException);
/** Switch Sick LMS to monitor mode (stream range and reflectivity) */
void _setSickOpModeMonitorStreamRangeAndReflectivity( )
throw( SickConfigException, SickTimeoutException, SickIOException, SickThreadException);
/** Switch Sick LMS to monitor mode (stream range from a partial scan) */
void _setSickOpModeMonitorStreamValuesFromPartialScan( )
throw( SickConfigException, SickTimeoutException, SickIOException, SickThreadException);
/** Switch Sick LMS to monitor mode (stream mean measured values) */
void _setSickOpModeMonitorStreamMeanValues( const uint8_t sample_size )
throw( SickConfigException, SickTimeoutException, SickIOException, SickThreadException);
/** Switch Sick LMS to monitor mode (stream mean measured values) */
void _setSickOpModeMonitorStreamValuesSubrange( const uint16_t subrange_start_index, const uint16_t subrange_stop_index )
throw( SickConfigException, SickTimeoutException, SickIOException, SickThreadException);
/** Switch Sick LMS to monitor mode (stream mean measured values subrange) */
void _setSickOpModeMonitorStreamMeanValuesSubrange( const uint16_t sample_size, const uint16_t subrange_start_index, const uint16_t subrange_stop_index )
throw( SickConfigException, SickTimeoutException, SickIOException, SickThreadException);
/** Switches the operating mode of the LMS. */
void _switchSickOperatingMode( const uint8_t sick_mode, const uint8_t * const mode_params = NULL )
throw( SickConfigException, SickTimeoutException, SickIOException, SickThreadException);
/** Parses the scan profile returned w/ message B0 */
void _parseSickScanProfileB0( const uint8_t * const src_buffer, sick_lms_2xx_scan_profile_b0_t &sick_scan_profile ) const;
/** Parses the scan profile returned w/ message B6 */
void _parseSickScanProfileB6( const uint8_t * const src_buffer, sick_lms_2xx_scan_profile_b6_t &sick_scan_profile ) const;
/** Parses the scan profile returned w/ message B6 */
void _parseSickScanProfileB7( const uint8_t * const src_buffer, sick_lms_2xx_scan_profile_b7_t &sick_scan_profile ) const;
/** Parses the scan profile returned w/ message BF */
void _parseSickScanProfileBF( const uint8_t * const src_buffer, sick_lms_2xx_scan_profile_bf_t &sick_scan_profile ) const;
/** Parses the scan profile returned w/ message C4 */
void _parseSickScanProfileC4( const uint8_t * const src_buffer, sick_lms_2xx_scan_profile_c4_t &sick_scan_profile ) const;
/** A function for parsing a byte sequence into a device config structure */
void _parseSickConfigProfile( const uint8_t * const src_buffer, sick_lms_2xx_device_config_t &sick_device_config ) const;
/** Acquires the bit mask to extract the field bit values returned with each range measurement */
void _extractSickMeasurementValues( const uint8_t * const byte_sequence, const uint16_t num_measurements, uint16_t * const measured_values,
uint8_t * const field_a_values = NULL, uint8_t * const field_b_values = NULL, uint8_t * const field_c_values = NULL ) const;
/** Tells whether the device is returning real-time indices */
bool _returningRealTimeIndices( ) const { return _sick_device_config.sick_availability_level & SICK_FLAG_AVAILABILITY_REAL_TIME_INDICES; }
/** Indicates whether the given unit value is defined */
bool _validSickMeasuringUnits( const sick_lms_2xx_measuring_units_t sick_units ) const;
/** Indicates whether the given scan angle is defined */
bool _validSickScanAngle( const sick_lms_2xx_scan_angle_t sick_scan_angle ) const;
/** Indicates whether the given scan resolution is defined */
bool _validSickScanResolution( const sick_lms_2xx_scan_resolution_t sick_scan_resolution ) const;
/** Indicates whether the given sensitivity is defined */
bool _validSickSensitivity( const sick_lms_2xx_sensitivity_t sick_sensitivity ) const;
/** Indicates whether the given peak threshold is defined */
bool _validSickPeakThreshold( const sick_lms_2xx_peak_threshold_t sick_peak_threshold ) const;
/** Indicates whether the given sensitivity is defined */
bool _validSickMeasuringMode( const sick_lms_2xx_measuring_mode_t sick_measuring_mode ) const;
/** Indicates whether the Sick LMS is type 200 */
bool _isSickLMS200( ) const;
/** Indicates whether the Sick LMS is type 211 */
bool _isSickLMS211( ) const;
/** Indicates whether the Sick LMS is type 220 */
bool _isSickLMS220( ) const;
/** Indicates whether the Sick LMS is type 221 */
bool _isSickLMS221( ) const;
/** Indicates whether the Sick LMS is type 291 */
bool _isSickLMS291( ) const;
/** Indicates whether the Sick LMS type is unknown */
bool _isSickUnknown( ) const;
/** Given a baud rate as an integer, gets a LMS baud rate command. */
sick_lms_2xx_baud_t _baudToSickBaud( const int baud_rate ) const;
/** Given a bytecode representing Sick LMS availability, returns a corresponding string */
std::string _sickAvailabilityToString( const uint8_t availability_code ) const;
/** Given a bytecode representing Sick LMS restart mode, returns a corresponding string */
std::string _sickRestartToString( const uint8_t restart_code ) const;
/** Converts the LMS's temporary field value to a string */
std::string _sickTemporaryFieldToString( const uint8_t temp_field_code ) const;
/** Converts the LMS's subtractive field value to a string */
std::string _sickSubtractiveFieldsToString( const uint8_t subt_field_code ) const;
/** Converts the LMS's contour function status code to a string */
std::string _sickContourFunctionToString( const uint8_t contour_function_code ) const;
/** Converts the LMS's variant to a corresponding string */
std::string _sickVariantToString( const unsigned int sick_variant ) const;
};
/*!
* \typedef sick_lms_2xx_type_t
* \brief Makes working w/ SickLMS2xx::sick_lms_2xx_type_t a bit easier
*/
typedef SickLMS2xx::sick_lms_2xx_type_t sick_lms_2xx_type_t;
/*!
* \typedef sick_lms_2xx_variant_t
* \brief Makes working w/ SickLMS2xx::sick_lms_2xx_variant_t a bit easier
*/
typedef SickLMS2xx::sick_lms_2xx_variant_t sick_lms_2xx_variant_t;
/*!
* \typedef sick_lms_2xx_scan_angle_t
* \brief Makes working w/ SickLMS2xx::sick_lms_2xx_scan_angle_t a bit easier
*/
typedef SickLMS2xx::sick_lms_2xx_scan_angle_t sick_lms_2xx_scan_angle_t;
/*!
* \typedef sick_lms_2xx_scan_resolution_t
* \brief Makes working w/ SickLMS2xx::sick_lms_2xx_scan_resolution_t a bit easier
*/
typedef SickLMS2xx::sick_lms_2xx_scan_resolution_t sick_lms_2xx_scan_resolution_t;
/*!
* \typedef sick_lms_2xx_measuring_units_t
* \brief Makes working w/ SickLMS2xx::sick_lms_2xx_measuring_units_t a bit easier
*/
typedef SickLMS2xx::sick_lms_2xx_measuring_units_t sick_lms_2xx_measuring_units_t;
/*!
* \typedef sick_lms_2xx_sensitivity_t
* \brief Makes working w/ SickLMS2xx::sick_lms_2xx_sensitivity_t a bit easier
*/
typedef SickLMS2xx::sick_lms_2xx_sensitivity_t sick_lms_2xx_sensitivity_t;
/*!
* \typedef sick_lms_2xx_peak_threshold_t
* \brief Makes working w/ SickLMS2xx::sick_lms_2xx_peak_threshold_t a bit easier
*/
typedef SickLMS2xx::sick_lms_2xx_peak_threshold_t sick_lms_2xx_peak_threshold_t;
/*!
* \typedef sick_lms_2xx_status_t
* \brief Makes working w/ SickLMS2xx::sick_lms_2xx_status_t a bit easier
*/
typedef SickLMS2xx::sick_lms_2xx_status_t sick_lms_2xx_status_t;
/*!
* \typedef sick_lms_2xx_measuring_mode_t
* \brief Makes working w/ SickLMS2xx::sick_lms_2xx_measuring_mode_t a bit easier
*/
typedef SickLMS2xx::sick_lms_2xx_measuring_mode_t sick_lms_2xx_measuring_mode_t;
/*!
* \typedef sick_lms_2xx_operating_mode_t
* \brief Makes working w/ SickLMS2xx::sick_lms_2xx_operating_mode_t a bit easier
*/
typedef SickLMS2xx::sick_lms_2xx_operating_mode_t sick_lms_2xx_operating_mode_t;
/*!
* \typedef sick_lms_2xx_baud_t
* \brief Makes working w/ SickLMS2xx::sick_lms_2xx_baud_t a bit easier
*/
typedef SickLMS2xx::sick_lms_2xx_baud_t sick_lms_2xx_baud_t;
} //namespace SickToolbox
#endif //SICK_LMS_2XX_HH

View File

@ -0,0 +1,51 @@
/*!
* \file SickLMS2xxBufferMonitor.hh
* \brief Defines a class for monitoring the receive
* buffer when interfacing w/ a Sick LMS 2xx
* laser range finder.
*
* Code by Jason C. Derenick and Thomas H. Miller.
* Contact derenick(at)lehigh(dot)edu
*
* The Sick LIDAR Matlab/C++ Toolbox
* Copyright (c) 2008, Jason C. Derenick and Thomas H. Miller
* All rights reserved.
*
* This software is released under a BSD Open-Source License.
* See http://sicktoolbox.sourceforge.net
*/
#ifndef SICK_LMS_2XX_BUFFER_MONITOR_HH
#define SICK_LMS_2XX_BUFFER_MONITOR_HH
#define DEFAULT_SICK_LMS_2XX_SICK_BYTE_TIMEOUT (35000) ///< Max allowable time between consecutive bytes
/* Definition dependencies */
#include "SickLMS2xxMessage.hh"
#include "SickBufferMonitor.hh"
#include "SickException.hh"
/* Associate the namespace */
namespace SickToolbox {
/*!
* \brief A class for monitoring the receive buffer when interfacing with a Sick LMS LIDAR
*/
class SickLMS2xxBufferMonitor : public SickBufferMonitor< SickLMS2xxBufferMonitor, SickLMS2xxMessage > {
public:
/** A standard constructor */
SickLMS2xxBufferMonitor( );
/** A method for extracting a single message from the stream */
void GetNextMessageFromDataStream( SickLMS2xxMessage &sick_message ) throw( SickIOException );
/** A standard destructor */
~SickLMS2xxBufferMonitor( );
};
} /* namespace SickToolbox */
#endif /* SICK_LMS_2XX_BUFFER_MONITOR_HH */

View File

@ -0,0 +1,99 @@
/*!
* \file SickLMS2xxMessage.hh
* \brief Definition of class SickLMS2xxMessage.
*
* Code by Jason C. Derenick and Thomas H. Miller.
* Contact derenick(at)lehigh(dot)edu
*
* The Sick LIDAR Matlab/C++ Toolbox
* Copyright (c) 2008, Jason C. Derenick and Thomas H. Miller
* All rights reserved.
*
* This software is released under a BSD Open-Source License.
* See http://sicktoolbox.sourceforge.net
*/
#ifndef SICK_LMS_2XX_MESSAGE_HH
#define SICK_LMS_2XX_MESSAGE_HH
/* Definition dependencies */
#include <string.h>
#include <netinet/in.h>
#include "SickMessage.hh"
#include "SickException.hh"
#define CRC16_GEN_POL 0x8005 ///< Used to compute CRCs
/** Makes a "short" in little endian */
#define MKSHORT(a,b) ((unsigned short) (a) | ((unsigned short)(b) << 8))
#define SICK_LMS_2XX_MSG_HEADER_LEN (4) ///< Sick LMS message length in bytes
#define SICK_LMS_2XX_MSG_PAYLOAD_MAX_LEN (812) ///< Sick LMS max payload length in bytes
#define SICK_LMS_2XX_MSG_TRAILER_LEN (2) ///< Sick LMS message trailer length in bytes
/* Associate the namespace */
namespace SickToolbox {
/**
* \brief A class to represent all messages sent to and from the Sick LMS 2xx
*
* This class helps to construct messages to be sent to the Sick. It also
* provides a container for received messages to be parsed into.
*/
class SickLMS2xxMessage : public SickMessage< SICK_LMS_2XX_MSG_HEADER_LEN, SICK_LMS_2XX_MSG_PAYLOAD_MAX_LEN, SICK_LMS_2XX_MSG_TRAILER_LEN >
{
public:
/** Default constructor. Constructs an empty message (not well-formed!). */
SickLMS2xxMessage( );
/** Constructs a frame by using BuildMessage(). */
SickLMS2xxMessage( const uint8_t dest_address, const uint8_t * const payload_buffer, const unsigned int payload_length );
/** Constructs a frame using ParseMessage(). */
SickLMS2xxMessage( uint8_t * const message_buffer );
/** Constructs a well-formed raw frame from input fields. */
void BuildMessage( uint8_t dest_address, const uint8_t * const payload_buffer,
const unsigned int payload_length );
/** Populates fields from a (well-formed) raw frame. */
void ParseMessage( const uint8_t * const message_buffer );
/** Gets the address of the frame. */
uint8_t GetDestAddress( ) const { return _message_buffer[1]; }
/** Gets the command code associated with the message */
uint8_t GetCommandCode( ) const { return _message_buffer[MESSAGE_HEADER_LENGTH]; }
/** Gets the status byte from an LMS response message (NOTE: only applies to Sick LMS response telegrams!) */
uint8_t GetStatusByte( ) const { return _message_buffer[MESSAGE_HEADER_LENGTH+_payload_length-1]; }
/** Gets the checksum for the message. */
uint16_t GetChecksum( ) const { return _checksum; }
/** Reset the data associated with this message (for initialization purposes) */
void Clear( );
/** A debugging function that prints the contents of the message. */
void Print( ) const;
/** Destructor */
~SickLMS2xxMessage();
protected:
/** The checksum (CRC16) */
uint16_t _checksum;
private:
/** Computes the checksum of the frame. */
uint16_t _computeCRC( uint8_t * data, unsigned int data_length ) const;
};
} /* namespace SickToolbox */
#endif //SICK_LMS_2XX_MESSAGE_HH

View File

@ -0,0 +1,121 @@
/*!
* \file SickLMS2xxUtility.hh
* \brief Defines simple utility functions for working with the
* Sick LMS 2xx laser range finder units.
*
* Code by Jason C. Derenick and Thomas H. Miller.
* Contact derenick(at)lehigh(dot)edu
*
* The Sick LIDAR Matlab/C++ Toolbox
* Copyright (c) 2008, Jason C. Derenick and Thomas H. Miller
* All rights reserved.
*
* This software is released under a BSD Open-Source License.
* See http://sicktoolbox.sourceforge.net
*/
/* Auto-generated header */
#include "SickConfig.hh"
/**
* \def REVERSE_BYTE_ORDER_16
* \brief Reverses the byte order of the given 16 bit unsigned integer
*/
#define REVERSE_BYTE_ORDER_16( y ) ( ( ( y & 0x00FF ) << 8 ) | ( ( y & 0xFF00 ) >> 8 ) )
/**
* \def REVERSE_BYTE_ORDER_32
* \brief Reverses the byte order of the given 32 bit unsigned integer
*/
#define REVERSE_BYTE_ORDER_32( y ) ( ( ( y & 0x000000FF ) << 24 ) | ( ( y & 0x0000FF00 ) << 8 ) | ( ( y & 0x00FF0000 ) >> 8 ) | ( ( y & 0xFF000000 ) >> 24 ) )
/* Associate the namespace */
namespace SickToolbox {
#ifndef WORDS_BIGENDIAN
/* NOTE: The following functions are necessary since the Sick LD doesn't adopt the
* convention of converting from network byte order.
*/
/**
* \brief Converts host byte order (little-endian) to Sick LMS byte order (little-endian)
* \param value The 2-byte value to convert to little-endian
* \return Value in Sick LMS byte order (little-endian)
*/
inline uint16_t host_to_sick_lms_2xx_byte_order( uint16_t value ) {
return value;
}
/**
* \brief Converts host byte order (little-endian) to Sick LMS byte order (little-endian)
* \param value The 4-byte value to convert to little-endian
* \return Value in Sick LMS byte order (little-endian)
*/
inline uint32_t host_to_sick_lms_2xx_byte_order( uint32_t value ) {
return value;
}
/**
* \brief Converts Sick LMS byte order (little-endian) to host byte order (little-endian)
* \param value The 2-byte value to convert to little-endian
* \return Value in host byte order (little-endian)
*/
inline uint16_t sick_lms_2xx_to_host_byte_order( uint16_t value ) {
return value;
}
/**
* \brief Converts Sick LMS byte order (little-endian) to host byte order (little-endian)
* \param value The 4-byte value to convert to little-endian
* \return Value in host byte order (little-endian)
*/
inline uint32_t sick_lms_2xx_to_host_byte_order( uint32_t value ) {
return value;
}
#else // The host has a big-endian architecture
/**
* \brief Converts host byte order (big-endian) to Sick LMS byte order (little-endian)
* \param value The 2-byte value to convert to little-endian
* \return Value in Sick LMS byte order (little-endian)
*/
inline uint16_t host_to_sick_lms_2xx_byte_order( uint16_t value ) {
return REVERSE_BYTE_ORDER_16(value);
}
/**
* \brief Converts host byte order (big-endian) to Sick LMS byte order (little-endian)
* \param value The 4-byte value to convertto little-endian
* \return Value in Sick LMS byte order (little-endian)
*/
inline uint32_t host_to_sick_lms_2xx_byte_order( uint32_t value ) {
return REVERSE_BYTE_ORDER_32(value);
}
/**
* \brief Converts Sick LMS byte order (little-endian) to host byte order (big-endian)
* \param value The 2-byte value to convert to big-endian
* \return Value in host byte order (big-endian)
*/
inline uint16_t sick_lms_2xx_to_host_byte_order( uint16_t value ) {
return REVERSE_BYTE_ORDER_16(value);
}
/**
* \brief Converts Sick LMS byte order (little-endian) to host byte order (big-endian)
* \param value The 4-byte value to convert to big-endian
* \return Value in host byte order (big-endian)
*/
inline uint32_t sick_lms_2xx_to_host_byte_order( uint32_t value ) {
return REVERSE_BYTE_ORDER_32(value);
}
#endif /* _LITTLE_ENDIAN_HOST */
/*
* NOTE: Other utility functions can be defined here
*/
} //namespace SickToolbox

View File

@ -0,0 +1,230 @@
/*!
* \file SickMessage.hh
* \brief Defines the abstract parent class for all Sick messages.
*
* Code by Jason C. Derenick and Thomas H. Miller.
* Contact derenick(at)lehigh(dot)edu
*
* The Sick LIDAR Matlab/C++ Toolbox
* Copyright (c) 2008, Jason C. Derenick and Thomas H. Miller
* All rights reserved.
*
* This software is released under a BSD Open-Source License.
* See http://sicktoolbox.sourceforge.net
*/
#ifndef SICK_MESSAGE
#define SICK_MESSAGE
/* Dependencies */
#include <arpa/inet.h>
#include <iomanip>
#include <iostream>
/* Associate the namespace */
namespace SickToolbox {
/**
* \class SickMessage
* \brief Provides an abstract parent for all Sick messages
*/
template < unsigned int MSG_HEADER_LENGTH, unsigned int MSG_PAYLOAD_MAX_LENGTH, unsigned int MSG_TRAILER_LENGTH >
class SickMessage {
public:
/** Some constants to make things more manageable */
static const unsigned int MESSAGE_HEADER_LENGTH = MSG_HEADER_LENGTH;
static const unsigned int MESSAGE_TRAILER_LENGTH = MSG_TRAILER_LENGTH;
static const unsigned int MESSAGE_PAYLOAD_MAX_LENGTH = MSG_PAYLOAD_MAX_LENGTH;
static const unsigned int MESSAGE_MAX_LENGTH = MESSAGE_HEADER_LENGTH + MESSAGE_PAYLOAD_MAX_LENGTH + MESSAGE_TRAILER_LENGTH;
/** A standard constructor */
SickMessage( );
/** Construct a well-formed Sick message */
void BuildMessage( const uint8_t * const payload_buffer, const unsigned int payload_length );
/** Populates fields given a sequence of bytes representing a raw message */
virtual void ParseMessage( const uint8_t * const message_buffer ) = 0;
/** Returns a copy of the raw message buffer */
void GetMessage( uint8_t * const message_buffer ) const;
/** Resturns the total message length in bytes */
unsigned int GetMessageLength( ) const { return _message_length; }
/** Returns a copy of the raw message payload */
void GetPayload( uint8_t * const payload_buffer ) const;
/** Returns a copy of the payload as a C String */
void GetPayloadAsCStr( char * const payload_str ) const;
/** Returns a subregion of the payload specified by indices */
void GetPayloadSubregion( uint8_t * const payload_sub_buffer, const unsigned int start_idx,
const unsigned int stop_idx ) const;
/** Returns the total payload length in bytes */
unsigned int GetPayloadLength( ) const { return _payload_length; }
/** Indicates whether the message container is populated */
bool IsPopulated( ) const { return _populated; };
/** Clear the contents of the message container/object */
virtual void Clear( );
/** Print the contents of the message */
virtual void Print( ) const;
/** A virtual destructor */
virtual ~SickMessage( );
protected:
/** The length of the message payload in bytes */
unsigned int _payload_length;
/** The length of the message in bytes */
unsigned int _message_length;
/** The message as a raw sequence of bytes */
uint8_t _message_buffer[MESSAGE_MAX_LENGTH];
/** Indicates whether the message container/object is populated */
bool _populated;
};
/**
* \brief A default constructor
*/
template< unsigned int MSG_HEADER_LENGTH, unsigned int MSG_PAYLOAD_MAX_LENGTH, unsigned int MSG_TRAILER_LENGTH >
SickMessage< MSG_HEADER_LENGTH, MSG_PAYLOAD_MAX_LENGTH, MSG_TRAILER_LENGTH >::SickMessage( ) { }
/**
* \brief Constructs a Sick message given the parameter values
* \param *payload_buffer The payload of the message as an array of bytes
* \param payload_length The length of the payload in bytes
*/
template< unsigned int MSG_HEADER_LENGTH, unsigned int MSG_PAYLOAD_MAX_LENGTH, unsigned int MSG_TRAILER_LENGTH >
void SickMessage< MSG_HEADER_LENGTH, MSG_PAYLOAD_MAX_LENGTH, MSG_TRAILER_LENGTH >::BuildMessage( const uint8_t * const payload_buffer, const unsigned int payload_length ) {
/* Clear the object */
Clear();
/* Assign the payload and message lengths */
_payload_length = payload_length;
_message_length = MESSAGE_HEADER_LENGTH + MESSAGE_TRAILER_LENGTH + _payload_length;
/* Copy the payload into the message buffer */
memcpy(&_message_buffer[MESSAGE_HEADER_LENGTH],payload_buffer,_payload_length);
/* Mark the object container as being populated */
_populated = true;
}
/**
* \brief Parses a sequence of bytes into a Sick message
* \param *message_buffer A well-formed message to be parsed into the class' fields
*/
template< unsigned int MSG_HEADER_LENGTH, unsigned int MSG_PAYLOAD_MAX_LENGTH, unsigned int MSG_TRAILER_LENGTH >
void SickMessage< MSG_HEADER_LENGTH, MSG_PAYLOAD_MAX_LENGTH, MSG_TRAILER_LENGTH >::ParseMessage( const uint8_t * const message_buffer ) {
/* Clear the message container/object */
Clear();
/* Mark the object as populated */
_populated = true;
}
/**
* \brief Get the message as a sequence of well-formed bytes
* \param *message_buffer Destination buffer for message contents
*/
template< unsigned int MSG_HEADER_LENGTH, unsigned int MSG_PAYLOAD_MAX_LENGTH, unsigned int MSG_TRAILER_LENGTH >
void SickMessage< MSG_HEADER_LENGTH, MSG_PAYLOAD_MAX_LENGTH, MSG_TRAILER_LENGTH >::GetMessage( uint8_t * const message_buffer ) const {
memcpy(message_buffer,_message_buffer,_message_length);
}
/**
* \brief Get the payload contents as a sequence of well-formed bytes
* \param *payload_buffer Destination buffer for message payload contents
*/
template< unsigned int MSG_HEADER_LENGTH, unsigned int MSG_PAYLOAD_MAX_LENGTH, unsigned int MSG_TRAILER_LENGTH >
void SickMessage< MSG_HEADER_LENGTH, MSG_PAYLOAD_MAX_LENGTH, MSG_TRAILER_LENGTH >::GetPayload( uint8_t * const payload_buffer ) const {
memcpy(payload_buffer,&_message_buffer[MESSAGE_HEADER_LENGTH],_payload_length);
}
/** Returns a copy of the payload as a C String */
template< unsigned int MSG_HEADER_LENGTH, unsigned int MSG_PAYLOAD_MAX_LENGTH, unsigned int MSG_TRAILER_LENGTH >
void SickMessage< MSG_HEADER_LENGTH, MSG_PAYLOAD_MAX_LENGTH, MSG_TRAILER_LENGTH >::GetPayloadAsCStr( char * const payload_buffer ) const {
memcpy(payload_buffer,&_message_buffer[MESSAGE_HEADER_LENGTH],_payload_length);
payload_buffer[_payload_length] = '\0';
}
/**
* \brief Get a specified sub-region of the payload buffer
* \param *payload_sub_buffer Destination buffer for message payload contents
* \param *start_idx The 0-indexed starting location for copying
* \param *stop_idx The 0-indexed stopping location for copying
*/
template< unsigned int MSG_HEADER_LENGTH, unsigned int MSG_PAYLOAD_MAX_LENGTH, unsigned int MSG_TRAILER_LENGTH >
void SickMessage< MSG_HEADER_LENGTH, MSG_PAYLOAD_MAX_LENGTH, MSG_TRAILER_LENGTH >::GetPayloadSubregion( uint8_t * const payload_sub_buffer,
const unsigned int start_idx,
const unsigned int stop_idx ) const {
/* Extract the subregion */
memcpy(payload_sub_buffer,&_message_buffer[MESSAGE_HEADER_LENGTH+start_idx],stop_idx+1);
}
/**
* \brief Reset all internal fields and buffers
*/
template< unsigned int MSG_HEADER_LENGTH, unsigned int MSG_PAYLOAD_MAX_LENGTH, unsigned int MSG_TRAILER_LENGTH >
void SickMessage< MSG_HEADER_LENGTH, MSG_PAYLOAD_MAX_LENGTH, MSG_TRAILER_LENGTH >::Clear( ) {
/* Reset the parent integer variables */
_message_length = _payload_length = 0;
/* Clear the message buffer */
memset(_message_buffer,0,MESSAGE_MAX_LENGTH);
/* Set the flag indicating this message object/container is empty */
_populated = false;
}
/**
* \brief Print data about this object
*/
template< unsigned int MSG_HEADER_LENGTH, unsigned int MSG_PAYLOAD_MAX_LENGTH, unsigned int MSG_TRAILER_LENGTH >
void SickMessage< MSG_HEADER_LENGTH, MSG_PAYLOAD_MAX_LENGTH, MSG_TRAILER_LENGTH >::Print( ) const {
std::cout << "Payload length: " << GetPayloadLength() << std::endl;
std::cout << "Message length: " << GetMessageLength() << std::endl;
std::cout << std::flush;
std::cout << "Message (hex):" << std::endl;
std::cout.setf(std::ios::hex,std::ios::basefield);
for (unsigned int i = 0; i < _message_length; i++) {
std::cout << (int)_message_buffer[i] << " ";
}
std::cout << std::endl << std::flush;
std::cout << "Message (ASCII):" << std::endl;
std::cout.setf(std::ios::dec,std::ios::basefield);
for (unsigned int i = 0; i < _message_length; i++) {
std::cout << _message_buffer[i] << " ";
}
std::cout << std::endl << std::flush;
}
/**
* \brief A destructor
*/
template< unsigned int MSG_HEADER_LENGTH, unsigned int MSG_PAYLOAD_MAX_LENGTH, unsigned int MSG_TRAILER_LENGTH >
SickMessage< MSG_HEADER_LENGTH, MSG_PAYLOAD_MAX_LENGTH, MSG_TRAILER_LENGTH >::~SickMessage() { }
} /* namespace SickToolbox */
#endif /* SICK_MESSAGE */

View File

@ -0,0 +1,27 @@
<?xml version="1.0"?>
<package>
<name>sicktoolbox</name>
<version>1.0.104</version>
<description>SICK Toolbox drivers for SICK laser rangefinders
This package contains the ROS fork of the SICK LIDAR Matlab/C++ Toolbox, available from <a href="http://sicktoolbox.sourceforge.net/">http://sicktoolbox.sourceforge.net/</a>.
The SICK LIDAR Matlab/C++ Toolbox offers stable and easy-to-use C++ drivers for SICK LMS 2xx and SICK LD LIDARs. Also included are config utilities, examples, and tutorials.
</description>
<maintainer email="chadrockey@gmail.com">Chad Rockey</maintainer>
<license>BSD</license>
<url type="website">http://sicktoolbox.sourceforge.net/</url>
<url type="bugtracker">https://github.com/ros-drivers/sicktoolbox/issues</url>
<url type="repository">https://github.com/ros-drivers/sicktoolbox</url>
<author email="derenick@lehigh.edu">Jason Derenick</author>
<author email="thm204@lehigh.edu">Thomas Miller</author>
<buildtool_depend>catkin</buildtool_depend>
<export>
</export>
</package>