Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #include <sick_tim/sick_tim_common.h>
00040
00041 namespace sick_tim
00042 {
00043
00044 SickTimCommon::SickTimCommon(AbstractParser* parser) :
00045 diagnosticPub_(NULL), expectedFrequency_(15.0), parser_(parser)
00046
00047 {
00048 dynamic_reconfigure::Server<sick_tim::SickTimConfig>::CallbackType f;
00049 f = boost::bind(&sick_tim::SickTimCommon::update_config, this, _1, _2);
00050 dynamic_reconfigure_server_.setCallback(f);
00051
00052
00053 ros::NodeHandle pn("~");
00054 pn.param<bool>("publish_datagram", publish_datagram_, false);
00055 if (publish_datagram_)
00056 datagram_pub_ = nh_.advertise<std_msgs::String>("datagram", 1000);
00057
00058
00059 pub_ = nh_.advertise<sensor_msgs::LaserScan>("scan", 1000);
00060
00061 diagnostics_.setHardwareID("none");
00062 diagnosticPub_ = new diagnostic_updater::DiagnosedPublisher<sensor_msgs::LaserScan>(pub_, diagnostics_,
00063
00064 diagnostic_updater::FrequencyStatusParam(&expectedFrequency_, &expectedFrequency_, 0.1, 10),
00065
00066 diagnostic_updater::TimeStampStatusParam(-1, 1.3 * 1.0/expectedFrequency_));
00067 ROS_ASSERT(diagnosticPub_ != NULL);
00068 }
00069
00070 int SickTimCommon::stop_scanner()
00071 {
00072
00073
00074
00075 const char requestScanData0[] = {"\x02sEN LMDscandata 0\x03\0"};
00076 int result = sendSOPASCommand(requestScanData0, NULL);
00077 if (result != 0)
00078
00079 printf("\nSOPAS - Error stopping streaming scan data!\n");
00080 else
00081 printf("\nSOPAS - Stopped streaming scan data.\n");
00082
00083 return result;
00084 }
00085
00086 SickTimCommon::~SickTimCommon()
00087 {
00088 delete diagnosticPub_;
00089
00090 printf("sick_tim driver exiting.\n");
00091 }
00092
00093
00094 int SickTimCommon::init()
00095 {
00096 int result = init_device();
00097 if(result != 0) {
00098 ROS_FATAL("Failed to init device: %d", result);
00099 return result;
00100 }
00101 result = init_scanner();
00102 if(result != 0) {
00103 ROS_FATAL("Failed to init scanner: %d", result);
00104 }
00105 return result;
00106 }
00107
00108 int SickTimCommon::init_scanner()
00109 {
00110
00111
00112
00113 const char requestDeviceIdent[] = "\x02sRI0\x03\0";
00114 std::vector<unsigned char> identReply;
00115 int result = sendSOPASCommand(requestDeviceIdent, &identReply);
00116 if (result != 0)
00117 {
00118 ROS_ERROR("SOPAS - Error reading variable 'DeviceIdent'.");
00119 diagnostics_.broadcast(diagnostic_msgs::DiagnosticStatus::ERROR, "SOPAS - Error reading variable 'DeviceIdent'.");
00120 }
00121
00122
00123
00124
00125 const char requestSerialNumber[] = "\x02sRN SerialNumber\x03\0";
00126 std::vector<unsigned char> serialReply;
00127 result = sendSOPASCommand(requestSerialNumber, &serialReply);
00128 if (result != 0)
00129 {
00130 ROS_ERROR("SOPAS - Error reading variable 'SerialNumber'.");
00131 diagnostics_.broadcast(diagnostic_msgs::DiagnosticStatus::ERROR, "SOPAS - Error reading variable 'SerialNumber'.");
00132 }
00133
00134
00135 identReply.push_back(0);
00136 serialReply.push_back(0);
00137 std::string identStr;
00138 for(std::vector<unsigned char>::iterator it = identReply.begin(); it != identReply.end(); it++) {
00139 if(*it > 13)
00140 identStr.push_back(*it);
00141 }
00142 std::string serialStr;
00143 for(std::vector<unsigned char>::iterator it = serialReply.begin(); it != serialReply.end(); it++) {
00144 if(*it > 13)
00145 serialStr.push_back(*it);
00146 }
00147 diagnostics_.setHardwareID(identStr + " " + serialStr);
00148
00149
00150
00151
00152 const char requestFirmwareVersion[] = {"\x02sRN FirmwareVersion\x03\0"};
00153 result = sendSOPASCommand(requestFirmwareVersion, NULL);
00154 if (result != 0)
00155 {
00156 ROS_ERROR("SOPAS - Error reading variable 'FirmwareVersion'.");
00157 diagnostics_.broadcast(diagnostic_msgs::DiagnosticStatus::ERROR, "SOPAS - Error reading variable 'FirmwareVersion'.");
00158 }
00159
00160
00161
00162
00163 const char requestScanData[] = {"\x02sEN LMDscandata 1\x03\0"};
00164 result = sendSOPASCommand(requestScanData, NULL);
00165 if (result != 0)
00166 {
00167 ROS_ERROR("SOPAS - Error starting to stream 'LMDscandata'.");
00168 diagnostics_.broadcast(diagnostic_msgs::DiagnosticStatus::ERROR, "SOPAS - Error starting to stream 'LMDscandata'.");
00169 return EXIT_FAILURE;
00170 }
00171
00172 return EXIT_SUCCESS;
00173 }
00174
00175 int SickTimCommon::loopOnce()
00176 {
00177 diagnostics_.update();
00178
00179 unsigned char receiveBuffer[65536];
00180 int actual_length = 0;
00181 static unsigned int iteration_count = 0;
00182
00183 int result = get_datagram(receiveBuffer, 65536, &actual_length);
00184 if (result != 0)
00185 {
00186 ROS_ERROR("Read Error when getting datagram: %i.", result);
00187 diagnostics_.broadcast(diagnostic_msgs::DiagnosticStatus::ERROR, "Read Error when getting datagram.");
00188 return EXIT_FAILURE;
00189 }
00190 if(actual_length <= 0)
00191 return EXIT_SUCCESS;
00192
00193
00194 if (iteration_count++ % (config_.skip + 1) != 0)
00195 return EXIT_SUCCESS;
00196
00197 if (publish_datagram_)
00198 {
00199 std_msgs::String datagram_msg;
00200 datagram_msg.data = std::string(reinterpret_cast<char*>(receiveBuffer));
00201 datagram_pub_.publish(datagram_msg);
00202 }
00203
00204 sensor_msgs::LaserScan msg;
00205
00206
00207
00208
00209 char* buffer_pos = (char*)receiveBuffer;
00210 char *dstart, *dend;
00211 while( (dstart = strchr(buffer_pos, 0x02)) && (dend = strchr(dstart + 1, 0x03)) )
00212 {
00213 size_t dlength = dend - dstart;
00214 *dend = '\0';
00215 dstart++;
00216 int success = parser_->parse_datagram(dstart, dlength, config_, msg);
00217 if (success == EXIT_SUCCESS)
00218 diagnosticPub_->publish(msg);
00219 buffer_pos = dend + 1;
00220 }
00221
00222 return EXIT_SUCCESS;
00223 }
00224
00225 void SickTimCommon::check_angle_range(SickTimConfig &conf)
00226 {
00227 if (conf.min_ang > conf.max_ang)
00228 {
00229 ROS_WARN("Minimum angle must be greater than maximum angle. Adjusting min_ang.");
00230 conf.min_ang = conf.max_ang;
00231 }
00232 }
00233
00234 void SickTimCommon::update_config(sick_tim::SickTimConfig &new_config, uint32_t level)
00235 {
00236 check_angle_range(new_config);
00237 config_ = new_config;
00238 }
00239
00240 }