/* 
   Project: coevolutionary GP moto driving
   Dana Vrajitoru
   moto_behave.h
   
   The class that handles behavior for the motorcycle, 
   meaning the kinematics - speed, acceleration, center of gravity.
  
**/

#ifndef MOTO_BEHAVE_H
#define MOTO_BEHAVE_H

#include "moto_animate.h"

class Moto_behave: public Moto_animate {
 protected:
  // Actions that the driver might perform on the motorcycle.
  float throttle_twist, max_throttle_twist, left_push, right_push,
    front_break, back_break, max_front_break, max_back_break, 
    lateral_momentum, max_speed_rate;

  // Physical attributes.
  float weight, kfriction, kdrag, bkdrag, bkfriction, 
        wheel_width, scale, wradius;
  float hor_speed, g, acceleration, g_scale, front_speed, back_speed,
        front_accl, back_accl;
  Point3f static_gcenter, dynamic_gcenter;

  // Values needed to compute the lift force.
  float air_density, ref_coef_lift, ref_coef_deg, surface_perc,
    surface, r_scale;
 
  // Delta t - timing of the motorcycle. It's the lapse between two
  // frames.
  float dt;
  float ds;
  bool crashed;

 public:
  // Default constructor
  Moto_behave();
  // Destructor
  ~Moto_behave();

  // Set some of the global constants and initial conditions.
  void set_consts();
  // Reset everything about the moto.
  void reset();
   
  //added by pk
  //After crash make the moto get up.
  void getup();
   
  //set const speed backwards(equal to manual pull)
  void set_const_speed_backward();

  //set const speed forwards(equal to manual push)
  void set_const_speed_forward();
  //---------------------------------------------- 
 

  // Set and get all of these values.
  void set_throttle_twist(float val=0.0);
  void add_throttle_twist(float val=0.01);
  void set_left_push(float val=0.0);
  void add_left_push(float val=5);
  void amortize_left_push();
  void set_right_push(float val=0.0);
  void add_right_push(float val=5);
  void amortize_right_push();
  void set_front_break(float val=0.0);
  void add_front_break(float val=0.01);
  void set_back_break(float val=0.0);
  void add_back_break(float val=0.01);
  void set_lateral_momentum(float val=0.0);
  void add_lateral_momentum(float val=0.0);
  // Explicit lean functions
  void lean_left(float val = 3);
  void lean_right(float val = 3);
  void set_weight(float val=100.0); // kg
  void set_kfriction(float val=0.0);
  void set_wheel_width(float val=0.05);
  float get_throttle_twist();
  float get_left_push();
  float get_right_push();
  float get_front_break();
  float get_back_break();
  float get_lateral_momentum();
  float get_weight();
  float get_kfriction();
  float get_wheel_width();
  float get_speed();
  float get_max_speed_rate();
  // Need this for some statistics.
  float get_ds();
  // Find out if the moto has crashed.
  bool has_crashed();
  // A natural decrease in the break if the user doesn't continue to
  // push on it.
  void amortize_front_break();
  void amortize_back_break();
  // Amortize the lateral momentum.
  void amortize_lateral_momentum()
    ;// Amortize the horizontal and angular speed in a crash situation.
  void amortize_speed();
  // Decrease all the components that need user input to keep going.
  void amortize();

  // Compute the gravity centers. 
  // The static center is based on the geometry.
  void compute_static_gcenter();
  // The dynamic one depends on the weight and position of the driver.
  void compute_dynamic_gcenter(const Point3f &driver_center, 
			       float driver_weight);
  // Compute the horizontal acceleration based on the slope, the
  // gravitation, and the friction.
  void compute_acceleration();
  // Compute the front, back, general, and angular speed.
  void compute_speed();
  // Translate the angular wheel speed into horizontal speed.
  void angular_2_hor();
  // Translate the horizontal speed into angular wheel speed.
  void hor_2_angular();

  // Changes the angle of the handlebar based on the left and right
  // push.
  void push_handlebar();

  // Lean the motorcycle left and right based on its lateral momentum.
  void push_lateral();

  // Compute the modification to the orientation based on the
  // handlebar angle and the lateral bending (later).
  void compute_orientation();

  // When the motorcycle turns on a circle of radius given by the
  // parameter.
  void move_by_radius(float radius);

  // Compute the radius of turning based on the lateral angle and the
  // lift force.
  float compute_radius();

  // A function that is invoked when the moto falls down. 
  void crash();

  // Main function which will be called from the display.
  void move();

  // Write out all the speed-acceleration-break-throttle.
  void status();
};

#endif
