/****************************************************************************/
/* Copyright (c) 2000 MBARI                                                 */
/* MBARI Proprietary Information. All rights reserved.                      */
/****************************************************************************/
/* Summary  :                                                               */
/* Filename : OdysseyTailCone.h                                             */
/* Author   :                                                               */
/* Project  :                                                               */
/* Version  : 1.0                                                           */
/* Created  : 02/07/2000                                                    */
/* Modified :                                                               */
/* Archived :                                                               */
/****************************************************************************/
/* Modification History:                                                    */
/****************************************************************************/
#ifndef _OdysseyTailCone_H
#define _OdysseyTailCone_H
#include "TailConeIF_SK.h"
#include "OdysseyThruster.h"
#include "OdysseyFin.h"
#include "SerialDevice.h"
#include "Attributes.h"
#include "SerialParameters.h"

/*
CLASS 
OdysseyTailCone

DESCRIPTION
Odyssey implementation of TailConeIF server. This class
encapsulates Odyssey tail device driver objects 
(OdysseyFin and OdysseyThruster).

AUTHOR
Tom O'Reilly
*/
class OdysseyTailCone : public TailConeIF_SK {

  friend class OdysseyTailConeLog;

public:

  ///////////////////////////////////////////////////////////////////
  // Constructor
  OdysseyTailCone(SerialParameters *serialParams); 

  ~OdysseyTailCone();


  /////////////////////////////////////////////////////////
  // If new status, trigger event and return True. Else return False.
  Boolean setStatus(DeviceIF::Status status);

  /////////////////////////////////////////////////////////
  // Current status
  DeviceIF::Status status();


protected:

  virtual void name(DeviceIF::Name name);
  virtual void serialNumber(DeviceIF::Name id);

  virtual DeviceIF::Status powerOn();
  virtual DeviceIF::Status powerOff();
  virtual DeviceIF::Status status();

  ///////////////////////////////////////////////////////////////////
  // Initialize and return status
  virtual DeviceIF::Status initialize();

  ///////////////////////////////////////////////////////////////////
  // Set propeller speed
  // [input] vehicleSpeed: Commanded vehicle speed in meters/sec
  virtual DeviceIF::Status setPropellerSpeed(double vehicleSpeed);

  ///////////////////////////////////////////////////////////////////
  // Set elevator angle
  // [input] angle: Commanded angle in radians
  virtual DeviceIF::Status setElevator(double angle);

  ///////////////////////////////////////////////////////////////////
  // Set rudder angle
  // [input] angle: Commanded angle in radians
  virtual DeviceIF::Status setRudder(double angle);

  ///////////////////////////////////////////////////////////////////
  // Command prop speed, elevator and rudder angles
  // [input] vehicleSpeed: vehicle speed in meters/sec
  // [input] elevator: Commanded elevator angle in radians
  // [input] rudder: Commanded rudder angle in radians
  virtual DeviceIF::Status command(double vehicleSpeed, double elevator, double rudder);

  ///////////////////////////////////////////////////////////////////
  // Set deadman timer
  // [input] milliseconds: timeout
  virtual DeviceIF::Status setDeadman(short milliseconds);

  ///////////////////////////////////////////////////////////////////
  // Get deadman timeout value
  // [output] milliseconds: timeout 
  virtual DeviceIF::Status deadman(short *milliseconds);


  /////////////////////////////////////////////////////////
  // Propeller speed
  // [output] speed: Propeller speed (rad/sec)
  // [output] time: Sample time
  virtual DeviceIF::Status propellerSpeed(double *speed, TimeIF::TimeSpec *time);

  /////////////////////////////////////////////////////////
  // Elevator angle
  // [output] angle: Elevator angle (rad)
  // [output] time: Sample time
  virtual DeviceIF::Status elevator(double *angle, TimeIF::TimeSpec *time);

  /////////////////////////////////////////////////////////
  // Rudder angle
  // [output] angle: Rudder angle (rad)
  // [output] time: Sample time
  virtual DeviceIF::Status rudder(double *angle, TimeIF::TimeSpec *time);

  /////////////////////////////////////////////////////////
  // Get propeller speed, elevator, and rudder angles
  // [output] speed: Propeller speed (rad/sec)
  // [output] elevator: Elevator angle (rad)
  // [output] rudder: Rudder angle (rad)
  // [output] time: Sample time
  virtual DeviceIF::Status actual(double *speed, double *elevator, 
				  double *rudder, 
				  TimeIF::TimeSpec *time);


  virtual void enableThruster();
  virtual void disableThruster();
  virtual Boolean thrusterEnabled();

  virtual TailConeIF::Type tailConeType();

  // If true, then thruster deadman is enabled at thruster initialization
  Boolean _enableThrusterDeadman;

  OdysseyThruster *_thruster;
  OdysseyFin *_elevator;
  OdysseyFin *_rudder;

  double _motorCurrent;

private:

  virtual DeviceIF::Status initThruster();
  virtual DeviceIF::Status initRudder();
  virtual DeviceIF::Status initElevator();

  virtual int spawnAuxTasks();

  double speedToCurrent(double vehicleSpeed);

  SerialDevice *_serialDevice;

  double _effDragCoeff;

  double _rudderCtsPerRad;
  double _elevatorCtsPerRad;

  Attributes _attributes;

  double _elevatorCmd; 
  double _rudderCmd;
  double _speedCmd;
  double _propPitch;
  long    _thrusterTimeout;

  DeviceIF::Status _status;
};

#endif
