/****************************************************************************
*
*   Copyright (c) 2008 www.societyofrobots.com
*   (please link back if you use this code!)
*
*   This program is free software; you can redistribute it and/or modify
*   it under the terms of the GNU General Public License version 2 as
*   published by the Free Software Foundation.
*
*   Alternatively, this software may be distributed under the terms of BSD
*   license.
*
****************************************************************************/

//This file stores walking gaits

//initialize variables
//these variables store only current servo location
long signed int head;
//long signed int head_tilt;
long signed int left_foot;
long signed int left_ankle;
long signed int left_knee;
long signed int left_thigh;
long signed int left_hip;
long signed int left_collar;
long signed int left_shoulder;
long signed int left_elbow;
long signed int right_foot;
long signed int right_ankle;
long signed int right_knee;
long signed int right_thigh;
long signed int right_hip;
long signed int right_collar;
long signed int right_shoulder;
long signed int right_elbow;

//initialize home variables
//tweak these numbers until biped stands up strait
long signed int home_head=550;			//
//long signed int home_head_tilt=550;
long signed int home_left_foot=710;			//set
long signed int home_left_ankle=810;		//set
long signed int home_left_knee=610;			//
long signed int home_left_thigh=870;		//
long signed int home_left_hip=740;			//
long signed int home_left_collar=550;		//
long signed int home_left_shoulder=550;		//
long signed int home_left_elbow=550;		//
long signed int home_right_foot=720;		//set
long signed int home_right_ankle=650;		//
long signed int home_right_knee=800;		//
long signed int home_right_thigh=560;		//
long signed int home_right_hip=570;			//
long signed int home_right_collar=550;		//
long signed int home_right_shoulder=550;	//
long signed int home_right_elbow=550;		//

//define walking forward gait
int forward_count=7;//number of positions in the forward gait array
long signed int forward_head[7]=			{100,150,200,150,100,0,-100};
//long signed int forward_head_tilt[7]=		{100,150,200,150,100,0,-100};
long signed int forward_left_foot[7]=		{100,150,200,150,100,0,-100};
long signed int forward_left_ankle[7]=		{100,150,200,150,100,0,-100};
long signed int forward_left_knee[7]=		{100,150,200,150,100,0,-100};
long signed int forward_left_thigh[7]=		{100,150,200,150,100,0,-100};
long signed int forward_left_hip[7]=		{100,150,200,150,100,0,-100};
long signed int forward_left_collar[7]=		{100,150,200,150,100,0,-100};
long signed int forward_left_shoulder[7]=	{100,150,200,150,100,0,-100};
long signed int forward_left_elbow[7]=		{100,150,200,150,100,0,-100};
long signed int forward_right_foot[7]=		{100,150,200,150,100,0,-100};
long signed int forward_right_ankle[7]=		{100,150,200,150,100,0,-100};
long signed int forward_right_knee[7]=		{100,150,200,150,100,0,-100};
long signed int forward_right_thigh[7]=		{100,150,200,150,100,0,-100};
long signed int forward_right_hip[7]=		{100,150,200,150,100,0,-100};
long signed int forward_right_collar[7]=	{100,150,200,150,100,0,-100};
long signed int forward_right_shoulder[7]=	{100,150,200,150,100,0,-100};
long signed int forward_right_elbow[7]=		{100,150,200,150,100,0,-100};


//various common initialized variables
int i;
int j;
float per_a;
float per_b;
int next;

//this function calculates gait meshing
void calculate_per(int speed)
	{
	//mesh current gait position with future gait position
	per_a=(speed-j)/speed;
	per_b=1-per_a;

	//make sure future gait position isn't outside array
	if(i!=forward_count-1)
		next=i+1;
	else //if it is, then restart back at zero
		next=0;
	}

//command biped to do stuff
void biped_move(void)
	{
	head(head+home_head);
	//head_tilt(head_tilt+home_head_tilt);

	left_foot(left_foot+home_left_foot);
	left_ankle(left_ankle+home_left_ankle);
	left_knee(left_knee+home_left_knee);
	left_thigh(left_thigh+home_left_thigh);
	left_hip(left_hip+home_left_hip);
	left_collar(left_collar+home_left_collar);
	left_shoulder(left_shoulder+home_left_shoulder);
	left_elbow(left_elbow+home_left_elbow);

	right_foot(right_foot+home_right_foot);
	right_ankle(right_ankle+home_right_ankle);
	right_knee(right_knee+home_right_knee);
	right_thigh(right_thigh+home_right_thigh);
	right_hip(right_hip+home_right_hip);
	right_collar(right_collar+home_right_collar);
	right_shoulder(right_shoulder+home_right_shoulder);
	right_elbow(right_elbow+home_right_elbow);
	}


//home position
//all positions are zeroed onto home position
void home_position(void)
	{
	head=0;
	//head_tilt=0;

	left_foot=0;
	left_ankle=0;
	left_knee=0;
	left_thigh=0;
	left_hip=0;
	left_collar=0;
	left_shoulder=0;
	left_elbow=0;

	right_foot=0;
	right_ankle=0;
	right_knee=0;
	right_thigh=0;
	right_hip=0;
	right_collar=0;
	right_shoulder=0;
	right_elbow=0;

	biped_move();
	}

//walking forward gait
//higher speed makes robot walk slower
void walk_forward(int speed)
	{

	for (i=0;i<forward_count;i++)
		{
		//to test a particular position, uncomment i
		//and set it to a particular value
		//i=0;
			
		//send each command several times
		for (j=0;j<speed;j++)
			{
			calculate_per(speed);

			head=forward_head[i]*per_a + forward_head[next]*per_b;		
			//head_tilt=forward_head_tilt[i]*per_a + forward_head_tilt[next]*per_b;

			left_foot=forward_left_foot[i]*per_a + forward_left_foot[next]*per_b;
			left_ankle=forward_left_ankle[i]*per_a + forward_left_ankle[next]*per_b;
			left_knee=forward_left_knee[i]*per_a + forward_left_knee[next]*per_b;
			left_thigh=forward_left_thigh[i]*per_a + forward_left_thigh[next]*per_b;
			left_hip=forward_left_hip[i]*per_a + forward_left_hip[next]*per_b;
			left_collar=forward_left_collar[i]*per_a + forward_left_collar[next]*per_b;
			left_shoulder=forward_left_shoulder[i]*per_a + forward_left_shoulder[next]*per_b;
			left_elbow=forward_left_elbow[i]*per_a + forward_left_elbow[next]*per_b;

			right_foot=forward_right_foot[i]*per_a + forward_right_foot[next]*per_b;
			right_ankle=forward_right_ankle[i]*per_a + forward_right_ankle[next]*per_b;
			right_knee=forward_right_knee[i]*per_a + forward_right_knee[next]*per_b;
			right_thigh=forward_right_thigh[i]*per_a + forward_right_thigh[next]*per_b;
			right_hip=forward_right_hip[i]*per_a + forward_right_hip[next]*per_b;
			right_collar=forward_right_collar[i]*per_a + forward_right_collar[next]*per_b;
			right_shoulder=forward_right_shoulder[i]*per_a + forward_right_shoulder[next]*per_b;
			right_elbow=forward_right_elbow[i]*per_a + forward_right_elbow[next]*per_b;

			biped_move();
			}
		}
	}

//walking reverse gait
//does the forward gait, but in reverse, making robot walk backwards
void walk_reverse(int speed)
	{

	for (i=(forward_count-1);i==0;i--)
		{
		//to test a particular position, uncomment i
		//and set it to a particular value
		//i=0;

		//send each command several times
		for (j=0;j<speed;j++)
			{
			calculate_per(speed);

			head=forward_head[i]*per_a + forward_head[next]*per_b;
			//head_tilt=forward_head_tilt[i]*per_a + forward_head_tilt[next]*per_b;

			left_foot=forward_left_foot[i]*per_a + forward_left_foot[next]*per_b;
			left_ankle=forward_left_ankle[i]*per_a + forward_left_ankle[next]*per_b;
			left_knee=forward_left_knee[i]*per_a + forward_left_knee[next]*per_b;
			left_thigh=forward_left_thigh[i]*per_a + forward_left_thigh[next]*per_b;
			left_hip=forward_left_hip[i]*per_a + forward_left_hip[next]*per_b;
			left_collar=forward_left_collar[i]*per_a + forward_left_collar[next]*per_b;
			left_shoulder=forward_left_shoulder[i]*per_a + forward_left_shoulder[next]*per_b;
			left_elbow=forward_left_elbow[i]*per_a + forward_left_elbow[next]*per_b;

			right_foot=forward_right_foot[i]*per_a + forward_right_foot[next]*per_b;
			right_ankle=forward_right_ankle[i]*per_a + forward_right_ankle[next]*per_b;
			right_knee=forward_right_knee[i]*per_a + forward_right_knee[next]*per_b;
			right_thigh=forward_right_thigh[i]*per_a + forward_right_thigh[next]*per_b;
			right_hip=forward_right_hip[i]*per_a + forward_right_hip[next]*per_b;
			right_collar=forward_right_collar[i]*per_a + forward_right_collar[next]*per_b;
			right_shoulder=forward_right_shoulder[i]*per_a + forward_right_shoulder[next]*per_b;
			right_elbow=forward_right_elbow[i]*per_a + forward_right_elbow[next]*per_b;

			biped_move();
			}
		}
	}


void print_servo_values(void)
{
	rprintf("\nleft foot:\t%d\tright foot:\t%d", left_foot, right_foot);
	rprintf("\nleft ankle:\t%d\tright ankle:\t%d", left_ankle, right_ankle);
	rprintf("\nleft knee:\t%d\tright knee:\t%d", left_knee, right_knee);
	rprintf("\nleft thigh:\t%d\tright thigh:\t%d", left_thigh, right_thigh);
	rprintf("\nleft hip:\t%d\tright hip:\t%d", left_hip, right_hip);
	rprintf("\nleft collar:\t%d\tright collar:\t%d", left_collar, right_collar);
	rprintf("\nleft shoulder:\t%d\tright shoulder:\t%d", left_shoulder, right_shoulder);
	rprintf("\nleft elbow:\t%d\tright elbow:\t%d\n", left_elbow, right_elbow);
}

void set_left_foot(int increment_value)
{
	delay_ms(100);
	left_foot = left_foot + increment_value;
	rprintf("\nleft foot: %d\n", left_foot);
}

void set_right_foot(int increment_value)
{
	delay_ms(100);
	right_foot = right_foot + increment_value;
	rprintf("\nright foot: %d\n", right_foot);
}

void set_left_ankle(int increment_value)
{
	delay_ms(100);
	left_ankle = left_ankle + increment_value;
	rprintf("\nleft ankle: %d\n", left_ankle);
}

void set_right_ankle(int increment_value)
{
	delay_ms(100);
	right_ankle = right_ankle + increment_value;
	rprintf("\nright ankle: %d\n", right_ankle);
}

void set_left_knee(int increment_value)
{
	delay_ms(100);
	left_knee = left_knee + increment_value;
	rprintf("\nleft knee: %d\n", left_knee);
}

void set_right_knee(int increment_value)
{
	delay_ms(100);
	right_knee = right_knee + increment_value;
	rprintf("\nright knee: %d\n", right_knee);
}

void set_left_thigh(int increment_value)
{
	delay_ms(100);
	left_thigh = left_thigh + increment_value;
	rprintf("\nleft thigh: %d\n", left_thigh);
}

void set_right_thigh(int increment_value)
{
	delay_ms(100);
	right_thigh = right_thigh + increment_value;
	rprintf("\nright thigh: %d\n", right_thigh);
}

void set_left_hip(int increment_value)
{
	delay_ms(100);
	left_hip = left_hip + increment_value;
	rprintf("\nleft hip: %d\n", left_hip);
}

void set_right_hip(int increment_value)
{
	delay_ms(100);
	right_hip = right_hip + increment_value;
	rprintf("\nright hip: %d\n", right_hip);
}
