|
|
|
![]() |
|
|||||||
|
||||||||
![]() |
|
|
Thread Tools | Rate Thread | Display Modes |
|
|
|
#1
|
|||
|
|||
|
Threading?
I am running into the issue that I can not do other robot things while my kickBall method is running. I am using this way currently for threading, but it crashes as is. I have also tried using the kickBall method to call just kickThread.run(); but that doesn't let me do anything else while the servo is moving.
Code:
Thread kickThread = new Thread() {
public void run() {
int i = 0;
for (; i < 20; i++) {
if (i == 1) {
setKickAngle(RobotMap.kickDefaultAngle);
doneKicking = false;
} else if (i == 4) {
setKickAngle(RobotMap.kickHitAngle);
doneKicking = false;
} else if (i == 15) {
setKickAngle(RobotMap.kickDefaultAngle);
doneKicking = true;
}
Timer.delay(0.05);
}
doneKicking = true;
kickThread.interrupt();
}
};
public void autoKick() {
if (!kickThread.isAlive() && kickThread.isInterrupted()) {
kickThread.start();
} else {
kickThread.run();
}
}
Thanks for any input you guys have! |
|
#2
|
|||
|
|||
|
Re: Threading?
When you create a Thread in Java, you only need to use the start() method to start the thread running in the background (you do not need to call the Thread's run() method directly). Try the following changes:
Code:
Thread kickThread = new Thread() {
public void run() {
int i = 0;
for (; i < 20; i++) {
if (i == 1) {
setKickAngle(RobotMap.kickDefaultAngle);
doneKicking = false;
} else if (i == 4) {
setKickAngle(RobotMap.kickHitAngle);
doneKicking = false;
} else if (i == 15) {
setKickAngle(RobotMap.kickDefaultAngle);
doneKicking = true;
}
Timer.delay(0.05);
}
doneKicking = true;
// CHANGE 1: Thread will terminate here, you don't need to try and have your thread interrupt itself
// kickThread.interrupt();
}
};
public void autoKick() {
// CHANGE 2: You only need to start your thread once per kick,
// its run() method will be done in the background
if (!kickThread.isAlive()) {
kickThread.start();
}
}
|
|
#3
|
|||
|
|||
|
Re: Threading?
Okay, I understand that we can leave the thread just running in the background, and the servo will move the first time we press the button, but I want to be able to press the button more than once per run of the robot. The way it is setup with your changed code I still run into the issue of only being able to kick the ball one time per power cycle. What can I do to fix that?
EDIT: Actually I pushed the code, and the second time I run the autoKick() method the code crashes with Illegal thread state errors. Last edited by fireXtract : 09-02-2016 at 12:42. |
|
#4
|
|||
|
|||
|
Re: Threading?
It looks like you forgot to remove the interrupt() invocation and check that the thread was not running before attempting to start it again.
However, it looks like you are now using the Command based framework in your robot project. In this case you should not need any threading to accomplish the automated task. As a rough guess, it appears that you are automating the task of kicking the boulder and this task involves spinning up some shooter motors and using a servo to feed the boulder into the shooter. My guess is that you are trying to:
Using your existing Shooter subsystem, you should be able to create two new simple commands and one command group to accomplish this. SetShooterSpeed - Simply sets the power on your shooter spinners and then quits (leaves the motors running). SetKickerPosition - Sets the position of the shooter servo. AutonKickCommand - Uses the two above commands and the built in WaitCommand to automate the entire sequence. Here is a start of SetShooterSpeed.java: Code:
package org.usfirst.frc.team2847.robot.commands;
import org.usfirst.frc.team2847.robot.Robot;
import edu.wpi.first.wpilibj.command.Command;
/**
* Command that sets power to shooter wheels and leaves them running.
*/
public class SetShooterSpeed extends Command {
double speed;
public SetShooterSpeed(double speed) {
requires(Robot.shooter);
this.speed = speed;
}
// Called just before this Command runs the first time
protected void initialize() {
Robot.shooter.spinShooters(speed);
}
// Called repeatedly when this Command is scheduled to run
protected void execute() {
}
// Make this return true when this Command no longer needs to run execute()
protected boolean isFinished() {
return true;
}
// Called once after isFinished returns true
protected void end() {
// Leave shooters running
// Robot.shooter.spinShooters(0);
}
// Called when another command which requires one or more of the same
// subsystems is scheduled to run
protected void interrupted() {
end();
}
}
Code:
package org.usfirst.frc.team2847.robot.commands;
import org.usfirst.frc.team2847.robot.Robot;
import edu.wpi.first.wpilibj.command.Command;
/**
* Command that sets power to shooter wheels and leaves them running.
*/
public class SetKickerPosition extends Command {
double angle;
public SetKickerPosition(double angle) {
requires(Robot.shooter);
this.angle = angle;
}
// Called just before this Command runs the first time
protected void initialize() {
Robot.shooter.setKickAngle(angle);
}
// Called repeatedly when this Command is scheduled to run
protected void execute() {
}
// Make this return true when this Command no longer needs to run execute()
protected boolean isFinished() {
return true;
}
// Called once after isFinished returns true
protected void end() {
}
// Called when another command which requires one or more of the same
// subsystems is scheduled to run
protected void interrupted() {
end();
}
}
Code:
package org.usfirst.frc.team2847.robot.commands;
import org.usfirst.frc.team2847.robot.RobotMap;
import edu.wpi.first.wpilibj.command.CommandGroup;
import edu.wpi.first.wpilibj.command.WaitCommand;
public class AutonKick extends CommandGroup {
public AutonKick(double speed) {
super("AutonKick " + speed);
// Get .25 seconds for kicker to get into default position
addSequential(new SetKickerPosition(RobotMap.kickDefaultAngle));
addSequential(new WaitCommand(0.25));
// Start spinning up shooters and give them 2 seconds to reach speed
addSequential(new SetShooterSpeed(speed));
addSequential(new WaitCommand(2.0));
// Move kicker into kick position and give .5 second for boulder
// to pass through
addSequential(new SetKickerPosition(RobotMap.kickHitAngle));
addSequential(new WaitCommand(0.5));
// Stop shooter and return kicker to default position
addSequential(new SetShooterSpeed(0));
addSequential(new SetKickerPosition(RobotMap.kickDefaultAngle));
}
}
Hope that helps. |
|
#5
|
|||
|
|||
|
Re: Threading?
Thank you! I was thinking quite narrow minded by thinking the only way I could do it was with threading! Thanks for showing me the way! One question, what does the super() thing do in the commandgroup? I use it in my PIDSubsystem to pass PID info, but what does it do in this case?
EDIT: I ended up doing this, the second parameter of the command can be used as a timeout ex. (addSequential(),1.5). I needed to do this so that the list doesn't get stuck in the SetShooterSpeedCommand as I don't have it exit unless its interrupted. This works as desired. Thanks for the help pblankenbaker! Code:
public KickNShootCommandGroup() {
// super("KickNShootCommandGroup " + RobotMap.shootSpeed);
// to get into default position
addSequential(new SetKickerPositionCommand(RobotMap.kickDefaultAngle));
// Start spinning up shooters and give them 2 seconds to reach speed
addSequential(new SetShooterSpeedCommand(RobotMap.shootSpeed), 1.5);
// Move kicker into kick position and give .5 second for boulder
// to pass through
addSequential(new SetKickerPositionCommand(RobotMap.kickHitAngle));
addSequential(new WaitCommand(0.7));
// Stop shooter and return kicker to default position
addSequential(new SetKickerPositionCommand(RobotMap.kickDefaultAngle));
addParallel(new SetShooterSpeedCommand(0), 0.5);
}
Last edited by fireXtract : 09-02-2016 at 16:57. Reason: code |
|
#6
|
|||
|
|||
|
Re: Threading?
The super(String) invocation just calls the CommandGroup's constructor (which is a Command object itself) that takes a string parameter. This parameter sets the name to associate with the command. It is not required (the default constructor will) work.
Setting the name on the Command objects can sometimes be useful when debugging. For example, if you add the line after your shooter subsystem is created, the smart dashboard will display the command that is currently active on it: Code:
SmartDashboard.putData("Shooter", Robot.shooter);
|
|
#7
|
|||
|
|||
|
Re: Threading?
I have tried that and it works quite well! Thanks for the idea. I think in the past I used a thing that would just print the current subsystem but with no useful info like speed or angle. Thanks! I think you helped me also in 2014 with another post. You are a helpful dude.
|
![]() |
| Thread Tools | |
| Display Modes | Rate This Thread |
|
|