//## begin module%1.4%.codegen_version preserve=yes
//   Read the documentation to learn more about C++ code generator
//   versioning.
//## end module%1.4%.codegen_version

//## begin module%3D86D3570320.cm preserve=no
//	  %X% %Q% %Z% %W%
//## end module%3D86D3570320.cm

//## begin module%3D86D3570320.cp preserve=no
//## end module%3D86D3570320.cp

//## Module: SIR%3D86D3570320; Pseudo Package specification
//## Source file: C:\Program Files\Rational\Rose\C++\source\SIR.h

#ifndef SIR_h
#define SIR_h 1

//## begin module%3D86D3570320.additionalIncludes preserve=no
//## end module%3D86D3570320.additionalIncludes

//## begin module%3D86D3570320.includes preserve=yes
//## end module%3D86D3570320.includes

// ImageFilter
#include "ImageFilter.h"
// PSDs
#include "PSDs.h"
// Camera
#include "Camera.h"
// Drive
#include "Drive.h"
// Thread
#include "Thread.h"
//## begin module%3D86D3570320.additionalDeclarations preserve=yes
//## end module%3D86D3570320.additionalDeclarations


//## begin SIR%3D86D3570320.preface preserve=yes
//## end SIR%3D86D3570320.preface

//## Class: SIR%3D86D3570320
//	/**
//	This class (Sensor and Image Recognition) provides
//	high-level information to the behaviors by
//	pre-processing the data internally. The provided
//	information includes current obstacle distances as
//	received by the infra-red sensors. But in particular
//	information about the locations of cubes and robots that
//	are visible on camera are provided.
//	As all behaviors should use the same SIR thread this class
//	is designed as a singleton class. So at any given time there
//	is at most one instance of the class. The method SIR::getSIR()
//	is used to access that instance.
//	@author Jia L. Du.
//	*/
//## Category: <Top Level>
//## Persistence: Transient
//## Cardinality/Multiplicity: n



class SIR : public Thread  //## Inherits: <unnamed>%3D86D5A002BC
{
  //## begin SIR%3D86D3570320.initialDeclarations preserve=yes
  //## end SIR%3D86D3570320.initialDeclarations

  public:
    //## Other Operations (specified)
      //## Operation: obstacleLeft%3D9296DA015E
      //	/**
      //	Indicates whether an obstacle is detected by the left
      //	infra-red sensor
      //	@return true if there is an obstacle
      //	*/
      bool obstacleLeft ();

      //## Operation: obstacleRight%3D9296F8000A
      //	/**
      //	Indicates whether an obstacle is detected by the right
      //	infra-red sensor
      //	@return true if there is an obstacle
      //	*/
      bool obstacleRight ();

      //## Operation: obstacleFront%3D9296F801C2
      //	/**
      //	Indicates whether an obstacle is detected by the front
      //	infra-red sensor
      //	@return true if there is an obstacle
      //	*/
      bool obstacleFront ();

      //## Operation: getLeftMargin%3D99481C028A
      //	/**
      //	Returns the distance from the robot to the next object
      //	to the left
      //	@return distance in meter
      //	*/
      double getLeftMargin ();

      //## Operation: getRightMargin%3D9948230082
      //	/**
      //	Returns the distance from the robot to the next object
      //	to the  right
      //	@return distance in meter
      //	*/
      double getRightMargin ();

      //## Operation: getFrontMargin%3D99482B0096
      //	/**
      //	Returns the distance from the robot to the next object
      //	in the front
      //	@return distance in meter
      //	*/
      double getFrontMargin ();

      //## Operation: robotDetected%3D99453C024E
      //	/**
      //	Indicates if a robot is currently visible on the camera
      //	@return true if a robot is on the camera
      //	*/
      bool robotDetected ();

      //## Operation: cubeDetected%3D994557000A
      //	/**
      //	Indicates if a cube is currently visible on the camera
      //	@return true if a cube is on the camera
      //	*/
      bool cubeDetected ();

      //## Operation: getRobotPosition%3D99488A033E
      //	/**
      //	Passes the last known position of the last detected
      //	robot. If no robot has been detected yet (0,0,0) is
      //	passed. SIR::robotDetected() should be used before
      //	calling this method to check if the data is up to date
      //	(i.e. the robot whose position is passed is indeed still
      //	visible). If more than one robot was detected on the
      //	image the position of the closest robot is passed
      //	*/
      void getRobotPosition (double& x, double& y, double& phi);

      //## Operation: getGlobalCubePosition%3D9948740168
      //	/**
      //	Passes the last known position of the last detected
      //	cube in global coordinates (i.e. with (0,0) and not the
      //  current robot position as origin). If no cube has been detected yet
      //  (0,0) is passed. SIR::cubeDetected() should be used before
      //	calling this method to check if the data is up to date
      //	(i.e. the cube whose position is passed is indeed still
      //	visible). If more than one cube was detected on the
      //	image the position of the closest cube is passed
      //	*/
      void getGlobalCubePosition (double& x, double& y);

      //## Operation: getDensity%3D9948C90294
      //	/**
      //	Estimates the cube density in the image by counting the
      //	pixels that have the cube color
      //  @param density The value can range from 0.0 (no cubes) to 1.0
      //	(all camera pixels have the cube color)
      //  @param centerOfDensityX x coordinate of the estimated center of the cube cluster
      //  relative to the current robot position
      //  @param centerOfDensityY y coordinate of the estimated center of the cube cluster
      //  relative to the current robot position
      //	*/
      void getDensity (double& density, double& centerOfDensityX, double& centerOfDensityY);

      //## Operation: setCubeSize%3D9972CE0334
      //	/**
      //	Not used yet
      //	*/
      void setCubeSize (int size);

      //## Operation: setCubeColor%3D9972EE00F0
      //	/**
      //	Not used yet
      //	*/
      void setCubeColor (int color);

    // Additional Public Declarations
      //## begin SIR%3D86D3570320.public preserve=yes
      //	/**
      //	This method is used to get the instance of this
      //	singleton class
      //	@return A pointer to the instance
      //	 */
      static SIR* getSIR ();

      //	/**
      //	Indicates whether an obstacle is detected by
      //	any of the infra-red sensors
      //	@return true if there is an obstacle
      //	*/
      bool obstacle (void);

      //	/**
      //	According to C++ convention, methods cannot be static and
      //	virtual at once. In the initial design run was declared as
      //	virtual which results in dynamic binding. That means the
      //	program determines at run-time which run method to use,
      //	the one of the Thread base class or the one of the inheritor.
      //	Because we have to use staticRun, we cannot use the virtual
      //	keyword anymore. Without the virtual keyword the compiler
      //	determines at compile-time which run method is used, always
      //	the run method of the Thread base class. To ensure that the
      //	inheritor indeed uses its own run method, it is necessary to
      //	overwrite the thread initialization method (spawn) as well.
      //	@see staticRun
      //	@return true if successful
      //	*/
      bool spawn ();


      //	/**
      //	Passes the last known position of the last detected
      //	cube in local coordinates. If no cube has been detected yet
      //  (0,0) is passed.
      //  As the position is passed in local coordinates
      //  (that is the relative distance from cube to robot
      //  at the time when the image - on which the cube was detected -
      //  was taken) this information expires quickly.
      //  SIR::cubeDetected() should definitely be used before
      //	calling this method to check if the data is up to date
      //	(i.e. the cube whose position is passed is indeed still
      //	visible). If more than one cube was detected on the
      //	image the position of the closest cube is passed
      //	*/
      void getLocalCubePosition (double& x, double& y);
      //## end SIR%3D86D3570320.public

  protected:
    //## Constructors (specified)
      //## Operation: SIR%3D9EBF620046
      //	/**
      //	Constructor for SIR. The parameters are passed to the
      //	Thread constructor
      //	@param name pointer to thread name
      //	@param stackSize size of thread stack
      //	@param priority thread priority (valid values are: MIN_
      //	PRI to MAX_PRI)
      //	@param id a unique thread id
      //	 */
      SIR (char* name, int stackSize, int priority, int id);


    // Additional Protected Declarations
      //## begin SIR%3D86D3570320.protected preserve=yes
      void run(void); //protected or private??
      
      //	/**
      //	Static wrapper method for run. It does nothing but to call run.
      //	That is necessary because the RoBIOS multi-tasking functions expect
      //	a pointer to a C-function (not a pointer to a C++ method) containing
      //	the code to be executed. Fortunately, pointer-to-static-C++-methods
      //	are compatible with regular pointer-to-C-functions. But the problem
      //	is that static methods can only use other static methods and variables.
      //	The reasons is that a static method, which is shared by all instances,
      //	would not know which non-static method or variable to use if there were
      //	multiple instances of the same class. Thus, the static property would
      //	have to be applied to all used (sub-)methods and (sub-) variables,
      //	and propagate through the whole class structure. By using staticRun,
      //	we can keep using our non-static run. If static methods cannot call
      //	non-static ones, how can staticRun call run? As aforementioned the
      //	reason why static method cannot use non-static members is because it
      //	is not clear which non-static member to use if there are multiple
      //	instances of the same class. That means staticRun needs a pointer
      //	to the instance whose run method is to be called. This pointer is
      //	stored in a static member variable called me.
      //	@see me
      //	*/
      static void staticRun(void); //protected or private??
      //## end SIR%3D86D3570320.protected

  private:

    //## Other Operations (specified)
      //## Operation: takePicture%3D9948FB03D4
      //	/**
      //	Gets a new image from the camera
			//	and stores it in currentImage
			//	@see currentImage
      //	*/
      void takePicture ();

      //## Operation: takeColorPicture%3D9FC00D014A
      //	/**
      //	Gets a new color image from the camera
			//	and stores it in currentColorImage
			//	@see currentColorImage
      //	*/
      void takeColorPicture ();

      //## Operation: detectCubes%3D99479F0168
      //	/**
      //	Tries to detect cubes in the current color image
      //	@see currentColorImage
      //	@return true if at least one cube was detected
      //	*/
      bool detectCubes ();

      //## Operation: detectRobots%3D9947AD00C8
      //	/**
      //	Tries to detect robots in the current image
      //	@see currentImage
      //	@return true if at least one robot was detected
      //	*/
      bool detectRobots ();

    // Additional Private Declarations

      //## begin SIR%3D86D3570320.private preserve=yes


      //	/**
      //	Stores a pointer to an instance of SIR
      //	@see staticRun
      //	*/
      static SIR* me;

      //	/**
      //	The single instance that exists of this class
      //	@see SIR::getSIR()
      //	*/
      static SIR aSIR;

      //	/**
	  	//Camera dependent lookup table.
			//Factor to get x position in meters from x position in pixels.
			//62 values, one for each row. 0 and 61 not used by me.
			//Example: something is in row 1.
			//Distance from the robot = 0.460m = row2Meter[1].
			//Something is in row 60.
			//Distance from the robot = 0.0023m = row2Meter[60]
      //	*/
			static const double row2Meter[imagerows]; //not static??




      //	/**
	  	//Camera dependent lookup table.
			//Factor to calculate y position from pixels to meters depending on
	  	//x position (unit of yFactor is width(m)/width(pixels)).
			//62 values, one for each row. 0 and 61 not used by me.
			//Example: cube width = 0.1m.
			//Cube size in pixel in row 1 (top row, furthest away) = 0.1m/(0.0093m/pixel) = 11 pixel.
			//Cube in pixel in row 60 (bottom row, closest) = 0.1m/(0.0017m/pixel) = 59 pixel.
			//The other direction: something is 20 pixel from the image middle and in row 1.
			//Distance from the robot (y component) = 20*(0.0093m/pixel) = 0.186m.
			//Something is 20 pixel from the image middle and in row 60.
			//Distance from the robot = 20*(0.0017m/pixel) = 0.034m.
      //yFactor is the table for objects left of the robot.
      //yFactorMinus is the table for objects left of the robot.
      //We obtained better results using two tables.
      //	*/
			static const double yFactor[imagerows]; //not static??

      //	/**
	  	//Camera dependent lookup table.
			//Factor to calculate y position from pixels to meters depending on
	  	//x position (unit of yFactor is width(m)/width(pixels)).
			//62 values, one for each row. 0 and 61 not used by me.
			//Example: cube width = 0.1m.
			//Cube size in pixel in row 1 (top row, furthest away) = 0.1m/(0.0093m/pixel) = 11 pixel.
			//Cube in pixel in row 60 (bottom row, closest) = 0.1m/(0.0017m/pixel) = 59 pixel.
			//The other direction: something is 20 pixel from the image middle and in row 1.
			//Distance from the robot (y component) = 20*(0.0093m/pixel) = 0.186m.
			//Something is 20 pixel from the image middle and in row 60.
			//Distance from the robot = 20*(0.0017m/pixel) = 0.034m.
      //yFactor is the table for objects left of the robot.
      //yFactorMinus is the table for objects right of the robot.
      //We obtained better results using two tables.
      //	*/
			static const double yFactorMinus[imagerows]; //not static??

      //	/**
      //	Stores the x value of the last known position of the last detected cube
      //  in local coordinates (That is the x distance from cube to robot
      //  at the time when the image - on which the cube was detected - was taken)
      //
      //	*/
			double cubeDistanceX;

      //	/**
      //	Stores the y value of the last known position of the last detected cube
      //  in local coordinates (That is the y distance from cube to robot
      //  at the time when the image - on which the cube was detected - was taken)
      //
      //	*/
			double cubeDistanceY;

      //	/**
      //	Stores the x value of the last known position of
			//	the last detected cube (in global coordinates, i.e. with (0,0) and not the
      //  current robot position as origin)
      //	*/
			double cubePositionX;

      //	/**
      //	Stores the y value of the last known position of
			//	the last detected cube (in global coordinates, i.e. with (0,0) and not the
      //  current robot position as origin)
      //	*/
			double cubePositionY;

      //	/**
      //	Checks if the passed hue is similar to the
			//	cube color
      //	@see cubeColor
			//	@see allowedCubeColorDeviation
      //	@return true if similar
      //	*/
			bool hasCubeColor(BYTE hue);

      //	/**
      //	How far the distance to an object may drop before the
      //	object is marked as an obstacle by the front PSD sensor (in meter)
      //	*/
      double obstacleThresholdFront;
      //## end SIR%3D86D3570320.private

  private: //## implementation
    // Data Members for Class Attributes

      //## Attribute: robotDetectedFlag%3D99450601EA
      //	/**
      //	Flag to indicate that a robot is visible on the camera.
      //	Used internally
      //	@see SIR::robotDetected()
      //	*/
      //## begin SIR::robotDetectedFlag%3D99450601EA.attr preserve=no  private: bool {U} false
      bool robotDetectedFlag;
      //## end SIR::robotDetectedFlag%3D99450601EA.attr

      //## Attribute: cubeDetectedFlag%3D99451A021C
      //	/**
      //	Flag to indicate that a cube is visible on the camera.
      //	Used internally
      //	@see SIR::cubeDetected()
      //	*/
      //## begin SIR::cubeDetectedFlag%3D99451A021C.attr preserve=no  private: bool {U} false
      bool cubeDetectedFlag;
      //## end SIR::cubeDetectedFlag%3D99451A021C.attr

      //## Attribute: minimumCubeSize%3D9973990302
      //	/**
      //	Stores the minimum size that an object must have to be
      //	accepted as a cube (in meter)
      //	*/
      //## begin SIR::minimumCubeSize%3D9973990302.attr preserve=no  private: double {U} 0.015
      double minimumCubeSize;
      //## end SIR::minimumCubeSize%3D9973990302.attr

      //## Attribute: cubeColor%3D9973A10348
      //	/**
      //	Stores the color of the cubes to be pushed as hue
      //	*/
      //## begin SIR::cubeColor%3D9973A10348.attr preserve=no  private: int {U} -1
      int cubeColor;
      //## end SIR::cubeColor%3D9973A10348.attr

      //## Attribute: allowedCubeColorDeviation%3D9FBCC60046
      //	/**
      //	By how much the color of a pixel may deviate and still
      //	be accepted as cube color
      //	*/
      //## begin SIR::allowedCubeColorDeviation%3D9FBCC60046.attr preserve=no  private: int {U} 0
      int allowedCubeColorDeviation;
      //## end SIR::allowedCubeColorDeviation%3D9FBCC60046.attr

      //## Attribute: obstacleThreshold%3D9FBD200168
      //	/**
      //	How far the distance to an object may drop before the
      //	object is marked as an obstacle by the left/right PSD sensor (in meter)
      //	*/
      //## begin SIR::obstacleThreshold%3D9FBD200168.attr preserve=no  private: double {U} 0.15
      double obstacleThresholdSides;
      //## end SIR::obstacleThreshold%3D9FBD200168.attr

      //## Attribute: currentImage%3D9FBDA600DC
      //	/**
      //	The grayscale image that is currently used for the
      //	detection of robots (SIR::detectRobots())
      //	*/
      //## begin SIR::currentImage%3D9FBDA600DC.attr preserve=no  private: image {U}
      image currentImage;
      //## end SIR::currentImage%3D9FBDA600DC.attr

      //## Attribute: currentColorImage%3D9FBDE4037A
      //	/**
      //	The color image that is currently used for
      //	the detection of cubes (by SIR::detectCubes(),
      //  SIR::getDensity())
      //	*/
      //## begin SIR::currentColorImage%3D9FBDE4037A.attr preserve=no  private: colimage {U}
      colimage currentColorImage;
      //## end SIR::currentColorImage%3D9FBDE4037A.attr

    // Data Members for Associations

      //## Association: <unnamed>%3D86D4B801E0
      //## Role: SIR::<camera>%3D86D4B9008C
      //	/**
      //	The SIR has a Camera to get pictures
      //	*/
      //## begin SIR::<camera>%3D86D4B9008C.role preserve=no  public: Camera { -> RHN}
      Camera *camera;
      //## end SIR::<camera>%3D86D4B9008C.role

      //## Association: <unnamed>%3D8843E00118
      //## Role: SIR::<imageFilter>%3D8843E0029E
      //	/**
      //	The SIR has an ImageFilter to process the taken pictures
      //	*/
      //## begin SIR::<imageFilter>%3D8843E0029E.role preserve=no  public: ImageFilter { -> RHN}
      ImageFilter imageFilter;
      //## end SIR::<imageFilter>%3D8843E0029E.role

      //## Association: <unnamed>%3D8FF37C0398
      //## Role: SIR::<pSDs>%3D8FF37E0014
      //	/**
      //	The SIR needs the PSDs to receive infra-red distance
      //	information
      //	*/
      //## begin SIR::<pSDs>%3D8FF37E0014.role preserve=no  public: PSDs { -> RHN}
      PSDs *psds;
      //## end SIR::<pSDs>%3D8FF37E0014.role

      //## Association: <unnamed>%3D9AC9BB029E
      //## Role: SIR::<drive>%3D9AC9BC0032
      //	/**
      //	The SIR needs the Drive to receive position information
      //	*/
      //## begin SIR::<drive>%3D9AC9BC0032.role preserve=no  public: Drive { -> RHN}
      Drive *drive;
      //## end SIR::<drive>%3D9AC9BC0032.role

    // Additional Implementation Declarations
      //## begin SIR%3D86D3570320.implementation preserve=yes
      //## end SIR%3D86D3570320.implementation

};

//## begin SIR%3D86D3570320.postscript preserve=yes
//## end SIR%3D86D3570320.postscript

// Class SIR

//## begin module%3D86D3570320.epilog preserve=yes
//## end module%3D86D3570320.epilog


#endif
