//## 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%3D86D3B103DE.cm preserve=no
//	  %X% %Q% %Z% %W%
//## end module%3D86D3B103DE.cm

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

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

#ifndef Pusher_h
#define Pusher_h 1

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

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

// Behavior
#include "Behavior.h"
//## begin module%3D86D3B103DE.additionalDeclarations preserve=yes
//## end module%3D86D3B103DE.additionalDeclarations


//## begin Pusher%3D86D3B103DE.preface preserve=yes
//## end Pusher%3D86D3B103DE.preface

//## Class: Pusher%3D86D3B103DE
//	/**
//	This class implements the pushing behavior of the robot.
//	The robot approaches the cube and tries to push it to
//	its cluster point. If the robot meets other robots on
//	its way it tries to avoid them.
//	@author Jia L. Du
//	 */
//## Category: <Top Level>
//## Persistence: Transient
//## Cardinality/Multiplicity: n



class Pusher : public Behavior  //## Inherits: <unnamed>%3D9ACA330014
{
  //## begin Pusher%3D86D3B103DE.initialDeclarations preserve=yes
  //## end Pusher%3D86D3B103DE.initialDeclarations

  public:
    //## Constructors (generated)
      Pusher();


    //## Other Operations (specified)
      //## Operation: activate%3D9291D102E4
      //	/**
      //	Activates this behavior
      //	@return A result code indicating why this behavior
      //	terminated. Pusher.ARRIVED, PUSHER. CUBE_LOST or
      //	Pusher.DRIVE_STALLED
      //	 */
      int activate ();

      //## Attribute: ARRIVED%3D9ABEE301CC
      //	/**
      //	Used as result code for Pusher::activate()
      //	*/
      //## begin Pusher::ARRIVED%3D9ABEE301CC.attr preserve=no  public: static int {UC} 0
      static const int ARRIVED;
      //## end Pusher::ARRIVED%3D9ABEE301CC.attr

      //## Attribute: CUBE_LOST%3D9ABEFC030C
      //	/**
      //	Used as result code for Pusher::activate()
      //	*/
      //## begin Pusher::CUBE_LOST%3D9ABEFC030C.attr preserve=no  public: static int {UC} 1
      static const int CUBE_LOST;
      //## end Pusher::CUBE_LOST%3D9ABEFC030C.attr

      //## Attribute: DRIVE_STALLED%3D9ABEFD00A0
      //	/**
      //	Used as result code for Pusher::activate()
      //	*/
      //## begin Pusher::DRIVE_STALLED%3D9ABEFD00A0.attr preserve=no  public: static int {UC} 2
      static const int DRIVE_STALLED;
      //## end Pusher::DRIVE_STALLED%3D9ABEFD00A0.attr

    // Additional Public Declarations
      //## begin Pusher%3D86D3B103DE.public preserve=yes
      //## end Pusher%3D86D3B103DE.public

  protected:
    // Additional Protected Declarations
      //## begin Pusher%3D86D3B103DE.protected preserve=yes
      //## end Pusher%3D86D3B103DE.protected

  private:

    //## Other Operations (specified)
      //## Operation: approachCube%3D996568037A
      //	/**
      //	Makes the robot approaching the closest cube such that
      //	the robot has a good starting position to push the cube
      //	to its cluster point in a next step. If no radio communication is
      //  used: To determine a common cluster point this method also calls
      //  Pusher::chooseClusterPoint to measure the cluster density around
      //  the cube to approach. If favorable the location of the cube to approach
      //  is chosen as new cluster point (i.e. if there are more cubes in this area
      //  then at the home cluster point we start pushing cubes to here as this is
      //  faster. And if every robot pushes cubes to the larger cluster points
      //  at the end a single cluster point will remain)
      //  @see Pusher::chooseClusterPoint
      //	@return Pusher::APPROACH_CUBE_ARRIVED or
      //  Pusher::APPROACH_CUBE_MET_ROBOT or
      //  Pusher::APPROACH_CUBE_CUBE_LOST or
      //  Pusher::APPROACH_CUBE_NEW_CLUSTER_POINT_CHOSEN
      //	*/
      int approachCube ();

      //## Operation: avoidRobot%3D99659201D6
      //	/**
      //	Used to avoid other robots by backing up and trying to
      //	go back to the old position after a random time
      //	@see minimumWaitingPeriod
      //	@see maximumWaitingPeriod
      //  @return true if successful
      //	*/
      bool avoidRobot ();

      //## Operation: checkForCube%3D99657E01A4
      //	/**
      //	Tries to retrieve or re-discover a lost cube by turning
      //	slightly left and right
      //  @param backup if true the robot backs up before trying to re-
      //  discover the cube
      //	@return true if successful
      //	*/
      bool checkForCube (bool backup);

      //## Operation: pushCube%3D996594000A
      //	/**
      //	Makes the robot pushing the cube in front of him to its
      //	cluster point, i.e. (0,0). This methods uses Drive::driveCurveTo
      //  to push the cube to the cluster point, that means the angle from
      //  the current position (x,y,phi) of the robot to the cluster point
      //  should be less then 135 degrees, preferably less then 60 degrees.
      //  The robot uses the front infra-red sensor to check if the cube is
      //  still there. If the robot meets an obstacle it tries to avoid the
      //  obstacle and retrieve the cube
      //  @see Drive::driveCurveTo
      //  @see Pusher::avoidRobot
      //	@return
      //	 Pusher::PUSH_CUBE_CUBE_LOST
      //	or
      //	Pusher::PUSH_CUBE_ARRIVED
      //	or
      //	Pusher::PUSH_CUBE_MET_ROBOT
      //
      //	*/
      int pushCube ();

    // Additional Private Declarations
      //## begin Pusher%3D86D3B103DE.private preserve=yes
      //	/**
      //	Used internally as result code for Pusher::approachCube()
      //	*/
      static const int APPROACH_CUBE_ARRIVED;
      //	/**
      //	Used internally as result code for Pusher::approachCube()
      //	*/
      static const int APPROACH_CUBE_CUBE_LOST;
      //	/**
      //	Used internally as result code for Pusher::approachCube()
      //	*/
      static const int APPROACH_CUBE_MET_ROBOT;
      //	/**
      //	Used internally as result code for Pusher::approachCube()
      //	*/
      static const int APPROACH_CUBE_NEW_CLUSTER_POINT_CHOSEN;

      //	/**
      //	If no communication is used the Pusher determines the
      //	cluster point for the robot. It does that by comparing
      //	the cube density of its own cluster with the density of
      //	the newly detected cluster. It chooses the cluster with
      //	the higher density as the new cluster point.
      //	A new cluster point is set by resetting the robot
      //	position. (0,0) is always used as cluster point position
      //	as it is easier to push cubes to that position. Thus if
      //	a new cluster point is chosen the current robot position
      //	is adapted
      //	@see Behavior::myClusterPointDensity
      //  @param forceChoiceOfClusterPoint if true the robot is forced
      //  to choose a new cluster point, even if the density of the
      //  cluster in front of the robot is
      //  smaller then the home cluster density (This flag is used to re-measure
      //  the home cluster density and re-set the robot's coordinate system
      //  after arriving home from a pushing operation)
      //  @return true if a new cluster point was chosen
      //	 */
      bool chooseClusterPoint (bool forceChoiceOfClusterPoint);


      //## end Pusher%3D86D3B103DE.private

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

      //## Attribute: PUSH_CUBE_MET_ROBOT%3D9FC42501D6
      //	/**
      //	Used internally as result code for Pusher::pushCube()
      //	*/
      //## begin Pusher::PUSH_CUBE_MET_ROBOT%3D9FC42501D6.attr preserve=no  private: static int {UC} 10
      static const int PUSH_CUBE_MET_ROBOT;
      //## end Pusher::PUSH_CUBE_MET_ROBOT%3D9FC42501D6.attr

      //## Attribute: PUSH_CUBE_CUBE_LOST%3D9FC4450370
      //	/**
      //	Used internally as result code for Pusher::pushCube()
      //	*/
      //## begin Pusher::PUSH_CUBE_CUBE_LOST%3D9FC4450370.attr preserve=no  private: static int {UC} 11
      static const int PUSH_CUBE_CUBE_LOST;
      //## end Pusher::PUSH_CUBE_CUBE_LOST%3D9FC4450370.attr

      //## Attribute: PUSH_CUBE_ARRIVED%3D9FC4460096
      //	/**
      //	Used internally as result code for Pusher::pushCube()
      //	*/
      //## begin Pusher::PUSH_CUBE_ARRIVED%3D9FC4460096.attr preserve=no  private: static int {UC} 12
      static const int PUSH_CUBE_ARRIVED;
      //## end Pusher::PUSH_CUBE_ARRIVED%3D9FC4460096.attr

      //## Attribute: minimumWaitingPeriod%3D9FC5570050
      //	/**
      //	Determines how long the robot should wait at least
      //	before trying to continue its task after being
      //	interrupted by another robot
      //	@see Pusher::avoidRobot()
      //	*/
      //## begin Pusher::minimumWaitingPeriod%3D9FC5570050.attr preserve=no  private: int {U} 0
      int minimumWaitingPeriod;
      //## end Pusher::minimumWaitingPeriod%3D9FC5570050.attr

      //## Attribute: maximumWaitingPeriod%3D9FC5C003CA
      //	/**
      //	Determines how long the robot should wait at most before
      //	trying to continue its task after being interrupted by
      //	another robot
      //	@see Pusher::avoidRobot()
      //	*/
      //## begin Pusher::maximumWaitingPeriod%3D9FC5C003CA.attr preserve=no  private: int {U} 1000
      int maximumWaitingPeriod;
      //## end Pusher::maximumWaitingPeriod%3D9FC5C003CA.attr

    // Additional Implementation Declarations
      //## begin Pusher%3D86D3B103DE.implementation preserve=yes
      //## end Pusher%3D86D3B103DE.implementation

};

//## begin Pusher%3D86D3B103DE.postscript preserve=yes
//## end Pusher%3D86D3B103DE.postscript

// Class Pusher

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


#endif
