/*   @(#) $Header: go2coord2.h,v  abrown Exp $
 * Author:
 *   "Allen Brown" http://brown.armoredpenguin.com/~abrown/contact.html
 * Description:
 *   Header file for motion control function library.
 *
 * Copyright (C) 2006,2007,2008 Allen Brown
 *
 * License:
 *   This program is free software; you can redistribute it and/or
 *   modify it under the terms of the GNU General Public License
 *   as published by the Free Software Foundation; either version 2
 *   of the License, or (at your option) any later version.
 *   
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *   
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the
 *     Free Software Foundation, Inc.,
 *     51 Franklin Street, Fifth Floor,
 *     Boston, MA  02110-1301, USA.
 */
#if ! defined(GO2COORD_H)
  #define GO2COORD_H 1

  #include "varsizes.h"

// ---------------------------------------------------------------------
  /* go2coord_new(): Create a go2coord object.
   * Returns: pointer to the new go2coord object.
   *   Or null pointer if fail.
   * power_left and power_right: pointers to the variables where
   *   motor power is controlled.
   * go2coord_new() returns: an object pointer which you must retain.
   *   All calls to go2coord_target() and go2coord_update()
   *   must provide this object pointer as the first parameter.
   *   This needs to have been declared in the form
   *       void * mynameforgo2coordobject=0;
   *   and then set by exactly one call to go2coord_new()
   *   for each object.  Generally a robot will only have one object.
   */
  void *go2coord_new( int16 *power_left, int16 *power_right );

// ---------------------------------------------------------------------
  /* go2coord_xy_set(): Set the objective for a go2coord_xy_go().
   * Returns: nothing
   * go2_data: The object pointer returned when you called
   *   go2coord_new().
   * x_curr, y_curr, heading_curr: the current x,y and heading
   *   of the robot.
   * x_target and y_target: describes the target location.
   *
   * All distance parameters must be in the same units.
   * All heading parameters must be in the same units.
   */
  void go2coord_xy_set( void* go2_data,
			int32 x_target, int32 y_target,
			int32 x_curr, int32 y_curr, int16 heading_curr );

// ---------------------------------------------------------------------
  /* go2coord_xy_go(): Control the robot motors to drive it
   *   to the x,y location specified in the last go2coord_xy_set().
   * Returns: Number representing the action taken this cycle.
   *   See the action lookup table below.
   * go2_data: The object pointer returned when you called
   *   go2coord_new().
   * x_curr, y_curr, heading_curr: the current x,y and heading
   *   of the robot.  Typically these will be values returned
   *   by a call to navigate_xy() and a call to navigate_heading().
   * power_fast: Motor power value to use on the side of the
   *   robot that you want to go fast.
   * power_slow: Motor power value to use on the side of the
   *   robot that you want to go slow.  Typically the power_slow
   *   value will be 1/10 or 1/20 the power_fast value.
   *
   * All distance parameters must be in the same units.
   * All heading parameters must be in the same units.
   */
  int8 go2coord_xy_go( void* go2_data,
			int32 x_curr, int32 y_curr, int16 heading_curr,
			int16 power_fast, int16 power_slow );

// ---------------------------------------------------------------------
  /* go2coord_heading_orient_set(): Specify what heading you want
   *   go2coord_heading_go() to seek.  However, the heading
   *   is not specified as an angle, but a coordinate.  The
   *   robot will pirouette to face that coordinate.  Either
   *   go2coord_heading_orient_set() or go2coord_heading_set()
   *   (but not both) may be used to tell subsequent calls to
   *   go2coord_heading_go() what to do.
   * Returns: nothing
   * go2_data: The object pointer returned when you called
   *   go2coord_new().
   * x_target and y_target: The point toward which the pirouette
   *   will orient.
   * x_center and y_center: The center point for the pirouette.
   *   This needs to be the same or very close to the current
   *   location or we will end up off target.  But if it is
   *   slightly off from the current location, during the pirouette
   *   go2coord_heading_go() will attempt to shift to that location.
   * heading_curr: current heading.
   *
   * All distance parameters must be in the same units.
   * All heading parameters must be in the same units.
   */
  void go2coord_heading_orient_set( void* go2_data,
			     int32 x_target, int32 y_target,
			     int32 x_center, int32 y_center,
			     int16 heading_curr );

// ---------------------------------------------------------------------
  /* go2coord_heading_set(): Specify what heading you want
   *   go2coord_heading_go() to seek.  Either
   *   go2coord_heading_orient_set() or go2coord_heading_set()
   *   (but not both) may be used to tell subsequent calls to
   *   go2coord_heading_go() what to do.
   * Returns: nothing
   * go2_data: The object pointer returned when you called
   *   go2coord_new().
   * x_center and y_center: The center point for the pirouette.
   *   This needs to be the same or very close to the current
   *   location or we will end up off target.  But if it is
   *   slightly off from the current location, during the pirouette
   *   go2coord_heading_go() will attempt to shift to that location.
   * heading_target: the heading we want to end up at.
   * heading_curr: current heading.
   *
   * All distance parameters must be in the same units.
   * All heading parameters must be in the same units.
   */
  void go2coord_heading_set( void* go2_data,
			     int32 x_center, int32 y_center,
			     int16 heading_target, int16 heading_curr );

// ---------------------------------------------------------------------
  /* go2coord_heading_go(): Pirouette the robot until the
   *   heading reaches that set by go2coord_heading_set().
   *   An attempt will be made to maintain the target x,y.
   *   But if the target is not where we start, success in
   *   that detail is unlikely.  Either
   *   go2coord_heading_orient_set() or go2coord_heading_set()
   *   (but not both) may be used to tell subsequent calls to
   *   go2coord_heading_go() what to do.
   * Returns: Number representing the action taken this cycle.
   *   See the action lookup table below.
   * go2_data: The object pointer returned when you called
   *   go2coord_new().
   * x_curr, y_curr, heading_curr: the current x,y and heading
   *   of the robot.
   * power_forw_fast: Power to apply to the motor you want to
   *   drive forward during a pirouette.
   * power_forw_slow: Power to apply to the motor when coasting
   *   forward during a pirouette.
   * power_rev_fast: Power to apply to the motor you want to
   *   drive in reverse during a pirouette.
   * power_rev_slow: Power to apply to the motor when coasting
   *   backward during a pirouette.
   *
   * Typically power_*_slow values will be about 1/3 as
   *   much as power_*_fast values.
   * Typically power_forw_* values will be the negative of
   *   power_rev_* values.
   * All distance parameters must be in the same units.
   * All heading parameters must be in the same units.
   */
  int8 go2coord_heading_go( void* go2_data, int32 x_curr, int32 y_curr,
			     int16 heading_curr,
			     int16 power_forw_fast, int16 power_forw_slow,
			     int16 power_rev_fast, int16 power_rev_slow,
			     int16 power_stop );

// ---------------------------------------------------------------------
  /* go2coord_stop(): Report when the robot has stopped.
   * Returns: 0 if stopped, 1 if moving, -1 if error
   */
  int8 go2coord_stop( void* go2_data,
		      int32 x_curr, int32 y_curr, int16 heading_curr );

// ---------------------------------------------------------------------
// go2coord2.c action return values for go2coord_xy_go()
// and go2coord_heading_go():
  #define GO2ERROR -1	// Something seriously wrong.
  #define GO2DONE 0	// Done!
  #define GO2PPLEFT 1	// Power pirouette left.
  #define GO2PPRIGHT 2	// Power pirouette right.
  #define GO2PDLEFT 3	// Drift pirouette left.
  #define GO2PDRIGHT 4	// Drift pirouette right.
  #define GO2PPLEFTR 5	// Power pirouette left.  Ease reverse.
  #define GO2PPRIGHTR 6	// Power pirouette right.  Ease reverse.
  #define GO2PDLEFTR 7	// Drift pirouette left.  Ease reverse.
  #define GO2PDRIGHTR 8	// Drift pirouette right.  Ease reverse.
  #define GO2PPLEFTF 9	// Power pirouette left.  Ease forward.
  #define GO2PPRIGHTF 10 // Power pirouette right.  Ease forward.
  #define GO2PDLEFTF 11	// Drift pirouette left.  Ease forward.
  #define GO2PDRIGHTF 12 // Drift pirouette right.  Ease forward.
  #define GO2SPLEFT 13	// Power steer left.
  #define GO2SPRIGHT 14	// Power steer right.
  #define GO2SDLEFT 15	// Drift steer left.  Power straight.
  #define GO2SDRIGHT 16	// Drift steer right.  Power straight.
  #define GO2STRAIGHT 17 // Straight ahead.
// ---------------------------------------------------------------------
  #define GO2COORD_QTY 1
  // GO2COORD_QTY declares the number of robots this code will direct.
  // Generally this will be 1.

#endif
/*
 * $Log: go2coord.h,v $
 * Revision 1.2  2006/03/05 21:02:59  abrown
 * go2coord_update(): Recompute target heading each time.  Check for
 * success before testing for corrections.  Major rewrite of the test data.
 *
 * Revision 1.1  2006/02/24 02:07:41  abrown
 * Given navigation data, this controls the robot to go to coordinates on field.
 *
 */

