Go to Post Warning: My opinion is worthless at inspection. - DonRotolo [more]
Home
Go Back   Chief Delphi > Technical > Programming > Java
CD-Media   CD-Spy  
portal register members calendar search Today's Posts Mark Forums Read FAQ rules

 
Reply
Thread Tools Rate Thread Display Modes
  #1   Spotlight this post!  
Unread 26-01-2016, 09:29
curtis0gj curtis0gj is offline
Registered User
FRC #5033 (Beavertronics)
Team Role: Programmer
 
Join Date: Jan 2015
Rookie Year: 2015
Location: Canada
Posts: 121
curtis0gj will become famous soon enough
Drive train PID control

Hello, my team this is looking at solutions for driving more accurately in autonomous. At this moment we are using this to drive a certain distance in autonomous.

Code:
if (encoderDistanceReading >= distance) {
				tankDrive.drive(0, 0);
				return;
			} else if (distance > encoderDistanceReading) {
				tankDrive.drive(-0.25, 0);
			} else {
				tankDrive.drive(0.25, 0);
			}
I am curious about using PID control to drive in autonomous with an encoder for input. I have looked at the Potentiometre PID example and read a bit about PID control (https://wpilib.screenstepslive.com/s...s-pid-control).

Our team is currently using the iterative robot template. The drive train is a four motored tank drive with 8 inch pneumatic tires. I have one encoder setup on the left small output shaft. We have a second encoder coming soon.
Reply With Quote
  #2   Spotlight this post!  
Unread 26-01-2016, 15:51
techkid86's Avatar
techkid86 techkid86 is offline
Magic Programer
FRC #3044 (0xBE4)
Team Role: Alumni
 
Join Date: Jan 2011
Rookie Year: 2010
Location: ballston spa
Posts: 58
techkid86 is an unknown quantity at this point
Re: Drive train PID control

The easiest way I can think to do this, is to initialize the motors separately without using the robotDrive class, as from the documentation, I can't find a way to integrate it with PID.

What kind of encoder are you using? continuous analog or digital quadrature?
__________________
"you can build a perfect machine out of imperfect parts" -Urza
Reply With Quote
  #3   Spotlight this post!  
Unread 26-01-2016, 16:28
curtis0gj curtis0gj is offline
Registered User
FRC #5033 (Beavertronics)
Team Role: Programmer
 
Join Date: Jan 2015
Rookie Year: 2015
Location: Canada
Posts: 121
curtis0gj will become famous soon enough
Re: Drive train PID control

Quote:
Originally Posted by techkid86 View Post
The easiest way I can think to do this, is to initialize the motors separately without using the robotDrive class, as from the documentation, I can't find a way to integrate it with PID.

What kind of encoder are you using? continuous analog or digital quadrature?
Digital Quadrature, similar to this one just a few years older. http://www.andymark.com/product-p/am-3132.htm.
Reply With Quote
  #4   Spotlight this post!  
Unread 26-01-2016, 18:00
techkid86's Avatar
techkid86 techkid86 is offline
Magic Programer
FRC #3044 (0xBE4)
Team Role: Alumni
 
Join Date: Jan 2011
Rookie Year: 2010
Location: ballston spa
Posts: 58
techkid86 is an unknown quantity at this point
Re: Drive train PID control

Be very careful with those encoders. My team has never successfully used these encoders in competition without hilariously disastrous consequences. Make sure you thoroughly test these in the shop and do plenty of research on how to mount them.

now, as to how to implement it. I did a little more research and found that you can infact use the robot drive class.
Code:
Encoder leftEncoder = new Encoder(1,2);
RobotDrive tank= new RobotDrive (/*numbers I dont know about*/)
PIDController leftControl = new PIDController(0.1,0,0, leftEncoder ,tank.m_frontLeftMotor);
This does not show how to tune PID, or set up encoder values, but it should be enough to get you started.

Code:
leftEncoder.setPIDSourceType(kDisplacement);
leftControl.enable();
leftControl.setSetpoint(distanceToTravel);
__________________
"you can build a perfect machine out of imperfect parts" -Urza

Last edited by techkid86 : 26-01-2016 at 18:06.
Reply With Quote
  #5   Spotlight this post!  
Unread 26-01-2016, 18:14
curtis0gj curtis0gj is offline
Registered User
FRC #5033 (Beavertronics)
Team Role: Programmer
 
Join Date: Jan 2015
Rookie Year: 2015
Location: Canada
Posts: 121
curtis0gj will become famous soon enough
Re: Drive train PID control

Quote:
Originally Posted by techkid86 View Post
Be very careful with those encoders. My team has never successfully used these encoders in competition without hilariously disastrous consequences. Make sure you thoroughly test these in the shop and do plenty of research on how to mount them.

now, as to how to implement it. I did a little more research and found that you can infact use the robot drive class.
Code:
Encoder leftEncoder = new Encoder(1,2);
RobotDrive tank= new RobotDrive (/*numbers I dont know about*/)
PIDController leftControl = new PIDController(0.1,0,0, leftEncoder ,tank.m_frontLeftMotor);
This does not show how to tune PID, or set up encoder values, but it should be enough to get you started.

Code:
leftEncoder.setPIDSourceType(kDisplacement);
leftControl.enable();
leftControl.setSetpoint(distanceToTravel);
Okay awesome, I will start working away at this. I am wondering if I will need to set up a right motor control and if so do I need a second encoder?
Reply With Quote
  #6   Spotlight this post!  
Unread 26-01-2016, 18:22
techkid86's Avatar
techkid86 techkid86 is offline
Magic Programer
FRC #3044 (0xBE4)
Team Role: Alumni
 
Join Date: Jan 2011
Rookie Year: 2010
Location: ballston spa
Posts: 58
techkid86 is an unknown quantity at this point
Re: Drive train PID control

It depends on what you're trying to keep track of in auto. If you're concerned only with distance, then one would work, but you would have to make sure all motors follow it. If you're using PWM, my team found it easiest to just splice the PWM cable into 2 end points so it can connect 2 Jags to 1 PWM output. This saves from having to set up sync/follower sets in code. ((obviously you would still need at least 2 PWM, one for each side))

if you're concerned about turning, (like when going over rough terrain) you may wish to use a gyro as well, as encoders will only track wheel spin, and not robot distance
__________________
"you can build a perfect machine out of imperfect parts" -Urza
Reply With Quote
  #7   Spotlight this post!  
Unread 26-01-2016, 20:53
curtis0gj curtis0gj is offline
Registered User
FRC #5033 (Beavertronics)
Team Role: Programmer
 
Join Date: Jan 2015
Rookie Year: 2015
Location: Canada
Posts: 121
curtis0gj will become famous soon enough
Re: Drive train PID control

Quote:
Originally Posted by techkid86 View Post
It depends on what you're trying to keep track of in auto. If you're concerned only with distance, then one would work, but you would have to make sure all motors follow it. If you're using PWM, my team found it easiest to just splice the PWM cable into 2 end points so it can connect 2 Jags to 1 PWM output. This saves from having to set up sync/follower sets in code. ((obviously you would still need at least 2 PWM, one for each side))

if you're concerned about turning, (like when going over rough terrain) you may wish to use a gyro as well, as encoders will only track wheel spin, and not robot distance
Driving straight for a desired distance is currently the main objective. However, it would be nice to be able to turn after going a set distance. My mentor did bring up the point about having wheels slip while going over rough terrain and we do have a gyro installed but I wasn't aware that it could be used to drive a distance.

Just starting adding some of the code but I am having difficulty with the leftControl. The error I am getting is: "The field RobotDrive.m_frontLeftMotor is not visible"

Code:
RobotDrive tankDrive = new RobotDrive(0, 1);
Encoder encoder = new Encoder(0 ,1 , true, EncodingType.k4X);
PIDController leftControl = new PIDController(0.1, 0, 0, encoder, tankDrive.m_frontLeftMotor);
I was looking at WPI docs and I realized that I may need to use the second constructor listed opposed to what I am doing now:
RobotDrive(int leftMotorChannel, int rightMotorChannel)
Constructor for RobotDrive with 2 motors specified with channel numbers.

RobotDrive(int frontLeftMotor, int rearLeftMotor, int frontRightMotor, int rearRightMotor)
Constructor for RobotDrive with 4 motors specified with channel numbers.

RobotDrive(SpeedController leftMotor, SpeedController rightMotor)
Constructor for RobotDrive with 2 motors specified as SpeedController objects.

RobotDrive(SpeedController frontLeftMotor, SpeedController rearLeftMotor, SpeedController frontRightMotor, SpeedController rearRightMotor)

http://first.wpi.edu/FRC/roborio/rel...obotDrive.html

Last edited by curtis0gj : 26-01-2016 at 21:22.
Reply With Quote
  #8   Spotlight this post!  
Unread 26-01-2016, 22:16
techkid86's Avatar
techkid86 techkid86 is offline
Magic Programer
FRC #3044 (0xBE4)
Team Role: Alumni
 
Join Date: Jan 2011
Rookie Year: 2010
Location: ballston spa
Posts: 58
techkid86 is an unknown quantity at this point
Re: Drive train PID control

That is a possibility, which you can fairly easily use if you split the PWM signal cable to both left drive jags. That way, you have one PWM signal, (one jag from the program's point of view) controlled by one PID/encoder.

Now, the gyro will help in keeping straight, but it will not help in going a set distance. for that, you would use an ultra sonic, (or similar range finder)

my team is trying to use vision to determine distance, but there is a myrid of other ways to do this. If your plan may involve drive slippage, PID distance control wont much help.

now, you might be able to combine that with an accelerometer, and a gyro to use PID after you get across the obstacle. That is, what for the accelerometer to say you are relatively level, use the gyro to straighten out, then use encoders to go forward a distance. IDK how well this will work in conjunction, since there is a lot of variability depending on your drive system.
__________________
"you can build a perfect machine out of imperfect parts" -Urza

Last edited by techkid86 : 26-01-2016 at 22:58.
Reply With Quote
  #9   Spotlight this post!  
Unread 27-01-2016, 00:12
techkid86's Avatar
techkid86 techkid86 is offline
Magic Programer
FRC #3044 (0xBE4)
Team Role: Alumni
 
Join Date: Jan 2011
Rookie Year: 2010
Location: ballston spa
Posts: 58
techkid86 is an unknown quantity at this point
Re: Drive train PID control

Sorry, after thought, it may be easier to just use basic the Jaguar class if you continue having issues with robotDrive. You'll have to set up your tank drive yourself, but it is as easy as linking a joystick to the jag's set function.
__________________
"you can build a perfect machine out of imperfect parts" -Urza
Reply With Quote
  #10   Spotlight this post!  
Unread 27-01-2016, 11:53
curtis0gj curtis0gj is offline
Registered User
FRC #5033 (Beavertronics)
Team Role: Programmer
 
Join Date: Jan 2015
Rookie Year: 2015
Location: Canada
Posts: 121
curtis0gj will become famous soon enough
Re: Drive train PID control

Quote:
Originally Posted by techkid86 View Post
Sorry, after thought, it may be easier to just use basic the Jaguar class if you continue having issues with robotDrive. You'll have to set up your tank drive yourself, but it is as easy as linking a joystick to the jag's set function.
kind of confused sorry. Would I use:
Code:
RobotDrive tankDrive = new RobotDrive(SpeedController leftMotor, SpeedController rightMotor)
We are using Talons but I am guessing this will work the same?
Reply With Quote
  #11   Spotlight this post!  
Unread 27-01-2016, 14:32
grainne grainne is offline
Lead Programmer
FRC #0811 (Team 811 Cardinals)
Team Role: Programmer
 
Join Date: Jan 2015
Rookie Year: 2014
Location: New Hampshire, United States
Posts: 10
grainne is an unknown quantity at this point
Re: Drive train PID control

Quote:
Originally Posted by curtis0gj View Post
Hello, my team this is looking at solutions for driving more accurately in autonomous. At this moment we are using this to drive a certain distance in autonomous.

Code:
if (encoderDistanceReading >= distance) {
				tankDrive.drive(0, 0);
				return;
			} else if (distance > encoderDistanceReading) {
				tankDrive.drive(-0.25, 0);
			} else {
				tankDrive.drive(0.25, 0);
			}
I am curious about using PID control to drive in autonomous with an encoder for input. I have looked at the Potentiometre PID example and read a bit about PID control (https://wpilib.screenstepslive.com/s...s-pid-control).

Our team is currently using the iterative robot template. The drive train is a four motored tank drive with 8 inch pneumatic tires. I have one encoder setup on the left small output shaft. We have a second encoder coming soon.
My team did this last year, and will probably do it again this year. I have attached the code for our drive train - we have a driveAuto method that would drive a number of inches passed as a parameter.

Our pid loop took a lot of time to tune, and we used mecanum drive, so please be aware of that.

Hope this helps
Attached Files
File Type: java Drive.java (5.7 KB, 22 views)
Reply With Quote
  #12   Spotlight this post!  
Unread 27-01-2016, 14:39
techkid86's Avatar
techkid86 techkid86 is offline
Magic Programer
FRC #3044 (0xBE4)
Team Role: Alumni
 
Join Date: Jan 2011
Rookie Year: 2010
Location: ballston spa
Posts: 58
techkid86 is an unknown quantity at this point
Arrow Re: Drive train PID control

More or less yes. So you're using talons. PWM I assume? if so, the following code should be enough to set up your drive.

using only basic classes:
Code:
Talon leftDrive=new Talon(1);
Talon rightDrive=new Talon(2);

//if using gamepad
Joystick gamepad=new Joystick(1);

//if using two individual joysticks
Joystick leftJoy=new Joystick(1);
Joystick leftJoy=new Joystick(2);

Encoder leftEncoder=new Encoder(1,2);
Encoder rightEncoder=new Encoder(1,2);

PIDController leftPID=new PIDController(0.1,0,0, leftEncoder, leftDrive);
PIDController rightPID=new PIDController(0.1,0,0, rightEncoder, rightDrive);

public void robotInit()
{
leftEncoder.setPIDSourceType(PIDSourceType.kDisplacement); rightEncoder.setPIDSourceType(PIDSourceType.kDisplacement); rightEncoder.setReverseDirection(true); rightDrive.setInverted(true); //only one side needs inversion leftEncoder.reset(); rightEncoder.reset(); leftPID.setOutputRange(-0.75,0.75); //max speed it can set to motors rightPID.setOutputRange(-0.75,0.75); //max speed it can set to motors leftPID.enable(); rightPID.enable();
} public void autonomousPeriodic() {
leftPID.setSetpoint(400); rightPID.setSetpoint(400); //set distance. you can change distance per tick through the encoder
} public void teleopInit() {
leftPID.disable(); rightPID.disable();
} public void teleopPeriodic() {
//for two joysticks leftDrive.set(leftJoy.getY()); rightDrive.set(rightJoy.getY()); //for one gamepad leftDrive.set(gamepad.getRawAxis(1)); rightDrive.set(gamepad.getRawAxis(2)); //replace 1 and 2 axis with actual axis number.
}
__________________
"you can build a perfect machine out of imperfect parts" -Urza

Last edited by techkid86 : 27-01-2016 at 14:51.
Reply With Quote
  #13   Spotlight this post!  
Unread 27-01-2016, 15:31
curtis0gj curtis0gj is offline
Registered User
FRC #5033 (Beavertronics)
Team Role: Programmer
 
Join Date: Jan 2015
Rookie Year: 2015
Location: Canada
Posts: 121
curtis0gj will become famous soon enough
Re: Drive train PID control

Quote:
Originally Posted by techkid86 View Post
More or less yes. So you're using talons. PWM I assume? if so, the following code should be enough to set up your drive.

using only basic classes:
Code:
Talon leftDrive=new Talon(1);
Talon rightDrive=new Talon(2);

//if using gamepad
Joystick gamepad=new Joystick(1);

//if using two individual joysticks
Joystick leftJoy=new Joystick(1);
Joystick leftJoy=new Joystick(2);

Encoder leftEncoder=new Encoder(1,2);
Encoder rightEncoder=new Encoder(1,2);

PIDController leftPID=new PIDController(0.1,0,0, leftEncoder, leftDrive);
PIDController rightPID=new PIDController(0.1,0,0, rightEncoder, rightDrive);

public void robotInit()
{
leftEncoder.setPIDSourceType(PIDSourceType.kDisplacement); rightEncoder.setPIDSourceType(PIDSourceType.kDisplacement); rightEncoder.setReverseDirection(true); rightDrive.setInverted(true); //only one side needs inversion leftEncoder.reset(); rightEncoder.reset(); leftPID.setOutputRange(-0.75,0.75); //max speed it can set to motors rightPID.setOutputRange(-0.75,0.75); //max speed it can set to motors leftPID.enable(); rightPID.enable();
} public void autonomousPeriodic() {
leftPID.setSetpoint(400); rightPID.setSetpoint(400); //set distance. you can change distance per tick through the encoder
} public void teleopInit() {
leftPID.disable(); rightPID.disable();
} public void teleopPeriodic() {
//for two joysticks leftDrive.set(leftJoy.getY()); rightDrive.set(rightJoy.getY()); //for one gamepad leftDrive.set(gamepad.getRawAxis(1)); rightDrive.set(gamepad.getRawAxis(2)); //replace 1 and 2 axis with actual axis number.
}
Is it complicated to set this up for arcade drive with one Logitech attack 3? We don't own two matching joysticks so tank drive would be funky.

This is what I thought of doing to have it work for arcade drive I have the PID setup stuff added on I just took it out for this.
Code:
public class Robot extends IterativeRobot {
	Talon leftDrive = new Talon(0);
	Talon rightDrive = new Talon(1);

	RobotDrive tankDrive = new RobotDrive(leftDrive, rightDrive);

	Joystick joystick = new Joystick(0);

	Encoder rightEncoder = new Encoder(0, 1, true,
			EncodingType.k4X);

	PIDController rightPID = new PIDController(0.1, 0, 0, rightEncoder, rightDrive);

	public void robotInit() {
	}

	public void autonomousInit() {
	}

	public void autonomousPeriodic() {
	}

	public void teleopPeriodic() {
		tankDrive.arcadeDrive(-joystick.getY(), -joystick.getX());
	}
}

Last edited by curtis0gj : 27-01-2016 at 15:38.
Reply With Quote
  #14   Spotlight this post!  
Unread 27-01-2016, 15:40
techkid86's Avatar
techkid86 techkid86 is offline
Magic Programer
FRC #3044 (0xBE4)
Team Role: Alumni
 
Join Date: Jan 2011
Rookie Year: 2010
Location: ballston spa
Posts: 58
techkid86 is an unknown quantity at this point
Re: Drive train PID control

yes, just switch out the teleop init and periodic with the following.

Code:
RobotDrive drive;

public void teleopInit()
{
leftPID.disable(); rightPID.disable(); drive=new RobotDrive(leftDrive, rightDrive);
} public void teleopPeriodic() {
drive.arcadeDrive(oneJoy); //where Joystick oneJoy = new Joystick(1);
}
__________________
"you can build a perfect machine out of imperfect parts" -Urza

Last edited by techkid86 : 27-01-2016 at 15:52.
Reply With Quote
  #15   Spotlight this post!  
Unread 27-01-2016, 15:52
curtis0gj curtis0gj is offline
Registered User
FRC #5033 (Beavertronics)
Team Role: Programmer
 
Join Date: Jan 2015
Rookie Year: 2015
Location: Canada
Posts: 121
curtis0gj will become famous soon enough
Re: Drive train PID control

Quote:
Originally Posted by techkid86 View Post
yes, just switch out the teleop init and periodic with the following.

Code:
RobotDrive drive;

public void teleopInit()
{
leftPID.disable(); rightPID.disable(); drive=new RobotDrive(leftDrive, rightDrive);
} public void teleopPeriodic() {
drive.arcadeDrive(//however you setup the stick);
}
Alright I've got that setup nicely next step is to actually add in the PID jazz.
Code:
public class Robot extends IterativeRobot {
	RobotDrive tankDrive;

	Talon leftDrive = new Talon(Defines.DRIVE_CHANNEL_ZERO);
	Talon rightDrive = new Talon(Defines.DRIVE_CHANNEL_ONE);

	Joystick joystick = new Joystick(Defines.JOYSTICK_CHANNEL);

	Encoder rightEncoder = new Encoder(Defines.ENCODER_CHANNEL_ZERO, Defines.ENCODER_CHANNEL_ONE, true,
			EncodingType.k4X);

	PIDController rightPID = new PIDController(0.1, 0, 0, rightEncoder, rightDrive);

	public void robotInit() {
	}

	public void autonomousInit() {
		final double distancePerPulse = Math.PI * Defines.WHEEL_DIAMETER / Defines.PULSE_PER_REVOLUTION
				/ Defines.ENCODER_GEAR_RATIO / Defines.GEAR_RATIO * Defines.FUDGE_FACTOR;

		rightEncoder.setDistancePerPulse(distancePerPulse);
		rightEncoder.get();
	}

	public void autonomousPeriodic() {
	}

	public void teleopInit() {
		rightPID.disable();
		tankDrive = new RobotDrive(leftDrive, rightDrive);
	}

	public void teleopPeriodic() {
		tankDrive.arcadeDrive(joystick.getY(), -joystick.getX());

	}
}
Reply With Quote
Reply


Thread Tools
Display Modes Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump


All times are GMT -5. The time now is 11:54.

The Chief Delphi Forums are sponsored by Innovation First International, Inc.


Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Copyright © Chief Delphi