/*---------------------------------------------------------------
	FILE: CSickLaserUSB.h

   Part of the MRPT Library
   ISA - Universidad de Malaga - http://www.isa.uma.es
  ---------------------------------------------------------------*/
#ifndef CSickLaserUSB_H
#define CSickLaserUSB_H

#include <MRPT/HWDRIVERS/C2DRangeFinderAbstract.h>
#include <MRPT/HWDRIVERS/CInterfaceFTDI.h>

namespace HWDRIVERS
{
	/** This "software driver" implements the communication protocol for interfacing a SICK LMS200 laser scanners through a custom USB RS-422 interface board.
      *   This class does not need to be bind, i.e. you do not need to call C2DRangeFinderAbstract::bindIO. However, calling it will have not effect.
	  *   In this class the "bind" is ignored since it is designed for USB connections only, thus it internally generate the required object for simplicity of use.
	  *   The serial number of the USB device is used to open it on the first call to "doProcess", thus you must call "loadConfig" before this, or manually
	  *     call "setDeviceSerialNumber". The default serial number is "LASER001"
	  *
	  * Warning: Avoid defining an object of this class in a global scope if you want to catch all potential
	  *      exceptions during the constructors (like USB interface DLL not found, etc...)
	  *
	  *
	  *  \code
	  *  PARAMETERS IN THE ".INI"-LIKE CONFIGURATION STRINGS:
	  * -------------------------------------------------------
	  *   [supplied_section_name]
	  *   SICKUSB_serialNumber=LASER001
	  *   pose_x=0.21	; Laser range scaner 3D position in the robot (meters)
	  *   pose_y=0
	  *   pose_z=0.34
	  *   pose_yaw=0	; Angles in degrees
	  *   pose_pitch=0
	  *   pose_roll=0
	  *  \endcode
	  *
	  */
	class CSickLaserUSB : public C2DRangeFinderAbstract
	{
	private:
		CInterfaceFTDI		*m_usbConnection;
		std::string			m_serialNumber;

		/** The sensor 6D pose:
		  */
		MRML::CPose3D		m_sensorPose;

		static int			CRC16_GEN_POL;

		bool 		checkControllerIsConnected();
		bool  	waitContinuousSampleFrame( short ranges[361], unsigned char &LMS_status );
		short 	computeCRC(unsigned char *data, unsigned long len);

	public:
		/** Constructor
		  */
		CSickLaserUSB();

		/** Destructor
		  */
		~CSickLaserUSB();

		/** Changes the serial number of the device to open (call prior to 'doProcess')
		  */
		void  setDeviceSerialNumber(const std::string &deviceSerialNumber)
		{
			m_serialNumber = deviceSerialNumber;
		}

		/** Specific laser scanner "software drivers" must process here new data from the I/O stream, and, if a whole scan has arrived, return it.
		  *  This method will be typically called in a different thread than other methods, and will be called in a timely fashion.
		  */
		void  doProcess(
			bool							&outThereIsObservation,
			MRML::CObservation2DRangeScan	&outObservation,
			bool							&hardwareError );

		/** Loads specific configuration for the device from a given source of configuration parameters, for example, an ".ini" file, loading from the section "[iniSection]" (see UTILS::CConfigFileBase and derived classes)
		  *  See HWDRIVERS::CSickLaserUSB for the possible parameters
		  */
		void  loadConfig(
			const CConfigFileBase *configSource,
			const std::string	  &iniSection );

		/** Enables the scanning mode (in this class this has no effect).
		  * \return If everything works "true", or "false" if there is any error.
		  */
		bool  turnOn();

		/** Disables the scanning mode (in this class this has no effect).
		  * \return If everything works "true", or "false" if there is any error.
		  */
		bool  turnOff();

	};	// End of class

} // End of namespace


#endif
