📄 sicklms200.cc
字号:
for (tries = 0; tries < DEFAULT_LASER_RETRIES; tries++) { packet[0] = 0x74; len = 1; //PLAYER_MSG0(2, "sending get configuration request to laser"); if (WriteToLaser(packet, len) < 0) return 1; // Wait for laser to return data //PLAYER_MSG0(2, "waiting for reply"); len = ReadFromLaser(packet, sizeof(packet), false, 10000); if (len < 0) return 1; else if (len < 1) { PLAYER_WARN("timeout"); continue; } else if (packet[0] == NACK) { PLAYER_ERROR("request denied by laser"); return 1; } else if (packet[0] != 0xF4) { PLAYER_ERROR("unexpected packet type"); return 1; } break; } if (tries >= DEFAULT_LASER_RETRIES) return 1; //PLAYER_MSG0(2, "get configuration request ok"); //PLAYER_TRACE1("laser units [%d]", (int) packet[7]); for (tries = 0; tries < DEFAULT_LASER_RETRIES; tries++) { // Modify the configuration and send it back packet[0] = 0x77; // Return intensity in top 3 data bits packet[6] = (intensity ? 0x01 : 0x00); // Set the units for the range reading if (this->range_res == 1) packet[7] = 0x01; else if (this->range_res == 10) packet[7] = 0x00; else if (this->range_res == 100) packet[7] = 0x02; else packet[7] = 0x01; //PLAYER_MSG0(2, "sending set configuration request to laser"); if (WriteToLaser(packet, len) < 0) return 1; // Wait for the change to "take" //PLAYER_MSG0(2, "waiting for acknowledge"); len = ReadFromLaser(packet, sizeof(packet), false, 10000); if (len < 0) return 1; else if (len < 1) { PLAYER_ERROR("timeout"); continue; } else if (packet[0] == NACK) { PLAYER_ERROR("request denied by laser"); return 1; } else if (packet[0] != 0xF7) { PLAYER_ERROR("unexpected packet type"); return 1; } //PLAYER_MSG0(2, "set configuration request ok"); break; } return (tries >= DEFAULT_LASER_RETRIES);}////////////////////////////////////////////////////////////////////////////////// Change the resolution of the laser// Valid widths are: 100, 180 (degrees)// Valid resolitions are: 25, 50, 100 (1/100 degree)//int SickLMS200::SetLaserRes(int width, int res){ int tries; ssize_t len; uint8_t packet[512]; for (tries = 0; tries < DEFAULT_LASER_RETRIES; tries++) { len = 0; packet[len++] = 0x3B; packet[len++] = (width & 0xFF); packet[len++] = (width >> 8); packet[len++] = (res & 0xFF); packet[len++] = (res >> 8); //PLAYER_MSG0(2, "sending set variant request to laser"); if (WriteToLaser(packet, len) < 0) return 1; // Wait for laser to return data //PLAYER_MSG0(2, "waiting for reply"); len = ReadFromLaser(packet, sizeof(packet), false, 10000); if (len < 0) return 1; else if (len < 1) { PLAYER_WARN("timeout"); continue; } else if (packet[0] == NACK) { PLAYER_ERROR("request denied by laser"); return 1; } else if (packet[0] != 0xBB) { PLAYER_ERROR("unexpected packet type"); return 1; } // See if the request was accepted if (packet[1] == 0) { PLAYER_ERROR("variant request ignored"); return 1; } break; } return (tries >= DEFAULT_LASER_RETRIES);}////////////////////////////////////////////////////////////////////////////////// Request data from the laser// Returns 0 on success//int SickLMS200::RequestLaserData(int min_segment, int max_segment){ int tries; ssize_t len; uint8_t packet[20]; for (tries = 0; tries < DEFAULT_LASER_RETRIES; tries++) { len = 0; packet[len++] = 0x20; /* mode change command */ if (min_segment == 0 && max_segment == 360) { // Use this for raw scan data... // packet[len++] = 0x24; } else { // Or use this for selected scan data... // int first = min_segment + 1; int last = max_segment + 1; packet[len++] = 0x27; packet[len++] = (first & 0xFF); packet[len++] = (first >> 8); packet[len++] = (last & 0xFF); packet[len++] = (last >> 8); } //PLAYER_MSG0(2, "sending scan data request to laser"); //printf("LASER: RLD: writing scan data\n"); if (WriteToLaser(packet, len) < 0) return 1; // Wait for laser to return ack // This should be fairly prompt len = ReadFromLaser(packet, sizeof(packet), true, 10000); if (len < 0) return 1; else if (len < 1) { PLAYER_WARN("timeout"); continue; } else if (packet[0] == NACK) { PLAYER_ERROR("request denied by laser"); return 1; } else if (packet[0] != ACK) { PLAYER_ERROR("unexpected packet type");; return 1; } break; } return (tries >= DEFAULT_LASER_RETRIES);}////////////////////////////////////////////////////////////////////////////////// Read range data from laser//int SickLMS200::ReadLaserData(uint16_t *data, size_t datalen){ uint8_t raw_data[1024]; // Read a packet from the laser // int len = ReadFromLaser(raw_data, sizeof(raw_data)); if (len == 0) { PLAYER_MSG0(2, "empty packet"); return 1; } // Process raw packets // if (raw_data[0] == 0xB0) { // Determine the number of values returned // //int units = raw_data[2] >> 6; int count = (int) raw_data[1] | ((int) (raw_data[2] & 0x3F) << 8); assert((size_t) count <= datalen); // Strip the status info and shift everything down a few bytes // to remove packet header. // for (int i = 0; i < count; i++) { int src = 2 * i + 3; data[i] = raw_data[src + 0] | (raw_data[src + 1] << 8); } } else if (raw_data[0] == 0xB7) { // Determine which values were returned // //int first = ((int) raw_data[1] | ((int) raw_data[2] << 8)) - 1; //int last = ((int) raw_data[3] | ((int) raw_data[4] << 8)) - 1; // Determine the number of values returned // //int units = raw_data[6] >> 6; int count = (int) raw_data[5] | ((int) (raw_data[6] & 0x3F) << 8); assert((size_t) count <= datalen); // Strip the status info and shift everything down a few bytes // to remove packet header. // for (int i = 0; i < count; i++) { int src = 2 * i + 7; data[i] = raw_data[src + 0] | (raw_data[src + 1] << 8); } } else RETURN_ERROR(1, "unexpected packet type"); return 0;}////////////////////////////////////////////////////////////////////////////////// Write a packet to the laser//ssize_t SickLMS200::WriteToLaser(uint8_t *data, ssize_t len){ uint8_t buffer[4 + 1024 + 2]; assert(4 + len + 2 < (ssize_t) sizeof(buffer)); // Create header // buffer[0] = STX; buffer[1] = 0; buffer[2] = LOBYTE(len); buffer[3] = HIBYTE(len); // Copy body // memcpy(buffer + 4, data, len); // Create footer (CRC) // uint16_t crc = CreateCRC(buffer, 4 + len); buffer[4 + len + 0] = LOBYTE(crc); buffer[4 + len + 1] = HIBYTE(crc); // Make sure both input and output queues are empty // tcflush(this->laser_fd, TCIOFLUSH); ssize_t bytes = 0;#ifdef HAVE_HI_SPEED_SERIAL struct timeval start, end; // have to write one char at a time, because if we're // high speed, then must take no longer than 55 us between // chars int ret; if (current_rate > 38400) { //printf("LASER: writing %d bytes\n", 6+len); for (int i =0; i < 6 + len; i++) { do { gettimeofday(&start, NULL); ret = ::write(this->laser_fd, buffer + i, 1); } while (!ret); if (ret > 0) { bytes += ret; } // need to do this sort of busy wait to ensure the right timing // although I've noticed you will get some anamolies that are // in the ms range; this could be a problem... int usecs; do { gettimeofday(&end, NULL); usecs= (end.tv_sec - start.tv_sec)*1000000 + (end.tv_usec - start.tv_usec); } while (usecs < 60); //printf("usecs: %d bytes=%02X\n", (end.tv_sec - start.tv_sec)*1000000 + // (end.tv_usec - start.tv_usec), *(buffer + i)); } } else { bytes = ::write( this->laser_fd, buffer, 4 + len + 2); }#else // Write the data to the port // bytes = ::write( this->laser_fd, buffer, 4 + len + 2);#endif // Make sure the queue is drained // Synchronous IO doesnt always work // ::tcdrain(this->laser_fd); // Return the actual number of bytes sent, including header and footer // return bytes;}////////////////////////////////////////////////////////////////////////////////// Read a packet from the laser// Set ack to true to ignore all packets except ack and nack// Set timeout to -1 to make this blocking, otherwise it will return in timeout ms.// Returns the packet length (0 if timeout occurs)//ssize_t SickLMS200::ReadFromLaser(uint8_t *data, ssize_t maxlen, bool ack, int timeout){ // If the timeout is infinite, // go to blocking io // if (timeout < 0) { //PLAYER_MSG0(2, "using blocking io"); int flags = ::fcntl(this->laser_fd, F_GETFL); if (flags < 0) { PLAYER_ERROR("unable to get device flags"); return 0; } if (::fcntl(this->laser_fd, F_SETFL, flags & (~O_NONBLOCK)) < 0) { PLAYER_ERROR("unable to set device flags"); return 0; } } // // Otherwise, use non-blocking io // else { //PLAYER_MSG0(2, "using non-blocking io"); int flags = ::fcntl(this->laser_fd, F_GETFL); if (flags < 0) { PLAYER_ERROR("unable to get device flags"); return 0; } if (::fcntl(this->laser_fd, F_SETFL, flags | O_NONBLOCK) < 0) { PLAYER_ERROR("unable to set device flags"); return 0; } } int64_t start_time = GetTime(); int64_t stop_time = start_time + timeout; //PLAYER_MSG2(2, "%Ld %Ld", start_time, stop_time); int bytes = 0; uint8_t header[5] = {0}; uint8_t footer[3]; // Read until we get a valid header // or we timeout // while (true) { if (timeout >= 0) usleep(1000); //printf("reading %d\n", timeout); fflush(stdout); bytes = ::read(this->laser_fd, header + sizeof(header) - 1, 1); //printf("bytes read %d\n", bytes); fflush(stdout); if (header[0] == STX && header[1] == 0x80) { if (!ack) break; if (header[4] == ACK || header[4] == NACK) break; } memmove(header, header + 1, sizeof(header) - 1); if (timeout >= 0 && GetTime() >= stop_time) { //PLAYER_MSG2(2, "%Ld %Ld", GetTime(), stop_time); //PLAYER_MSG0(2, "timeout on read (1)"); return 0; } } // Determine data length // Includes status, but not CRC, so subtract status to get data packet length. // ssize_t len = ((int) header[2] | ((int) header[3] << 8)) - 1; // Check for buffer overflows // if (len > maxlen) RETURN_ERROR(0, "buffer overflow (len > max_len)"); // Read in the data // Note that we smooge the packet type from the header // onto the front of the data buffer. // bytes = 0; data[bytes++] = header[4]; while (bytes < len) { if (timeout >= 0) usleep(1000); bytes += ::read(this->laser_fd, data + bytes, len - bytes); if (timeout >= 0 && GetTime() >= stop_time) { //PLAYER_MSG2(2, "%Ld %Ld", GetTime(), stop_time); RETURN_ERROR(0, "timeout on read (3)"); } } // Read in footer // bytes = 0; while (bytes < 3) { if (timeout >= 0) usleep(1000); bytes += ::read(this->laser_fd, footer + bytes, 3 - bytes); if (timeout >= 0 && GetTime() >= stop_time) { //PLAYER_MSG2(2, "%Ld %Ld", GetTime(), stop_time); RETURN_ERROR(0, "timeout on read (4)"); } } // Construct entire packet // And check the CRC // uint8_t buffer[4 + 1024 + 1]; assert(4 + len + 1 < (ssize_t) sizeof(buffer)); memcpy(buffer, header, 4); memcpy(buffer + 4, data, len); memcpy(buffer + 4 + len, footer, 1); uint16_t crc = CreateCRC(buffer, 4 + len + 1); if (crc != MAKEUINT16(footer[1], footer[2])) RETURN_ERROR(0, "CRC error, ignoring packet"); return len;} ////////////////////////////////////////////////////////////////////////////////// Create a CRC for the given packet//unsigned short SickLMS200::CreateCRC(uint8_t* data, ssize_t len){ uint16_t uCrc16; uint8_t abData[2]; uCrc16 = 0; abData[0] = 0; while(len-- ) { abData[1] = abData[0]; abData[0] = *data++; if( uCrc16 & 0x8000 ) { uCrc16 = (uCrc16 & 0x7fff) << 1; uCrc16 ^= CRC16_GEN_POL; } else { uCrc16 <<= 1; } uCrc16 ^= MAKEUINT16(abData[0],abData[1]); } return (uCrc16); }////////////////////////////////////////////////////////////////////////////////// Get the time (in ms)//int64_t SickLMS200::GetTime(){ struct timeval tv; //gettimeofday(&tv, NULL); GlobalTime->GetTime(&tv); return (int64_t) tv.tv_sec * 1000 + (int64_t) tv.tv_usec / 1000;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -