Skip to content

Commit 4041a96

Browse files
dbking77mintar
authored andcommitted
Automatically reboot scanner if it reports an error code. (#44)
1 parent dc75c39 commit 4041a96

File tree

3 files changed

+116
-14
lines changed

3 files changed

+116
-14
lines changed

cfg/SickTim.cfg

+1
Original file line numberDiff line numberDiff line change
@@ -46,5 +46,6 @@ gen.add("intensity", bool_t, 0, "Whether or not to return intensity value
4646
gen.add("skip", int_t, 0, "The number of scans to skip between each measured scan.", 0, 0, 9)
4747
gen.add("frame_id", str_t, 0, "The TF frame in which laser scans will be returned.", "laser")
4848
gen.add("time_offset", double_t, 0, "An offset to add to the time stamp before publication of a scan [s].", -0.001, -0.25, 0.25)
49+
gen.add("auto_reboot", bool_t, 0, "Whether or not to reboot laser if it reports an error", True)
4950

5051
exit(gen.generate(PACKAGE, "sick_tim", "SickTim"))

include/sick_tim/sick_tim_common.h

+14
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141

4242
#include <stdio.h>
4343
#include <stdlib.h>
44+
#include <string>
4445
#include <string.h>
4546
#include <vector>
4647

@@ -71,6 +72,12 @@ class SickTimCommon
7172

7273
double get_expected_frequency() const { return expectedFrequency_; }
7374

75+
/// Send a SOPAS command to the scanner that should cause a soft reset
76+
/**
77+
* \returns true if reboot command was accepted, false otherwise
78+
*/
79+
virtual bool rebootScanner();
80+
7481
protected:
7582
virtual int init_device() = 0;
7683
virtual int init_scanner();
@@ -92,6 +99,13 @@ class SickTimCommon
9299
*/
93100
virtual int get_datagram(unsigned char* receiveBuffer, int bufferSize, int* actual_length) = 0;
94101

102+
/// Converts reply from sendSOPASCommand to string
103+
/**
104+
* \param [in] reply reply from sendSOPASCommand
105+
* \returns reply as string with special characters stripped out
106+
*/
107+
static std::string replyToString(const std::vector<unsigned char> &reply);
108+
95109
bool isCompatibleDevice(const std::string identStr) const;
96110

97111
protected:

src/sick_tim_common.cpp

+101-14
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,54 @@ int SickTimCommon::stop_scanner()
8686
return result;
8787
}
8888

89+
bool SickTimCommon::rebootScanner()
90+
{
91+
/*
92+
* Set Maintenance access mode to allow reboot to be sent
93+
*/
94+
std::vector<unsigned char> access_reply;
95+
int result = sendSOPASCommand("\x02sMN SetAccessMode 03 F4724744\x03\0", &access_reply);
96+
if (result != 0)
97+
{
98+
ROS_ERROR("SOPAS - Error setting access mode");
99+
diagnostics_.broadcast(diagnostic_msgs::DiagnosticStatus::ERROR, "SOPAS - Error setting access mode.");
100+
return false;
101+
}
102+
std::string access_reply_str = replyToString(access_reply);
103+
if (access_reply_str != "sAN SetAccessMode 1")
104+
{
105+
ROS_ERROR_STREAM("SOPAS - Error setting access mode, unexpected response : " << access_reply_str);
106+
diagnostics_.broadcast(diagnostic_msgs::DiagnosticStatus::ERROR, "SOPAS - Error setting access mode.");
107+
return false;
108+
}
109+
110+
/*
111+
* Send reboot command
112+
*/
113+
std::vector<unsigned char> reboot_reply;
114+
result = sendSOPASCommand("\x02sMN mSCreboot\x03\0", &reboot_reply);
115+
if (result != 0)
116+
{
117+
ROS_ERROR("SOPAS - Error rebooting scanner");
118+
diagnostics_.broadcast(diagnostic_msgs::DiagnosticStatus::ERROR, "SOPAS - Error rebooting device.");
119+
return false;
120+
}
121+
std::string reboot_reply_str = replyToString(reboot_reply);
122+
if (reboot_reply_str != "sAN mSCreboot")
123+
{
124+
ROS_ERROR_STREAM("SOPAS - Error rebooting scanner, unexpected response : " << reboot_reply_str);
125+
diagnostics_.broadcast(diagnostic_msgs::DiagnosticStatus::ERROR, "SOPAS - Error setting access mode.");
126+
return false;
127+
}
128+
129+
ROS_INFO("SOPAS - Rebooted scanner");
130+
131+
// Wait a few seconds after rebooting
132+
ros::Duration(15.0).sleep();
133+
134+
return true;
135+
}
136+
89137
SickTimCommon::~SickTimCommon()
90138
{
91139
delete diagnosticPub_;
@@ -135,20 +183,8 @@ int SickTimCommon::init_scanner()
135183
}
136184

137185
// set hardware ID based on DeviceIdent and SerialNumber
138-
identReply.push_back(0); // add \0 to convert to string
139-
serialReply.push_back(0);
140-
std::string identStr;
141-
for (std::vector<unsigned char>::iterator it = identReply.begin(); it != identReply.end(); it++)
142-
{
143-
if (*it > 13) // filter control characters for display
144-
identStr.push_back(*it);
145-
}
146-
std::string serialStr;
147-
for (std::vector<unsigned char>::iterator it = serialReply.begin(); it != serialReply.end(); it++)
148-
{
149-
if (*it > 13)
150-
serialStr.push_back(*it);
151-
}
186+
std::string identStr = replyToString(identReply);
187+
std::string serialStr = replyToString(serialReply);
152188
diagnostics_.setHardwareID(identStr + " " + serialStr);
153189

154190
if (!isCompatibleDevice(identStr))
@@ -165,6 +201,44 @@ int SickTimCommon::init_scanner()
165201
diagnostics_.broadcast(diagnostic_msgs::DiagnosticStatus::ERROR, "SOPAS - Error reading variable 'FirmwareVersion'.");
166202
}
167203

204+
/*
205+
* Read Device State
206+
*/
207+
const char requestDeviceState[] = {"\x02sRN SCdevicestate\x03\0"};
208+
std::vector<unsigned char> deviceStateReply;
209+
result = sendSOPASCommand(requestDeviceState, &deviceStateReply);
210+
if (result != 0)
211+
{
212+
ROS_ERROR("SOPAS - Error reading variable 'devicestate'.");
213+
diagnostics_.broadcast(diagnostic_msgs::DiagnosticStatus::ERROR, "SOPAS - Error reading variable 'devicestate'.");
214+
}
215+
std::string deviceStateReplyStr = replyToString(deviceStateReply);
216+
217+
/*
218+
* Process device state, 0=Busy, 1=Ready, 2=Error
219+
* If configuration parameter is set, try resetting device in error state
220+
*/
221+
if (deviceStateReplyStr == "sRA SCdevicestate 0")
222+
{
223+
ROS_WARN("Laser is busy");
224+
}
225+
else if (deviceStateReplyStr == "sRA SCdevicestate 1")
226+
{
227+
ROS_DEBUG("Laser is ready");
228+
}
229+
else if (deviceStateReplyStr == "sRA SCdevicestate 2")
230+
{
231+
ROS_ERROR_STREAM("Laser reports error state : " << deviceStateReplyStr);
232+
if (config_.auto_reboot)
233+
{
234+
rebootScanner();
235+
}
236+
}
237+
else
238+
{
239+
ROS_WARN_STREAM("Laser reports unknown devicestate : " << deviceStateReplyStr);
240+
}
241+
168242
/*
169243
* Start streaming 'LMDscandata'.
170244
*/
@@ -180,6 +254,19 @@ int SickTimCommon::init_scanner()
180254
return ExitSuccess;
181255
}
182256

257+
std::string sick_tim::SickTimCommon::replyToString(const std::vector<unsigned char> &reply)
258+
{
259+
std::string reply_str;
260+
for (std::vector<unsigned char>::const_iterator it = reply.begin(); it != reply.end(); it++)
261+
{
262+
if (*it > 13) // filter control characters for display
263+
{
264+
reply_str.push_back(*it);
265+
}
266+
}
267+
return reply_str;
268+
}
269+
183270
bool sick_tim::SickTimCommon::isCompatibleDevice(const std::string identStr) const
184271
{
185272
char device_string[7];

0 commit comments

Comments
 (0)