Skip to content

Commit 6919eab

Browse files
authored
Merge pull request #25 from SICKAG/feature/lidar_stop_exit
Fix issue #24 (stop scanner at exit), new ros service SickScanExit to…
2 parents 292cc08 + 7f023f3 commit 6919eab

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+2015
-1341
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ features that will be removed in future versions **Removed** for deprecated feat
88

99
## Released ##
1010

11+
### v2.5.0 -
12+
- **Fixed** Issue #24 (stop scanner at exit)
13+
- **Added** new ros service SickScanExit to stop scanner and exit
14+
1115
### v2.4.6 -
1216
- **Fixed** Corrected angle shift parameter for LMS-4xxx
1317
- **Changed** Typo corrected

CMakeLists.txt

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ if(ROS_VERSION EQUAL 1)
149149
SCdevicestateSrv.srv
150150
SCrebootSrv.srv
151151
SCsoftresetSrv.srv
152+
SickScanExitSrv.srv
152153
)
153154
endif(ROS_VERSION EQUAL 1)
154155

@@ -158,7 +159,10 @@ if(ROS_VERSION EQUAL 2)
158159
set(FastRTPS_LIBRARY_RELEASE /opt/ros/$ENV{ROS_DISTRO}/lib/libfastrtps.so)
159160

160161
find_package(ament_cmake REQUIRED)
161-
find_package(diagnostic_updater REQUIRED)
162+
if(NOT WIN32)
163+
set(diagnostic_updater_pkg diagnostic_updater)
164+
find_package(${diagnostic_updater_pkg} REQUIRED)
165+
endif()
162166
find_package(rclcpp REQUIRED)
163167
find_package(sensor_msgs REQUIRED)
164168
find_package(std_msgs REQUIRED)
@@ -257,6 +261,7 @@ if(ROS_VERSION EQUAL 2)
257261
"srv/SCdevicestateSrv.srv"
258262
"srv/SCrebootSrv.srv"
259263
"srv/SCsoftresetSrv.srv"
264+
"srv/SickScanExitSrv.srv"
260265
${ROSIDL_EMULATOR_FILES}
261266
DEPENDENCIES builtin_interfaces std_msgs nav_msgs geometry_msgs sensor_msgs
262267
)
@@ -363,7 +368,7 @@ if(ROS_VERSION EQUAL 1)
363368
)
364369

365370
catkin_package(
366-
CATKIN_DEPENDS message_runtime roscpp sensor_msgs diagnostic_updater dynamic_reconfigure pcl_conversions pcl_ros tf tf2
371+
CATKIN_DEPENDS message_runtime roscpp sensor_msgs ${diagnostic_updater_pkg} dynamic_reconfigure pcl_conversions pcl_ros tf tf2
367372
LIBRARIES sick_scan_lib sick_scan_shared_lib
368373
INCLUDE_DIRS include
369374
# DEPENDS Boost
@@ -527,7 +532,7 @@ if(ROS_VERSION EQUAL 2)
527532
"nav_msgs"
528533
"visualization_msgs"
529534
"tf2_ros"
530-
"diagnostic_updater"
535+
"${diagnostic_updater_pkg}"
531536
${LDMRS_TARGET_DEPENDENCIES}
532537
)
533538

@@ -542,7 +547,7 @@ if(ROS_VERSION EQUAL 2)
542547
"nav_msgs"
543548
"visualization_msgs"
544549
"tf2_ros"
545-
"diagnostic_updater"
550+
"${diagnostic_updater_pkg}"
546551
${LDMRS_TARGET_DEPENDENCIES}
547552
)
548553

@@ -557,7 +562,7 @@ if(ROS_VERSION EQUAL 2)
557562
"nav_msgs"
558563
"visualization_msgs"
559564
"tf2_ros"
560-
"diagnostic_updater"
565+
"${diagnostic_updater_pkg}"
561566
${LDMRS_TARGET_DEPENDENCIES}
562567
)
563568

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -566,6 +566,12 @@ ros2 service call /SCreboot sick_scan/srv/SCrebootSrv "{}" # execute a
566566
ros2 service call /SCsoftreset sick_scan/srv/SCsoftresetSrv "{}" # save current parameter and shut down device
567567
```
568568
569+
Use ros service `SickScanExit` to stop the scanner and driver:
570+
```
571+
rosservice call /sick_nav_3xx/SickScanExit "{}" # stop scanner and driver on ROS-1
572+
ros2 service call /SickScanExit sick_scan/srv/SickScanExitSrv "{}" # stop scanner and driver on ROS-2
573+
```
574+
569575
Note:
570576
* The COLA commands are sensor specific. See the user manual and telegram listing for further details.
571577
* ROS services require installation of ROS-1 or ROS-2, i.e. services for Cola commands are currently not supported on native Linux or native Windows.

demo/scan.csv

Lines changed: 1141 additions & 1141 deletions
Large diffs are not rendered by default.

demo/scan.jpg

66 Bytes
Loading

driver/src/sick_generic_caller.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,8 @@
8080
#define MAX_NAME_LEN (1024)
8181

8282
#define SICK_GENERIC_MAJOR_VER "2"
83-
#define SICK_GENERIC_MINOR_VER "4"
84-
#define SICK_GENERIC_PATCH_LEVEL "6"
83+
#define SICK_GENERIC_MINOR_VER "5"
84+
#define SICK_GENERIC_PATCH_LEVEL "0"
8585

8686
#include <algorithm> // for std::min
8787

@@ -155,10 +155,11 @@ int main(int argc, char **argv)
155155
rosNodePtr node = rclcpp::Node::make_shared("sick_scan", "", node_options);
156156
#else
157157
ros::init(argc, argv, scannerName, ros::init_options::NoSigintHandler); // scannerName holds the node-name
158-
signal(SIGINT, rosSignalHandler);
158+
// signal(SIGINT, rosSignalHandler);
159159
ros::NodeHandle nh("~");
160160
rosNodePtr node = &nh;
161161
#endif
162+
signal(SIGINT, rosSignalHandler);
162163

163164
ROS_INFO_STREAM(versionInfo << "\n");
164165
for (int i = 0; i < argc_tmp; i++)

driver/src/sick_generic_laser.cpp

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -135,22 +135,27 @@ bool getTagVal(std::string tagVal, std::string &tag, std::string &val)
135135
return (ret);
136136
}
137137

138-
139-
void rosSignalHandler(int signalRecv)
138+
bool stopScannerAndExit(bool force_immediate_shutdown)
140139
{
141-
ROS_INFO_STREAM("Caught signal " << signalRecv << "\n");
142-
ROS_INFO_STREAM("good bye\n");
143-
ROS_INFO_STREAM("You are leaving the following version of this node:\n");
144-
ROS_INFO_STREAM(getVersionInfo() << "\n");
140+
bool success = true;
145141
if (s_scanner != NULL)
146142
{
147143
if (isInitialized)
148144
{
149-
s_scanner->stopScanData();
145+
success = s_scanner->stopScanData(force_immediate_shutdown);
150146
}
151-
152147
runState = scanner_finalize;
153148
}
149+
return success;
150+
}
151+
152+
void rosSignalHandler(int signalRecv)
153+
{
154+
ROS_INFO_STREAM("Caught signal " << signalRecv << "\n");
155+
ROS_INFO_STREAM("good bye\n");
156+
ROS_INFO_STREAM("You are leaving the following version of this node:\n");
157+
ROS_INFO_STREAM(getVersionInfo() << "\n");
158+
stopScannerAndExit(true);
154159
rosShutdown();
155160
}
156161

@@ -467,9 +472,15 @@ int mainGenericLaser(int argc, char **argv, std::string nodeName, rosNodePtr nhP
467472
int result = sick_scan::ExitError;
468473

469474
//sick_scan::SickScanConfig cfg;
475+
//std::chrono::system_clock::time_point timestamp_rosOk = std::chrono::system_clock::now();
470476

471477
while (rosOk() && runState != scanner_finalize)
472478
{
479+
//if (rosOk())
480+
// timestamp_rosOk = std::chrono::system_clock::now();
481+
//else if (std::chrono::duration<double>(std::chrono::system_clock::now() - timestamp_rosOk).count() > 2 * 1000) // 2 seconds timeout to stop the scanner
482+
// runState = scanner_finalize;
483+
473484
switch (runState)
474485
{
475486
case scanner_init:
@@ -507,7 +518,7 @@ int mainGenericLaser(int argc, char **argv, std::string nodeName, rosNodePtr nhP
507518
}
508519

509520
isInitialized = true;
510-
signal(SIGINT, SIG_DFL); // change back to standard signal handler after initialising
521+
// signal(SIGINT, SIG_DFL); // change back to standard signal handler after initialising
511522

512523
if (result == sick_scan::ExitSuccess) // OK -> loop again
513524
{
@@ -549,6 +560,7 @@ int mainGenericLaser(int argc, char **argv, std::string nodeName, rosNodePtr nhP
549560
break;
550561
}
551562
}
563+
printf("sick_generic_laser: leaving main loop...");
552564

553565
if(pointcloud_monitor)
554566
pointcloud_monitor->stopPointCloudMonitoring();

driver/src/sick_scan_common.cpp

Lines changed: 50 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -589,38 +589,40 @@ namespace sick_scan
589589
\brief Stops sending scan data
590590
\return error code
591591
*/
592-
int SickScanCommon::stop_scanner()
592+
int SickScanCommon::stop_scanner(bool force_immediate_shutdown)
593593
{
594594
/*
595595
* Stop streaming measurements
596596
*/
597-
const char requestScanData0[] = {"\x02sEN LMDscandata 0\x03\0"};
598-
int result = sendSOPASCommand(requestScanData0, NULL);
599-
if (result != 0)
597+
std::vector<std::string> sopas_stop_scanner_cmd = { "\x02sEN LMDscandata 0\x03\0" };
598+
if (parser_->getCurrentParamPtr()->getUseEvalFields() == USE_EVAL_FIELD_TIM7XX_LOGIC || parser_->getCurrentParamPtr()->getUseEvalFields() == USE_EVAL_FIELD_LMS5XX_LOGIC)
600599
{
601-
// use printf because we cannot use ROS_ERROR from the destructor
602-
printf("\nSOPAS - Error stopping streaming scan data!\n");
600+
sopas_stop_scanner_cmd.push_back("\x02sEN LFErec 0\x03"); // TiM781S: deactivate LFErec messages, send "sEN LFErec 0"
601+
sopas_stop_scanner_cmd.push_back("\x02sEN LIDoutputstate 0\x03"); // TiM781S: deactivate LIDoutputstate messages, send "sEN LIDoutputstate 0"
602+
sopas_stop_scanner_cmd.push_back("\x02sEN LIDinputstate 0\x03"); // TiM781S: deactivate LIDinputstate messages, send "sEN LIDinputstate 0"
603603
}
604-
else
604+
sopas_stop_scanner_cmd.push_back("\x02sMN SetAccessMode 3 F4724744\x03\0");
605+
sopas_stop_scanner_cmd.push_back("\x02sMN LMCstopmeas\x03\0");
606+
// sopas_stop_scanner_cmd.push_back("\x02sMN Run\x03\0");
607+
608+
setReadTimeOutInMs(1000);
609+
ROS_INFO_STREAM("sick_scan_common: stopping scanner ...");
610+
int result = ExitSuccess, cmd_result = ExitSuccess;
611+
for(int cmd_idx = 0; cmd_idx < sopas_stop_scanner_cmd.size(); cmd_idx++)
605612
{
606-
printf("\nSOPAS - Stopped streaming scan data.\n");
607-
}
608-
609-
if (parser_->getCurrentParamPtr()->getUseEvalFields() == USE_EVAL_FIELD_TIM7XX_LOGIC || parser_->getCurrentParamPtr()->getUseEvalFields() == USE_EVAL_FIELD_LMS5XX_LOGIC)
610-
{
611-
if(sendSOPASCommand("\x02sEN LFErec 0\x03", NULL) != 0 // TiM781S: deactivate LFErec messages, send "sEN LFErec 0"
612-
|| sendSOPASCommand("\x02sEN LIDoutputstate 0\x03", NULL) != 0 // TiM781S: deactivate LIDoutputstate messages, send "sEN LIDoutputstate 0"
613-
|| sendSOPASCommand("\x02sEN LIDinputstate 0\x03", NULL) != 0) // TiM781S: deactivate LIDinputstate messages, send "sEN LIDinputstate 0"
613+
std::vector<unsigned char> sopas_reply;
614+
cmd_result = convertSendSOPASCommand(sopas_stop_scanner_cmd[cmd_idx], &sopas_reply, (force_immediate_shutdown==false));
615+
if (force_immediate_shutdown == false)
614616
{
615-
// use printf because we cannot use ROS_ERROR from the destructor
616-
printf("\nSOPAS - Error stopping streaming LFErec, LIDoutputstate and LIDinputstate messages!\n");
617+
ROS_INFO_STREAM("sick_scan_common: received sopas reply \"" << replyToString(sopas_reply) << "\"");
617618
}
618-
else
619+
if (cmd_result != ExitSuccess)
619620
{
620-
printf("\nSOPAS - Stopped streaming LFErec, LIDoutputstate and LIDinputstate messages\n");
621+
ROS_WARN_STREAM("## ERROR sick_scan_common: ERROR sending sopas command \"" << sopas_stop_scanner_cmd[cmd_idx] << "\"");
622+
result = ExitError;
621623
}
624+
// std::this_thread::sleep_for(std::chrono::milliseconds((int64_t)100));
622625
}
623-
624626
return result;
625627
}
626628

@@ -678,9 +680,32 @@ namespace sick_scan
678680

679681
}
680682

683+
/// Converts a given SOPAS command from ascii to binary (in case of binary communication), sends sopas (ascii or binary) and returns the response (if wait_for_reply:=true)
684+
/**
685+
* \param [in] request the command to send.
686+
* \param [in] cmdLen Length of the Comandstring in bytes used for Binary Mode only
687+
*/
688+
int SickScanCommon::convertSendSOPASCommand(const std::string& sopas_ascii_request, std::vector<unsigned char> *sopas_reply, bool wait_for_reply)
689+
{
690+
int result = ExitError;
691+
if (getProtocolType() == CoLa_B)
692+
{
693+
std::vector<unsigned char> requestBinary;
694+
convertAscii2BinaryCmd(sopas_ascii_request.c_str(), &requestBinary);
695+
ROS_INFO_STREAM("sick_scan_common: sending sopas command \"" << stripControl(requestBinary) << "\"");
696+
result = sendSOPASCommand((const char*)requestBinary.data(), sopas_reply, requestBinary.size(), wait_for_reply);
697+
}
698+
else
699+
{
700+
ROS_INFO_STREAM("sick_scan_common: sending sopas command \"" << sopas_ascii_request << "\"");
701+
result = sendSOPASCommand(sopas_ascii_request.c_str(), sopas_reply, sopas_ascii_request.size(), wait_for_reply);
702+
}
703+
return result;
704+
}
705+
681706

682707
/*!
683-
\brief Reboot scanner (todo: this does not work if the scanner is set to binary mode) Fix me!
708+
\brief Reboot scanner
684709
\return Result of rebooting attempt
685710
*/
686711
bool SickScanCommon::rebootScanner()
@@ -689,8 +714,10 @@ namespace sick_scan
689714
* Set Maintenance access mode to allow reboot to be sent
690715
*/
691716
std::vector<unsigned char> access_reply;
717+
718+
692719
// changed from "03" to "3"
693-
int result = sendSOPASCommand("\x02sMN SetAccessMode 3 F4724744\x03\0", &access_reply);
720+
int result = convertSendSOPASCommand("\x02sMN SetAccessMode 3 F4724744\x03\0", &access_reply);
694721
if (result != 0)
695722
{
696723
ROS_ERROR("SOPAS - Error setting access mode");
@@ -715,7 +742,7 @@ namespace sick_scan
715742
* Send reboot command
716743
*/
717744
std::vector<unsigned char> reboot_reply;
718-
result = sendSOPASCommand("\x02sMN mSCreboot\x03\0", &reboot_reply);
745+
result = convertSendSOPASCommand("\x02sMN mSCreboot\x03\0", &reboot_reply);
719746
if (result != 0)
720747
{
721748
ROS_ERROR("SOPAS - Error rebooting scanner");

driver/src/sick_scan_common_tcp.cpp

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ namespace sick_scan
232232

233233
SickScanCommonTcp::~SickScanCommonTcp()
234234
{
235-
// stop_scanner();
235+
// stop_scanner(true);
236236
close_device();
237237
}
238238

@@ -620,10 +620,10 @@ namespace sick_scan
620620
}
621621

622622

623-
bool SickScanCommonTcp::stopScanData()
623+
bool SickScanCommonTcp::stopScanData(bool force_immediate_shutdown)
624624
{
625-
stop_scanner();
626-
return (true);
625+
int retval = stop_scanner(force_immediate_shutdown);
626+
return retval == ExitSuccess;
627627
}
628628

629629
// void SickScanCommonTcp::handleRead(boost::system::error_code error, size_t bytes_transfered)
@@ -677,7 +677,7 @@ namespace sick_scan
677677
/**
678678
* Send a SOPAS command to the device and print out the response to the console.
679679
*/
680-
int SickScanCommonTcp::sendSOPASCommand(const char *request, std::vector<unsigned char> *reply, int cmdLen)
680+
int SickScanCommonTcp::sendSOPASCommand(const char *request, std::vector<unsigned char> *reply, int cmdLen, bool wait_for_reply)
681681
{
682682
int sLen = 0;
683683
int msgLen = 0;
@@ -744,6 +744,10 @@ namespace sick_scan
744744
}
745745
}
746746
}
747+
if(!wait_for_reply)
748+
{
749+
return ExitSuccess;
750+
}
747751

748752
// Set timeout in 5 seconds
749753
const int BUF_SIZE = 65536;
@@ -765,7 +769,7 @@ namespace sick_scan
765769
ROS_WARN_STREAM("sendSOPASCommand: no full reply available for read after " << getReadTimeOutInMs() << " ms");
766770
#endif
767771
#ifdef USE_DIAGNOSTIC_UPDATER
768-
if(diagnostics_)
772+
if(diagnostics_ && rosOk())
769773
diagnostics_->broadcast(getDiagnosticErrorCode(),
770774
"sendSOPASCommand: no full reply available for read after timeout.");
771775
#endif

0 commit comments

Comments
 (0)