📄 sicks3000.cc
字号:
/* * Player - One Hell of a Robot Server * Copyright (C) 2000 * Brian Gerkey, Kasper Stoy, Richard Vaughan, & Andrew Howard * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * *//* Desc: Driver for the SICK S3000 laser Author: Toby Collett (based on lms200 by Andrew Howard) Date: 7 Nov 2000 CVS: $Id: sicks3000.cc,v 1.1.2.1 2006/09/22 23:58:35 gerkey Exp $*//** @ingroup drivers Drivers *//** @{ *//** @defgroup driver_sicks3000 sicks3000 * @brief SICK S 3000 laser range-finderThe sicks3000 driver controls the SICK S 3000 safety laser scanner interpreting its data output.The driver is very basic and assumes the S3000 has already been configured to continuously outputits measured data on the RS422 data lines.It is also assumed that the laser is outputing its full 190 degree scan in a single scanning block.@par Compile-time dependencies- none@par Provides- @ref interface_laser@par Requires- none@par Configuration requests- PLAYER_LASER_REQ_GET_GEOM- PLAYER_LASER_REQ_GET_CONFIG @par Configuration file options- port (string) - Default: "/dev/ttyS0" - Serial port to which laser is attached. If you are using a USB/232 or USB/422 converter, this will be "/dev/ttyUSBx".- transfer_rate (integer) - Rate desired for data transfers, negotiated after connection - Default: 38400 - Baud rate. Valid values are 9600, 19200, 38400, 125k, 250k, 500k- pose (length tuple) - Default: [0.0 0.0 0.0] - Pose (x,y,theta) of the laser, relative to its parent object (e.g., the robot to which the laser is attached).- size (length tuple) - Default: [0.15 0.15] - Footprint (x,y) of the laser. @par Example @verbatimdriver( name "sicks3000" provides ["laser:0"] port "/dev/ttyS0")@endverbatim@author Toby Collett*//** @} */ #if HAVE_CONFIG_H #include <config.h>#endif#include <assert.h>#include <math.h>#include <errno.h>#include <fcntl.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>#include <sys/stat.h>#include <termios.h>#include <unistd.h>#include <sys/ioctl.h>#include <arpa/inet.h> // for htons etc#undef HAVE_HI_SPEED_SERIAL#ifdef HAVE_LINUX_SERIAL_H #ifndef DISABLE_HIGHSPEEDSICK #include <linux/serial.h> #define HAVE_HI_SPEED_SERIAL #endif#endif#include <libplayercore/playercore.h>#include <replace/replace.h>extern PlayerTime* GlobalTime;#define DEFAULT_LASER_PORT "/dev/ttyS0"#define DEFAULT_LASER_TRANSFER_RATE 38400#define RX_BUFFER_SIZE 4096// The laser device class.class SickS3000 : public Driver{ public: // Constructor SickS3000(ConfigFile* cf, int section); ~SickS3000(); int Setup(); int Shutdown(); // MessageHandler int ProcessMessage(MessageQueue * resp_queue, player_msghdr * hdr, void * data); private: // Main function for device thread. virtual void Main(); // Open the terminal // Returns 0 on success int OpenTerm(); // Close the terminal // Returns 0 on success int CloseTerm(); // Set the terminal speed // can be any value valid for the s3000 // Returns 0 on success int ChangeTermSpeed(int speed); // Set the laser data rate // Valid values are 9600 and 38400 // Returns 0 on success int SetLaserSpeed(int speed); // Read range data from laser int ReadLaserData(); // Process range data from laser int ProcessLaserData(); // Calculates CRC for a telegram unsigned short CreateCRC(uint8_t *data, ssize_t len); // Get the time (in ms) int64_t GetTime(); protected: // Laser pose in robot cs. double pose[3]; double size[2]; // Name of device used to communicate with the laser const char *device_name; // laser device file descriptor int laser_fd; // Scan width and resolution. int scan_width, scan_res; // Start and end scan angles (for restricted scan). These are in // units of 0.01 degrees. int min_angle, max_angle; // Start and end scan segments (for restricted scan). These are // the values used by the laser. int scan_min_segment, scan_max_segment; // Range resolution (1 = 1mm, 10 = 1cm, 100 = 10cm). int range_res; // Turn intensity data on/off bool intensity; // Is the laser upside-down? (if so, we'll reverse the ordering of the // readings) int invert; bool can_do_hi_speed; int connect_rate; // Desired rate for first connection int transfer_rate; // Desired rate for operation int current_rate; // Current rate int scan_id; // rx buffer uint8_t * rx_buffer; unsigned int rx_buffer_size; unsigned int rx_count; // storage for outgoing data player_laser_data_t data_packet; player_laser_config_t config_packet; #ifdef HAVE_HI_SPEED_SERIAL struct serial_struct old_serial;#endif};// a factory creation functionDriver* SickS3000_Init(ConfigFile* cf, int section){ return((Driver*)(new SickS3000(cf, section)));}// a driver registration functionvoid SickS3000_Register(DriverTable* table){ table->AddDriver("sicks3000", SickS3000_Init);}////////////////////////////////////////////////////////////////////////////////// Device codes#define STX 0x02#define ACK 0xA0#define NACK 0x92#define CRC16_GEN_POL 0x8005////////////////////////////////////////////////////////////////////////////////// Error macros#define RETURN_ERROR(erc, m) {PLAYER_ERROR(m); return erc;} ////////////////////////////////////////////////////////////////////////////////// ConstructorSickS3000::SickS3000(ConfigFile* cf, int section) : Driver(cf, section, true, PLAYER_MSGQUEUE_DEFAULT_MAXLEN, PLAYER_LASER_CODE){ // allocate our recieve buffer rx_buffer_size = RX_BUFFER_SIZE; rx_buffer = new uint8_t[rx_buffer_size]; assert(rx_buffer); memset(&data_packet,0,sizeof(data_packet)); data_packet.min_angle = DTOR(-95); data_packet.max_angle = DTOR(95); data_packet.resolution = DTOR(0.25); data_packet.max_range = 49; memset(&config_packet,0,sizeof(config_packet)); config_packet.min_angle = DTOR(-95); config_packet.max_angle = DTOR(95); config_packet.resolution = DTOR(0.25); config_packet.max_range = 49; // Laser geometry. this->pose[0] = cf->ReadTupleLength(section, "pose", 0, 0.0); this->pose[1] = cf->ReadTupleLength(section, "pose", 1, 0.0);; this->pose[2] = cf->ReadTupleLength(section, "pose", 2, 0.0);; this->size[0] = 0.15; this->size[1] = 0.15; // Serial port this->device_name = cf->ReadString(section, "port", DEFAULT_LASER_PORT); // Serial rate this->transfer_rate = cf->ReadInt(section, "transfer_rate", DEFAULT_LASER_TRANSFER_RATE); this->current_rate = 0;#ifdef HAVE_HI_SPEED_SERIAL this->can_do_hi_speed = true;#else this->can_do_hi_speed = false;#endif if (!this->can_do_hi_speed && this->transfer_rate > 38400) { PLAYER_ERROR1("sicklms200: requested hi speed serial, but no support compiled in. Defaulting to %d bps.", DEFAULT_LASER_TRANSFER_RATE); this->connect_rate = DEFAULT_LASER_TRANSFER_RATE; } return;}SickS3000::~SickS3000(){ delete [] rx_buffer; }////////////////////////////////////////////////////////////////////////////////// Set up the deviceint SickS3000::Setup(){ PLAYER_MSG1(2, "Laser initialising (%s)", this->device_name); // Open the terminal if (OpenTerm()) return 1; if (ChangeTermSpeed(this->transfer_rate)) { return 1; } PLAYER_MSG0(2, "laser ready"); // Start the device thread StartThread(); return 0;}////////////////////////////////////////////////////////////////////////////////// Shutdown the deviceint SickS3000::Shutdown(){ // shutdown laser device StopThread(); CloseTerm(); PLAYER_MSG0(2, "laser shutdown"); return(0);}int SickS3000::ProcessMessage(MessageQueue * resp_queue, player_msghdr * hdr, void * data){ 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); } this->Publish(this->device_addr, resp_queue, PLAYER_MSGTYPE_RESP_ACK, PLAYER_LASER_REQ_GET_CONFIG, (void*)&config_packet, sizeof(config_packet), 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];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -