Turret in auton

Hello! I was just wondering how one would go about programing their turret into auton in command-based. I’m completely new to command based and for some reason when we use auto the turret is set to the initial speed from our PID loop and doesn’t update the turret speed. Here’s our code, sorry for the mess: https://github.com/Karma1100/2022-Command.

Seems like the repo is set to private as it 404s for me

3 Likes

is your turret alignment a default command? for us, we just have the default set in both teleop and auto so it just runs normally

Sorry it should be up now

You are setting the turret speed based on joystick input through its default command and you don’t have joystick input in auton, which is why it’s not moving. What are you wanting to do with the turret in auton?

So there is a separate command to allow the turret to function by itself, the command is called Turret Assist. I want to call the turret assist into auton so that the turret will track the hab. Turret assist runs on a pid loop that is getting info from a limelight. Its also hooked up to a button.

Ok, make a parallel command group that combines your turret command and trajectory command, and then return that parallel command in the getAutonomousCommand() method in RobotContainer

2 Likes

In my case, the reason why the speed never updated was because I assumed that subsystem periodic ran in auton, but they don’t. I just called the periodic that I needed info from in a while command inside of an auton command. I also figured out how to break out of the command itself using the “isFinished” function and that the “addRequirements” broke out of the default commands in the robot container which for some reason messed up the auto command. The motors would try to set themselves to the speed of the joysticks while also trying to set themselves to the setSpeed, so if i wanted the robot to move at .5 speed it would set it at 0 to then .5 and then back to 0, causeing a wierd loop that would last the duration of the command. Thank you for the help tho. <3

I am 99% sure that is incorrect

They do. What made you think that they don’t?

Forgetting to add addRequirements is one of the most common mistakes I see, and the result is usually autonomous commands fighting the joystick for control. I wish WPILIB would come up with a way to enforce it.

3 Likes

So when I and the tech at Seneca was troubleshooting we tried just calling the periodic in a command execute and the motors finally updated to the correct values. We tried commenting it out and it went straight back to one motor speed. We put all of the data values that needed to be updated in the periodic and no matter what we tried the only thing that seemed to work was to call the periodic in the cases where we needed it. (the PID loop for the turret I think was the only thing) We did a System out and everything to validate this and even got other techs to look at it. Spent around an hour or two figuring everything out. Thank you for replying ^-^.

If you have any ideas I’m all ears ^-^.

Also, just in case you are wondering if you look at it, the m_timer.alarm() is a custom scheduler because I didn’t really understand how the scheduler worked and I was in the middle of calculus and decided to just try to make my own. It’s all in the regular format now tho, just just in case you were wondering what it was in my auton.

I’m having a little trouble working out what you’re saying here. I think you’re talking about the drive subsystem here, and you’re saying that you added a System.out.println to the periodic method but the message did not show up during autonomous unless you called periodic explicitly in the autonomous command’s execute. Is that right?

Which was the auto command you were using? I see a call to periodic in Drive.java.old.

It might help if I explained that the main event loop calls all of the subsystem periodic methods and also all of the execute methods of running commands, essentially in a single thread. Hence the drive subsystem’s periodic method will be called in between calls to the command’s execute. If you write an execute method that includes a long-running while loop or a sleep, then you are holding up every other action in the event loop. Did you see Loop time of 0.02s overrun messages?

Also, what are you expecting the periodic method of the drive subsystem to do? What does the count represent, and why are you incrementing/decrementing it in this way?

So the subsystem that I am using is Turret.java and limelight.java and the periodic that wouldn’t run is the Limelight one. I am calling targetx to be updated but it never updates in auton. I added the System.out in the auton command TurretAssistAuto and this is where I would see the motor speed being set when the command was being run. I know it wasn’t the addRequirements error because it was already called and yes for some reason the PID value from the limelight would never update. While I was there I regretably did not call targetx so I don’t know if the position was ever being updated, but all I know is the second I put the periodic for the limelight in my code it started working.

I dont see a looptime overrun, and for the count in the DriveTrain subsystem, it was just me and my mentor experimenting with how the periodic runs. The count in DriveTrain is for rotations and we just wanted to see if we could manipulate things that way. Sorry, I forgot to delete it. All the problems are with the subsystems Turret and Limelight, and all of the commands that I had trouble with were the turretAutons. I have no idea what it looked like because we changed so much over the course of those days. Thank you again so much for your help.

1 Like

Looking at TurretAssistAuto, I see that the execute method contains while(true). Just to reiterate: Subsystem periodic methods will be called in between calls to your command execute method. If your execute contains a long-running loop, then no other event methods will be called. This is bad. Your execute method should be quick in-and-out, not looping. The main event loop does the looping for you.

Your code should look something more like:

@Override 
public void execute() { 
    m_Turret.turretTurn(m_Limelight.getTurretSpeed()); 
}

@Override 
public void end(boolean interrupted) { 
    m_Turret.turretTurn(0); 
}

@Override 
public boolean isFinished() { 
    return m_Limelight.OnTarget() ; 
}

You need to work with the scheduler, not against it. You’re just making beads. The scheduler is threading those beads: intitialize, execute, isFinished, periodic, execute, isFinished, periodic … end, periodic

2 Likes

Shorn of some details, the scheduler is run every 20ms in the main event loop and does something like:

For every subsystem: 
    Call subsystem.periodic()
For every button: 
    If triggered: 
        Schedule command
For every scheduled command:
    If command is uninitialized:
        Call command.initialize()
    If command.isFinished():
        Call command.end()
        Unschedule command
    Else:
        Call command.execute()
1 Like

Ah, thank you so much! This helps a lot. I will be sure to teach this to the next-gen. Thank you ^-^.

1 Like

One small correction. Execute is always called at least once.

For every subsystem: 
    Call subsystem.periodic() 
For every button: 
    If triggered: 
        Schedule command
For every scheduled command:
    If command is uninitialized:
        Call command.initialize()
    Call command.execute()
    If command.isFinished():
        Call command.end()
        Unschedule command
1 Like

Just another clarification:

initialize is called when the command is scheduled, not during the scheduler run method.

1 Like