*

-- Author.

import java.util.*;
public class pidsim 
{		
	double timeunit = 0.02;      //iteration time (guesstimated)
	double maxrotaterate = 1.00; //maximum rotation rate allowed 
	
	//play with the following 3 constants
	double kp = 1.5;             //proportional constant
	double ki = 1.0;             //integral constant
	double kd = 1.0;             //derivative constant
	
	double setpoint = 0;         //target angle
	double maxturnrate = 0.1;    //guess at motor maximum turning rate
	double accuracy = 0.50;      //tolerance of target closeness 
	double currheading = 0;      //current reported gyro heading
	double error = 0.0;          //difference (heading - setpoint)
	double preverror = 0;        //prior error calculated 
	double rr = 0.0;             //rotation rate
	double i = 0.0;              //integral variable
	double d = 0.0;              //derivative variable
	
	static int src = 0;
	int rc = 0;                  //return code
	int approachside = 0;        //1 = postive slope, -1 = negative slope
	int icount = 0;
	

public static void main(String[] args) 
{
	pidsim t = new pidsim();
	src = t.process();
	System.out.println("E-O-P");
	return;
}

	
public int process()
{
	String keyline;
	Scanner sc = new Scanner(System.in);
	for(;;)
	{
    	System.out.println("Please enter target angle");
    	keyline = sc.nextLine();
    	keyline = keyline.trim();
    	if(keyline.length() == 0)
        {
            System.out.println("Nothing entered, terminating");
            break;
        }
        try
        {
            setpoint = Integer.parseInt((String) keyline);
        }
        catch(NumberFormatException e)
        {
            System.out.println("Non-integer detected");
            continue;
        }
        rc = initvalues();
        rc = pidprocess();
	}
	sc.close();
	return 0;
} // end method


public int pidprocess()
{
	if ( (setpoint - currheading) > 0 )    //Recognize overshoot of target from any oscillation
	{
		approachside = 1;
	}
	else
	{
		approachside = -1;
	}
	while (Math.abs(setpoint - currheading) > accuracy)
	{
		currheading = currheading + (Math.abs(setpoint) * maxturnrate * rr);  //a guess about amount of movement
		rr = calcPID();
        //pause(1000);		
	}
	return 0;
} // end method


public double calcPID()
{
	error = setpoint - currheading;      //amount still to go to reach target setpoint
	if (((error > 0) && (preverror < 0)) || ((error < 0) && (preverror > 0)))
	{
		approachside = approachside * -1;
		System.out.println("Setpoint approach direction change");
		i = 0;  //reset integral summation 
	}	
	i = i + (error * timeunit);         //sum of the history of (errors * timeunit)
	double deltaerror = preverror - error;
	if (Math.abs(deltaerror) < timeunit) 	//employ only when change in error is small
	{
		d = deltaerror / timeunit;  //slope of the current error differentiated over timeunit
	}
	else
	{
		d = 0;
	}
	preverror = error;     //save value for next iteration
	rr = (kp * error) + (ki * i) + (kd * d);  //rotation rate calculation
	if (rr > 0)                               //constrain on the interval (-1,1) or less
	{
		rr = Math.min((rr / Math.abs(setpoint)), maxrotaterate);
	}
	else
	{
		rr = Math.max((rr / Math.abs(setpoint) ), -1 * maxrotaterate);
	}	
	System.out.printf("Interval: %3d  Heading: %+7.2f  Error: %+7.2f  Integral: %+6.2f  Derivative: %+5.2f  RotateRate: %+5.2f ",icount,currheading,error,i,d,rr);
	System.out.println("");
	icount++;
	return rr;
} // end method


public int initvalues()      //Initialize variables
{
	icount = 0;
	currheading = 0;
	error = 0.0;
	preverror = 0;
	rr = 0.0;
	i = 0;
	d = 0;
	approachside = 0;
	return 0;
} // end method


public static int pause(int d)     // puts thread to sleep for d milliseconds
{ 
	try
	{
		Thread.sleep(d);
	}
	catch (InterruptedException e1)
	{
		return 1;
	}
    return 0;
}


} // end class


} // end class

</pre>