paper: Scripted Autonomous Control: Presentation material and code samples

Thread created automatically to discuss a document in CD-Media.

Scripted Autonomous Control: Presentation material and code samples
by: Chris Hibner

Presentation material and code samples from Chris Hibner’s 2011 FIRST Robotics Conference presentation on scripted autonomous control.

Presentation material and code samples from Chris Hibner’s 2011 FIRST Robotics Conference presentation on scripted autonomous control.

Autonomous Flexibity.ppt (2.8 MB)
autonomousScriptingExampleExplanation.ppt (1.88 MB) (3.55 MB)

The conference material is finally posted. Sorry for taking so long, and thanks to Brandon for helping me get this posted.

If you are having any trouble with getting the samples to run (especially the simulator), PLEASE let me know. I can only test it on my laptop and Team 51’s programming laptop. Since the LabVIEW installation on those two computers are almost identical, there’s a chance that I may be masking an issue that makes the samples not run on someone else’s computer.

Keepin mind: there’s a good chance that if you’re having a problem, a lot of people are going to have that same problem, so please report it. I would like to get the issues sorted out as soon as possible so the samples are as useful as they can be.

Lastly, if anyone has any questions, please let me know. I’ve been working with this setup for so long that it seems like second nature to me. That means that something may be completely unclear to everyone that I am oblivious to given my closeness to the subject.

Have you, or anyone else for that matter, used Gazebo for an FRC robot simulation?


Does this work for state machines or is it more for a sequential set of maneuvers?

Right now I am playing with the idea of trees and graphs, backed by a decision making architecture.

Right now when i look at these scripts, they seem to be good for individual maneuver but maybe not for a graph of maneuvers. Then again I may just be reading into it wrong.

Correct me if I’m wrong, but It seems like the transitions for the state machine still need to be defined within the code.

Some of the guys in my Mobile Robotics course used it for a project, they said it was a pain to get set up but once it was set up it worked ok.

Great presentation.

Do you have any recommendations for multitasking? For example, if I want to drive the robot while positioning a manipulator?

It depends on exactly what system you’re using. With the case structure method described in the presentation, it may be easiest to make a new case that drives and positions the manipulator simultaneously. This works nicely if this is the only multitasking you need, but it gets cumbersome to implement for many possible combinations.
We created a class for each possible command and placed instances of those commands in a queue, which were run one by one as the exit conditions for the previous command were met. One of our classes was DoubleCommand, which took two other commands and a delay between them as an argument and ran both of them. Depending on the exact setup, something similar could be easy to implement when using a case structure.

How we do it is this:

  1. Pass manipulator commands in as parameters in the script.
    a) If you have feedback controlled appendages (for example, the elevator and arm on our 2011 robot), the manipulator commands would be desired positions (see 2 below).
    b) If you have an appendage that’s NOT feedback controlled (for example, the roller claw on our 2011 robot), the manipulator command is just the motor command (-1.0 to 1.0)

For feedback controlled appendages:

  1. Put your PID code for closed loop control in (see the code samples for an example).

  2. Define global variables for “Desired Position” and “Actual Position” (i.e. set-point and process variable, if you use the lingo defined in LabVIEW).

  3. In your autonomous case structure, set the DesiredPostion global to the parameter being passed in from the script. The PID controller will then control your manipulator in parallel to the autonomous code.

  4. In your autonomous case structure, use abs(DesiredPosition - ActualPosition) as an exit condition IF YOU NEED TO. (That’s why you make ActualPosition a global - so you can use it in the autonomous code as an exit condition if needed.)

The PID in can be extremely simple. Just wire DesiredPosition into the setpoint and wire your sensor value (encoder or pot) to the process variable AND the ActualPosition global. Then wire the output of the PID into your manipulator motor “set” block from the WPI library.

So, how should the autonomous side of the code be set up?
With a little thought, it’s not that complicated. In certain cases in the case structure, take the absolute value of the manipulator error (i.e. abs(ActualPosition - DesiredPosition) and when the error drops below a set threshold, then the manipulator porition of the exit condition is TRUE. Use AND logic (or maybe OR logic, depending on what you’re trying to accomplish) with your other exit conditions.

Another question: when would you use the manipulator in the exit condition (and when would you NOT use it)?

Answer: that is always up to you, but here is some guidance.

  1. If your drivetrain continues to move until the exit condition, you should NOT use the manipulator as an exit condition. Primitive 1 (drive straight - constant speed) in the sample code is a good example. If you use the manipulator as an exit, there’s a good chance you’ll go blowing past your desired distance waiting for the arm to finish what it is doing.

  2. If your drivetrain will hold a position (by position, I mean a small spot on the floor), then using the manipulator in the exit condition can be a good idea. Primitive 3 (drive straight, gradual approach) in the sample code is a good example. With primitive 3, if your manipulator isn’t quite finished when you get to your desired distance, the robot will slow down and wait at the desired distance setpoint until the arm finishes. This is safe.

  3. Define a “Hold Position” primitive. Hold Position is a primitive that actively holds the robot’s position using a PID for heading and a PID for distance. It is basically the same code as 3 in the sample code, but the exit is different - usually the exit is time, and the exit condition can be AND’d or OR’d with a manipulator-based exit condition. Hold Position is great for keeping the robot drivetrain still while you score with your manipulator.

One final note: if you plan to use feedback control on your manipulator during autonomous, but do NOT want to use it during teleop, then you can put the PID controllers in I’m assuming that if you’re using feedback control you would want to do it in teleop as well, which is why I suggest putting the PIDs in - that way you can use the same code for both auton and teleop.

If any of this isn’t clear (which it probably isn’t) or there are any more questions, please let me know.

The beauty of software is that it can do whatever you tell it to do. No, wait, that’s the CURSE of software. I suppose it’s both.

The method outlined in the presentation is just a way to command a sequence of events. However, it wouldn’t be that complicated to put decision making into the system. I’ve thought of one simple scheme to make it happen with a simple change.

Once again, it’s just a method of organization, and it’s only a starting point. Have fun with it.

@Chris Hibner
I actually already started trying implementing this for a 2-ubertube autonomous procedure.

What I ended up doing was since I already had 2 small independent state machines set up–one for the elevator/arm, and one for the claw–I made 2 simple new primitives–one for setting the manipulator states (this one exits automatically after one program cycle), and one that does nothing while checks if the manipulator is finished. The states are held in global variables so that made it easy.