/*

ARIA header files for use with ARNL 1.7.1

Copyright(C) 2004, 2005 ActivMedia Robotics, LLC. 
Copyright(C) 2006, 2007, 2008, 2009 MobileRobots Inc.
All rights reserved.

This copy of Aria was relicensed for use with Arnl and the Arnl
license by MobileRobots Inc.  If you wish to download a seperate
distribution of Aria licensed under the GPL or a commercial license go to
http://www.mobilerobots.com/SOFTWARE/aria.html or contact MobileRobots
Inc, at robots@mobilerobots.com or MobileRobots Inc,
10 Columbia Drive, Amherst, NH 03031; 800-639-9481

MobileRobots Inc hereby grants to other individuals or
organizations permission to use this software with Arnl and in
compliance with the Arnl license.  This software may not be
distributed to others except by MobileRobots Inc.

MobileRobots Inc does not make any representations about the
suitability of this software for any purpose.  It is provided "as is"
without express or implied warranty.

*/
#ifndef ARACTIONROBOTJOYDRIVE_H
#define ARACTIONROBOTJOYDRIVE_H

#include "ariaTypedefs.h"
#include "ArAction.h"

class ArRobotPacket;

/// This action will use the joystick for input to drive the robot
/**
   This class creates its own ArJoyHandler to get input from the
   joystick.  Then it will scale the speed between 0 and the given max
   for velocity and turning, up and down on the joystick go
   forwards/backwards while right and left go right and left.  You
   must press in one of the two joystick buttons for the class to pay
   attention to the joystick.
   
   NOTE: The joystick does not save calibration information, so you
   must calibrate the joystick before each time you use it.  To do
   this, press the button for at least a half a second while the
   joystick is in the middle.  Then let go of the button and hold the
   joystick in the upper left for at least a half second and then in
   the lower right corner for at least a half second.
**/
class ArActionRobotJoydrive : public ArAction
{
public:
  /// Constructor
  AREXPORT ArActionRobotJoydrive(const char * name = "robotJoyDrive", 
				 bool requireDeadmanPushed = true);
  /// Destructor
  AREXPORT virtual ~ArActionRobotJoydrive();
  AREXPORT virtual ArActionDesired *fire(ArActionDesired currentDesired);
  AREXPORT virtual ArActionDesired *getDesired(void) { return &myDesired; }
#ifndef SWIG
  AREXPORT virtual const ArActionDesired *getDesired(void) const 
                                                        { return &myDesired; }
#endif
  AREXPORT virtual void setRobot(ArRobot *robot);
protected:
  AREXPORT bool handleJoystickPacket(ArRobotPacket *packet);
  AREXPORT void connectCallback(void);
  // whether we require the deadman to be pushed to drive
  bool myRequireDeadmanPushed;

  bool myDeadZoneLast;
  int myButton1;
  int myButton2;
  int myJoyX;
  int myJoyY;
  int myThrottle;
  ArTime myPacketReceivedTime;
  // action desired
  ArActionDesired myDesired;
  ArRetFunctor1C<bool, ArActionRobotJoydrive, 
      ArRobotPacket *> myHandleJoystickPacketCB;
  ArFunctorC<ArActionRobotJoydrive> myConnectCB;
};

#endif //ARACTIONROBOTJOYDRIVE_H
