📄 sicklms200.cc
字号:
resp_queue, PLAYER_MSGTYPE_RESP_ACK, PLAYER_LASER_REQ_SET_CONFIG, data, hdr->size, NULL); // Return 0 to say that we handled this message return(0); } else if (Message::MatchMessage(hdr, PLAYER_MSGTYPE_REQ, PLAYER_LASER_REQ_GET_CONFIG, this->device_addr)) { if(hdr->size != 0) { PLAYER_ERROR2("request is wrong length (%d != %d); ignoring", hdr->size, 0); return(-1); } player_laser_config_t config; config.intensity = this->intensity; config.resolution = DTOR(this->scan_res)/100; config.min_angle = DTOR(this->min_angle)/100; config.max_angle = DTOR(this->max_angle)/100; if(this->range_res == 1) config.max_range = 8.0; else if(this->range_res == 10) config.max_range = 80.0; else if(this->range_res == 100) config.max_range = 150.0; else { PLAYER_WARN("Invalid range_res!"); config.max_range = 8.0; } config.range_res = ((double)this->range_res)/1000.0; this->Publish(this->device_addr, resp_queue, PLAYER_MSGTYPE_RESP_ACK, PLAYER_LASER_REQ_GET_CONFIG, (void*)&config, sizeof(config), NULL); return(0); } else if (Message::MatchMessage(hdr, PLAYER_MSGTYPE_REQ, PLAYER_LASER_REQ_GET_GEOM, this->device_addr)) { if(hdr->size != 0) { PLAYER_ERROR2("request is wrong length (%d != %d); ignoring", hdr->size, 0); return(PLAYER_MSGTYPE_RESP_NACK); } player_laser_geom_t geom; geom.pose.px = this->pose[0]; geom.pose.py = this->pose[1]; geom.pose.pa = this->pose[2]; geom.size.sl = this->size[0]; geom.size.sw = this->size[1]; this->Publish(this->device_addr, resp_queue, PLAYER_MSGTYPE_RESP_ACK, PLAYER_LASER_REQ_GET_GEOM, (void*)&geom, sizeof(geom), NULL); return(0); } // Don't know how to handle this message. return(-1);}////////////////////////////////////////////////////////////////////////////////// Main function for device threadvoid SickLMS200::Main() { int itmp; float tmp; bool first = true; // Ask the laser to send data if (RequestLaserData(this->scan_min_segment, this->scan_max_segment) != 0) { PLAYER_ERROR("laser not responding; exiting laser thread"); return; } while(true) { // test if we are supposed to cancel pthread_testcancel(); ProcessMessages(); // Get the time at which we started reading // This will be a pretty good estimate of when the phenomena occured double time; GlobalTime->GetTimeDouble(&time); // Process incoming data uint16_t mm_ranges[PLAYER_LASER_MAX_SAMPLES]; if (ReadLaserData(mm_ranges, PLAYER_LASER_MAX_SAMPLES) == 0) { player_laser_data_t data; if (first) { PLAYER_MSG0(2, "receiving data"); first = false; } // Prepare packet data.min_angle = DTOR((this->scan_min_segment * this->scan_res) / 1e2 - this->scan_width / 2.0); data.max_angle = DTOR((this->scan_max_segment * this->scan_res) / 1e2 - this->scan_width / 2.0); if(this->range_res == 1) data.max_range = 8.0; else if(this->range_res == 10) data.max_range = 80.0; else if(this->range_res == 100) data.max_range = 150.0; else { PLAYER_WARN("Invalid range_res!"); data.max_range = 8.0; } data.resolution = DTOR(this->scan_res / 1e2); data.ranges_count = data.intensity_count = this->scan_max_segment - this->scan_min_segment + 1; for (int i = 0; i < this->scan_max_segment - this->scan_min_segment + 1; i++) { data.intensity[i] = ((mm_ranges[i] >> 13) & 0x0007); data.ranges[i] = (mm_ranges[i] & 0x1FFF) * this->range_res / 1e3; } // if the laser is upside-down, reverse the data and intensity // arrays, in place. this could probably be made more efficient by // burying it in a lower-level loop where the data is being read, but // i can't be bothered to figure out where. if(this->invert) { for (int i = 0; i < (this->scan_max_segment - this->scan_min_segment + 1)/2; i++) { tmp=data.ranges[i]; data.ranges[i]=data.ranges[this->scan_max_segment-this->scan_min_segment-i]; data.ranges[this->scan_max_segment-this->scan_min_segment-i] = tmp; itmp=data.intensity[i]; data.intensity[i]=data.intensity[this->scan_max_segment-this->scan_min_segment-i]; data.intensity[this->scan_max_segment-this->scan_min_segment-i] = itmp; } } data.id = this->scan_id++; // Make data available this->Publish(this->device_addr, NULL, PLAYER_MSGTYPE_DATA, PLAYER_LASER_DATA_SCAN, (void*)&data, sizeof(data), &time); } }}////////////////////////////////////////////////////////////////////////////////// Compute the start and end scan segments based on the current resolution and// scan angles. Returns 0 if the configuration is valid.int SickLMS200::CheckScanConfig(){ if (this->scan_res == 25) { // For high res, drop the scan range down to 100 degrees. // The angles must be interpreted differently too. this->scan_width = 100; this->scan_min_segment = (this->min_angle + 5000) / this->scan_res; this->scan_max_segment = (this->max_angle + 5000) / this->scan_res; if (this->scan_min_segment < 0) this->scan_min_segment = 0; if (this->scan_min_segment > 400) this->scan_min_segment = 400; if (this->scan_max_segment < 0) this->scan_max_segment = 0; if (this->scan_max_segment > 400) this->scan_max_segment = 400; return 0; } else if (this->scan_res == 50 || this->scan_res == 100) { this->scan_width = 180; this->scan_min_segment = (this->min_angle + 9000) / this->scan_res; this->scan_max_segment = (this->max_angle + 9000) / this->scan_res; if (this->scan_min_segment < 0) this->scan_min_segment = 0; if (this->scan_min_segment > 360) this->scan_min_segment = 360; if (this->scan_max_segment < 0) this->scan_max_segment = 0; if (this->scan_max_segment > 360) this->scan_max_segment = 360; return 0; } if (!(this->range_res == 1 || this->range_res == 10 || this->range_res == 100)) return -1; return 0;}////////////////////////////////////////////////////////////////////////////////// Open the terminal// Returns 0 on successint SickLMS200::OpenTerm(){ this->laser_fd = ::open(this->device_name, O_RDWR | O_SYNC , S_IRUSR | S_IWUSR ); if (this->laser_fd < 0) { PLAYER_ERROR2("unable to open serial port [%s]; [%s]", (char*) this->device_name, strerror(errno)); return 1; } // set the serial port speed to 9600 to match the laser // later we can ramp the speed up to the SICK's 38K // struct termios term; if( tcgetattr( this->laser_fd, &term ) < 0 ) RETURN_ERROR(1, "Unable to get serial port attributes"); cfmakeraw( &term ); cfsetispeed( &term, B9600 ); cfsetospeed( &term, B9600 ); if( tcsetattr( this->laser_fd, TCSAFLUSH, &term ) < 0 ) RETURN_ERROR(1, "Unable to set serial port attributes"); // Make sure queue is empty // tcflush(this->laser_fd, TCIOFLUSH); return 0;}////////////////////////////////////////////////////////////////////////////////// Close the terminal// Returns 0 on success//int SickLMS200::CloseTerm(){ /* REMOVE#ifdef HAVE_HI_SPEED_SERIAL if (ioctl(this->laser_fd, TIOCSSERIAL, &this->old_serial) < 0) { //RETURN_ERROR(1, "error trying to reset serial to old state"); PLAYER_WARN("ioctl() failed while trying to reset serial to old state"); }#endif */ ::close(this->laser_fd); return 0;}////////////////////////////////////////////////////////////////////////////////// Set the terminal speed// Valid values are 9600 and 38400// Returns 0 on success//int SickLMS200::ChangeTermSpeed(int speed){ struct termios term; current_rate = speed;#ifdef HAVE_HI_SPEED_SERIAL struct serial_struct serial; // we should check and reset the AYSNC_SPD_CUST flag // since if it's set and we request 38400, we're likely // to get another baud rate instead (based on custom_divisor) // this way even if the previous player doesn't reset the // port correctly, we'll end up with the right speed we want if (ioctl(this->laser_fd, TIOCGSERIAL, &serial) < 0) { //RETURN_ERROR(1, "error on TIOCGSERIAL in beginning"); PLAYER_WARN("ioctl() failed while trying to get serial port info"); } else { serial.flags &= ~ASYNC_SPD_CUST; serial.custom_divisor = 0; if (ioctl(this->laser_fd, TIOCSSERIAL, &serial) < 0) { //RETURN_ERROR(1, "error on TIOCSSERIAL in beginning"); PLAYER_WARN("ioctl() failed while trying to set serial port info"); } }#endif //printf("LASER: change TERM speed: %d\n", speed); switch(speed) { case 9600: //PLAYER_MSG0(2, "terminal speed to 9600"); if( tcgetattr( this->laser_fd, &term ) < 0 ) RETURN_ERROR(1, "unable to get device attributes"); cfmakeraw( &term ); cfsetispeed( &term, B9600 ); cfsetospeed( &term, B9600 ); if( tcsetattr( this->laser_fd, TCSAFLUSH, &term ) < 0 ) RETURN_ERROR(1, "unable to set device attributes"); break; case 38400: //PLAYER_MSG0(2, "terminal speed to 38400"); if( tcgetattr( this->laser_fd, &term ) < 0 ) RETURN_ERROR(1, "unable to get device attributes"); cfmakeraw( &term ); cfsetispeed( &term, B38400 ); cfsetospeed( &term, B38400 ); if( tcsetattr( this->laser_fd, TCSAFLUSH, &term ) < 0 ) RETURN_ERROR(1, "unable to set device attributes"); break; case 500000: //PLAYER_MSG0(2, "terminal speed to 500000");#ifdef HAVE_HI_SPEED_SERIAL if (ioctl(this->laser_fd, TIOCGSERIAL, &this->old_serial) < 0) { RETURN_ERROR(1, "error on TIOCGSERIAL ioctl"); } serial = this->old_serial; serial.flags |= ASYNC_SPD_CUST; serial.custom_divisor = 48; // for FTDI USB/serial converter divisor is 240/5 if (ioctl(this->laser_fd, TIOCSSERIAL, &serial) < 0) { RETURN_ERROR(1, "error on TIOCSSERIAL ioctl"); } #else fprintf(stderr, "sicklms200: Trying to change to 500kbps, but no support compiled in, defaulting to 38.4kbps.\n");#endif // even if we are doing 500kbps, we have to set the speed to 38400... // the driver will know we want 500000 instead. if( tcgetattr( this->laser_fd, &term ) < 0 ) RETURN_ERROR(1, "unable to get device attributes"); cfmakeraw( &term ); cfsetispeed( &term, B38400 ); cfsetospeed( &term, B38400 ); if( tcsetattr( this->laser_fd, TCSAFLUSH, &term ) < 0 ) RETURN_ERROR(1, "unable to set device attributes"); break; default: PLAYER_ERROR1("unknown speed %d", speed); } return 0;} ////////////////////////////////////////////////////////////////////////////////// Put the laser into configuration mode//int SickLMS200::SetLaserMode(){ int tries; ssize_t len; uint8_t packet[20]; for (tries = 0; tries < DEFAULT_LASER_RETRIES; tries++) { packet[0] = 0x20; /* mode change command */ packet[1] = 0x00; /* configuration mode */ packet[2] = 0x53; // S - the password packet[3] = 0x49; // I packet[4] = 0x43; // C packet[5] = 0x4B; // K packet[6] = 0x5F; // _ packet[7] = 0x4C; // L packet[8] = 0x4D; // M packet[9] = 0x53; // S len = 10; PLAYER_MSG0(2, "sending configuration mode request to laser"); if (WriteToLaser(packet, len) < 0) return 1; // Wait for laser to return ack // This could take a while... // PLAYER_MSG0(2, "waiting for acknowledge"); 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);}////////////////////////////////////////////////////////////////////////////////// Set the laser data rate// Valid values are 9600 and 38400// Returns 0 on success//int SickLMS200::SetLaserSpeed(int speed){ int tries; ssize_t len; uint8_t packet[20]; for (tries = 0; tries < DEFAULT_LASER_RETRIES; tries++) { packet[0] = 0x20; packet[1] = (speed == 9600 ? 0x42 : (speed == 38400 ? 0x40 : 0x48)); len = 2; //PLAYER_MSG0(2, "sending baud rate request to laser"); if (WriteToLaser(packet, len) < 0) return 1; // Wait for laser to return ack //PLAYER_MSG0(2, "waiting for acknowledge"); len = ReadFromLaser(packet, sizeof(packet), true, 20000); if (len < 0) return 1; else if (len < 1) { PLAYER_ERROR("no reply from laser"); return 1; } 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);}////////////////////////////////////////////////////////////////////////////////// Get the laser type//int SickLMS200::GetLaserType(char *buffer, size_t bufflen){ int tries; ssize_t len; uint8_t packet[512]; for (tries = 0; tries < DEFAULT_LASER_RETRIES; tries++) { packet[0] = 0x3A; len = 1; //PLAYER_MSG0(2, "sending get type request to laser"); if (WriteToLaser(packet, len) < 0) return 1; // Wait for laser to return data 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] != 0xBA) { PLAYER_ERROR("unexpected packet type"); return 1; } // NULL terminate the return string assert((size_t) len < sizeof(packet)); packet[len] = 0; // Copy to buffer assert(bufflen >= (size_t) len - 1); strcpy(buffer, (char*) (packet + 1)); break; } return (tries >= DEFAULT_LASER_RETRIES);}////////////////////////////////////////////////////////////////////////////////// Set the laser configuration// Returns 0 on success//int SickLMS200::SetLaserConfig(bool intensity){ int tries; ssize_t len; uint8_t packet[512];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -