Main Site Documentation

FEZ Mini, Steering of RC Car vs PID Controller?


#1

So. How do i set the correct steering position when I have the correct bearing to drive to?
Do I need a (programmatically) PID Controller to calculate the new steering position?

Can someone help me with this?


#2

PID would be the best way to do it, that way you can also set turn rates and things like that.

http://www.codeproject.com/KB/recipes/IndustrialDotNetPID.aspx

That’s an article I wrote on PID controllers, it should apply to .NET MF.


#3

PID is the way to go, it’s what I did on my GPS waypoint robot. See my blog for details: http://www.chrisseto.com/wordpress/?tag=rwar

There’s also a PID class I made on code.tinyclr.com somewhere. In this application, PV is the current compass heading, SP is the heading to follow, and the correction delta + 90 (assuming 180 is full servo travel) is MV. You also need to account for the fact that the compass heading wraps around otherwise you will get really weird results when the robot heads near north.


#4

Some basics.

If you know that your robot should be going in a direction, say more left of current direction, then you can start steering left. Looks simple enough, but isn’t. What you do is if the direction is off by 30 degrees then you can steer left by running the right motor 30% faster than the left motor(if differential steering). This is a multiplication factor of 1(Steering = Error X 1). This factor can be adjusted to suit. As the error becomes less you decrease the steering, 20 degrees = 20%. ETC. This works fine, but you will never exactly reach your desired heading as 1 degree offset is 1% steering.

That is the “P” in PID. The corrective action is directly related to the offset.

The “I” term is added to increase the speed at which the actual heading and the desired heading converge. It adds more steering related to the sum of the past direction error. So even if there is only 1% error, the loop will gradually add more steering to compensate. The down side is that this can add oscillation around the desired heading by overshooting.

The “D” term adds a bit of dampening to the control loop. It looks at the speed at which the error is shrinking and removes some steering. So if the direction is changing too fast then this will reduce the steering a bit…

I would say you should start with purely a P loop and grow from there.

Hope this helps…


#5

Chris, i just took a look at your code. some questions about it.

TargetHeading, i the target heading i calculated by myself.
CurrentHeading, taking the heading from my gps.
AllowError, is the degrees of tolerance, about 5 or 10 or so?
SteadyError, is the current steering?
DeltaTime, where is this variable stand for?

/// <summary>
/// Do the PID correction
/// </summary>
/// <param name="o"></param>
private static void DoPID(object o)
{
	// Bring the LED up to signify frame start
	BoardLED.Write(true);

	// Get IMU heading
	float currentHeading = (float)RazorIMU.Yaw;

	// Calculate error
	// (let's just assume CurrentHeading really is the current GPS heading, OK?)
	float error = (TargetHeading - currentHeading);

	LCD.Lines[0].Text = "Heading: "+ currentHeading.ToString("F2");

	// We calculated the error, but we need to make sure the error is set so that we will be correcting in the
	// direction of least work. For example, if we are flying a heading of 2 degrees and the error is a few degrees
	// to the left of that ( IE, somewhere around 360) there will be a large error and the rover will try to turn all
	// the way around to correct, when it could just turn to the right a few degrees.
	// In short, we are adjusting for the fact that a compass heading wraps around in a circle instead of continuing
	// infinity on a line
	if (error < -180)
		error = error + 360;
	else if (error > 180)
		error = error - 360;

	// We need to allow for a certain amount of tolerance.
	// If the abs(error) is less than the set amount, we will
	// set error to 0, effectively telling the equation that the
	// rover is perfectly on course.
	if (MyAbs(error) < AllowError)
		error = 0;

	LCD.Lines[2].Text = "Error:   " + error.ToString("F2");

	// Calculate proportional term
	float proportional = Kp * error;

	// Calculate integral term
	float integral = Ki * (SteadyError + (error * DeltaTime));

	// Calculate derivative term
	float derivative = Kd * ((error - PrevError) / DeltaTime);

	// Add them all together to get the correction delta
	float correction = proportional + integral + derivative;

	// Set the steering servo to the correction
	Steering.Degree = 90 + correction;

	// At this point, the current PID frame is finished
	// ------------------------------------------------------------
	// Now, we need to setup for the next PID frame

	// The "current" error is now the previous error
	// (Remember, we are done with the current frame, so in
	// relative terms, the previous frame IS the "current" frame)
	PrevError = error;

	// Add the error calculated in this frame to the running total
	SteadyError += (error * DeltaTime);

	BoardLED.Write(false);
}


#6

How about this …??

        float CurrentHeading = 0; // for example, straight north
        float TargetHeading = 90; // for example, east, so, need to go right
        float NewBearing = CurrentHeading - TargetHeading;
        float CurrentSteer = 0;

        if (NewBearing < -180)
        {
            NewBearing = NewBearing + 360;
        }
        else if (NewBearing > 180)
        {
            NewBearing = NewBearing - 360;
        }

        txtSteering.Text = ScaleRange(NewBearing, -180, 180, -30, 30);

My steering angle is -30 left, and 30 right.
so -30 is the most to the left. and 30 is the moest to right.
This is because the steering isn’t steering more then this.
I don’t have thank-steering, like, left wheels spins more then right.
I’ve got real steering, like a real (rc) car :wink:


#7

Hi Colin,

Sorry for the long response time

[quote]TargetHeading, i the target heading i calculated by myself. [Yes]
CurrentHeading, taking the heading from my gps. [Or compass, but yes]
AllowError, is the degrees of tolerance, about 5 or 10 or so? [Get rid of AllowError, it was a design flaw]
SteadyError, is the current steering? [No, that’s the summation of all previous errors]
DeltaTime, where is this variable stand for?[That’s the time between PID corrections][/quote]