Go to Post I think this thread needs a reminder that there's no h in mecanum. ;) - Lil' Lavery [more]
Home
Go Back   Chief Delphi > Technical > Programming > C/C++
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 13-12-2016, 11:23
GavinL GavinL is offline
intensely stares at program
FRC #5726 (Rhumbotz)
Team Role: Programmer
 
Join Date: Jan 2016
Rookie Year: 2016
Location: San Antonio, Texas
Posts: 27
GavinL is a splendid one to beholdGavinL is a splendid one to beholdGavinL is a splendid one to beholdGavinL is a splendid one to beholdGavinL is a splendid one to beholdGavinL is a splendid one to beholdGavinL is a splendid one to behold
Need help understanding command-based Robots

Before the new season starts, I'd like to learn command-based programming. Last year, I used the sample robot. Any sites besides screensteps that I could use? I am confused about the subsystems, commands, and how the drivetrain is made.
Thanks
Reply With Quote
  #2   Spotlight this post!  
Unread 13-12-2016, 12:25
euhlmann's Avatar
euhlmann euhlmann is online now
CTO, Programmer
AKA: Erik Uhlmann
FRC #2877 (LigerBots)
Team Role: Leadership
 
Join Date: Dec 2015
Rookie Year: 2015
Location: United States
Posts: 322
euhlmann has much to be proud ofeuhlmann has much to be proud ofeuhlmann has much to be proud ofeuhlmann has much to be proud ofeuhlmann has much to be proud ofeuhlmann has much to be proud ofeuhlmann has much to be proud ofeuhlmann has much to be proud of
Re: Need help understanding command-based Robots

Command: Basically some action that you can define. This might be an autonomous mode action, or a teleop action, or something you use in both modes. initialize() sets up the action to happen, then execute() is repeatedly called until isFinished() is true, then end() is called to clean up.
Example:
Code:
public class MoveToPositionCommand extends Command {
    private int encoderTicksToDrive;
    
    public MoveToPositionCommand(int encoderTicksToDrive) {
        this.encoderTicksToDrive = encoderTicksToDrive;
        require(driveSubsystem);
    }
    
    public void initialize() {
        driveSubsystem.resetEncoders();
    }

    public void execute() {
        int leftEncoder = driveSubsystem.getLeftEncoder();
        int rightEncoder = driveSubsystem.getRightEncoder();
        double turn = DriveSubsystem.SOME_TURN_CONSTANT * (rightEncoder - leftEncoder);
        double throttle = DriveSubsystem.AUTO_DRIVE_SPEED;
        driveSubsystem.drive(throttle, turn);
    }

    public boolean isFinished() {
        return driveSubsystem.getLeftEncoder() > encoderTicksToDrive || driveSubsystem.getRightEncoder() > encoderTicksToDrive;
    }

    public void end() {
        driveSubsystem.drive(0, 0);
    }
}
Subsystem: Exactly what it sounds like. A virtual representation of a robot subsystem. Subsystems have WPILib objects and define methods that commands can use
Example:
Code:
public class DriveSubsystem {
    public static final double SOME_CONSTANT = 42;

    CANTalon leftDrive, rightDrive;
    Encoder leftEncoder, rightEncoder;

    public DriveSubsystem() {
        // initialize objects
    }

    public void drive(double throttle, double turn) {
        // do the driving
    }

    // other methods that commands need, etc
}
Edit: oops I just realized I posted Java in the C++ forum. It shouldn't be too difficult to translate though
__________________
Creator of SmartDashboard.js, an extensible nodejs/webkit replacement for SmartDashboard


https://ligerbots.org

Last edited by euhlmann : 13-12-2016 at 19:20.
Reply With Quote
  #3   Spotlight this post!  
Unread 13-12-2016, 12:44
phurley67 phurley67 is offline
Programming Mentor
FRC #0862 (Lightning Robotics)
Team Role: Mentor
 
Join Date: Apr 2014
Rookie Year: 2013
Location: Michigan
Posts: 65
phurley67 is an unknown quantity at this point
Re: Need help understanding command-based Robots

Have you checked out the robotbuilder? If not it provide a very concrete way to understand how subsystems, commands and OI all fit together. It generates readable code based on your description.

Think of it this way, your robot is composed of one or more subsystems. Each subsystem will have one or more commands associated with it.

You will almost always have a subsystem for your drivetrain, which at least initially will probably use either the 2 or 4 motor controller. You will then create a teleop_drive command for your drivetrain controller.

Generate the code, and fill in a few blanks and you should be able to get your robot moving pretty quickly. Give that a try and if you get stuck let us know.
Reply With Quote
  #4   Spotlight this post!  
Unread 13-12-2016, 15:26
GavinL GavinL is offline
intensely stares at program
FRC #5726 (Rhumbotz)
Team Role: Programmer
 
Join Date: Jan 2016
Rookie Year: 2016
Location: San Antonio, Texas
Posts: 27
GavinL is a splendid one to beholdGavinL is a splendid one to beholdGavinL is a splendid one to beholdGavinL is a splendid one to beholdGavinL is a splendid one to beholdGavinL is a splendid one to beholdGavinL is a splendid one to behold
Re: Need help understanding command-based Robots

Quote:
Originally Posted by phurley67 View Post
Have you checked out the robotbuilder? If not it provide a very concrete way to understand how subsystems, commands and OI all fit together. It generates readable code based on your description.

Think of it this way, your robot is composed of one or more subsystems. Each subsystem will have one or more commands associated with it.

You will almost always have a subsystem for your drivetrain, which at least initially will probably use either the 2 or 4 motor controller. You will then create a teleop_drive command for your drivetrain controller.

Generate the code, and fill in a few blanks and you should be able to get your robot moving pretty quickly. Give that a try and if you get stuck let us know.
Ok, thanks a lot! And if I want to execute a command, is it "MoveToPosition.execute();"? (without "")
Reply With Quote
  #5   Spotlight this post!  
Unread 13-12-2016, 17:10
bobbysq bobbysq is offline
Registered User
FRC #4646 (Team ASAP)
Team Role: Leadership
 
Join Date: Apr 2016
Rookie Year: 2015
Location: Des Moines, IA
Posts: 281
bobbysq has much to be proud ofbobbysq has much to be proud ofbobbysq has much to be proud ofbobbysq has much to be proud ofbobbysq has much to be proud ofbobbysq has much to be proud ofbobbysq has much to be proud ofbobbysq has much to be proud ofbobbysq has much to be proud ofbobbysq has much to be proud of
Re: Need help understanding command-based Robots

Quote:
Originally Posted by GavinL View Post
Ok, thanks a lot! And if I want to execute a command, is it "MoveToPosition.execute();"? (without "")
Nope, just run MoveToPosition(); from a CommandGroup or assign it to a button in OI and it'll go.
Reply With Quote
  #6   Spotlight this post!  
Unread 13-12-2016, 17:22
phurley67 phurley67 is offline
Programming Mentor
FRC #0862 (Lightning Robotics)
Team Role: Mentor
 
Join Date: Apr 2014
Rookie Year: 2013
Location: Michigan
Posts: 65
phurley67 is an unknown quantity at this point
Re: Need help understanding command-based Robots

Quote:
Originally Posted by GavinL View Post
Ok, thanks a lot! And if I want to execute a command, is it "MoveToPosition.execute();"? (without "")
You would generally associate the MoveToPosition command with operator interface (OI). Using robot builder you can assign it to when a button on a joystick (or gamepad) is pressed, held, or released.

The code ends up looking something like (but again, let robot builder do the lifting until you get the hang of it):

Code:
    // where the coPilot and cmdMove2Pos variables are generally 
    // defined in your OI.h file like
    std::shared_ptr<Joystick> coPilot;
    std::shared_ptr<JoystickButton> cmdMove2Pos;

    // in you OI.cpp file in the constructor
    coPilot.reset(new Joystick(1));
    coPilot.cmdMove2Pos.reset(new JoystickButton(coPilot.get(), 2));
    cmdMove2Pos->WhenPressed(new MoveToPosition());
You can also setup a command (or different commands based on a dashboard option) to run as your auton. The commands can run in sequence, so you can build complicated autonomous behavior from simpler command options.
Reply With Quote
  #7   Spotlight this post!  
Unread 13-12-2016, 18:29
GeeTwo's Avatar
GeeTwo GeeTwo is offline
Technical Director
AKA: Gus Michel II
FRC #3946 (Tiger Robotics)
Team Role: Mentor
 
Join Date: Jan 2014
Rookie Year: 2013
Location: Slidell, LA
Posts: 3,574
GeeTwo has a reputation beyond reputeGeeTwo has a reputation beyond reputeGeeTwo has a reputation beyond reputeGeeTwo has a reputation beyond reputeGeeTwo has a reputation beyond reputeGeeTwo has a reputation beyond reputeGeeTwo has a reputation beyond reputeGeeTwo has a reputation beyond reputeGeeTwo has a reputation beyond reputeGeeTwo has a reputation beyond reputeGeeTwo has a reputation beyond repute
Re: Need help understanding command-based Robots

Quote:
Originally Posted by GavinL View Post
Ok, thanks a lot! And if I want to execute a command, is it "MoveToPosition.execute();"? (without "")
Quote:
Originally Posted by bobbysq View Post
Nope, just run MoveToPosition(); from a CommandGroup or assign it to a button in OI and it'll go.
Quote:
Originally Posted by phurley67 View Post
You would generally associate the MoveToPosition command with operator interface (OI). Using robot builder you can assign it to when a button on a joystick (or gamepad) is pressed, held, or released.
To clarify (as this does NOT make much sense until you wrap your head around it, especially if you're coming from a sampleRobot mindset): You just create the commands with new MoveToPosition() and pass them to the buttons, joysticks, or other control objects. The internals of those control objects call your initialize(), execute(), isFinished(), and end() methods at the appropriate times. You should only put "one pass" of your execute loop in the execute command; it will be called repeatedly. Any information you need to carry from one call to execute() to another should be declared as part of the object and instantiated/initialized in initialize(). Each of your functions (especially execute() and isFinished()) should be written to return as quickly as possible - do not put any waits or loops of more than a very few passes in them.
__________________

If you can't find time to do it right, how are you going to find time to do it over?
If you don't pass it on, it never happened.
Robots are great, but inspiration is the reason we're here.
Friends don't let friends use master links.

Last edited by GeeTwo : 13-12-2016 at 18:33.
Reply With Quote
  #8   Spotlight this post!  
Unread 13-12-2016, 19:13
ahartnet's Avatar
ahartnet ahartnet is offline
Registered User
AKA: Andrew Hartnett
FRC #5414 (Pearadox)
Team Role: Mentor
 
Join Date: Jan 2011
Rookie Year: 2005
Location: Houston, Texas
Posts: 194
ahartnet has a brilliant futureahartnet has a brilliant futureahartnet has a brilliant futureahartnet has a brilliant futureahartnet has a brilliant futureahartnet has a brilliant futureahartnet has a brilliant futureahartnet has a brilliant futureahartnet has a brilliant futureahartnet has a brilliant futureahartnet has a brilliant future
Re: Need help understanding command-based Robots

After being confused at first about command-based programming, I am now a big fan of it. It allows for some pretty complex movements with organized and reusable code. The one definite downside is that it can actually make the code seem more complex than it actually is to someone who hasn't been working on it because of all the extra file structure and such. There's some other downsides to it if you want to really squeeze every bit of performance out of the roboRIO possible - but 5414 isn't at that point yet. euhlmann covered it and screensteps does a pretty good job in my opinion, but I'll just kind of repeat and add a little bit:

I like to start with the RobotMap - adding in static variable names for whatever motors or buttons you plan on having. For instance you might have:

Code:
public class RobotMap {
	public static int CollectorRetract = 12;
	public static int CollectorExtend = 8;	

}
and then in OI, making the connection from your interface to your new functions you'll be adding:

Code:
public class OI {

	private Joystick stick = new Joystick(0);		//Joystick in Driver Station Spot 0
	private Joystick stick2 = new Joystick(1);		//Joystick in Driver Station Spot 1
	
	public OI()
	{
		//Stick 2 Controls
		JoystickButton CollectorInStick2 = new JoystickButton(stick2, RobotMap.CollectorRetract);
		JoystickButton CollectorOutStick2 = new JoystickButton(stick2, RobotMap.CollectorExtend);

		CollectorInStick2.whileHeld(new CollectorInCommand());			//Collector Retract
		CollectorOutStick2.whileHeld(new CollectorOutCommand());			//Collector Extend
		CollectorInStick2.whenReleased(new CollectorStopCommand());		//Collector Retract Stop
		CollectorOutStick2.whenReleased(new CollectorStopCommand());		//Collector Extend Stop
       }
}
then, if it's not defined already, you'll have to define your subsystem. Your subsystem should include any motor controllers or sensors for that group of thing. For a drivetrain, that could be 4-6 CIMs, 2 encoders, a gyro, servos, shifting pneumatics, etc (but start small then add the rest in). For this simple example I'm walking through, it's just one motor. In this, we have three different things we do with our collector: extent, retract, and stop. For something (potentially) more complicated like a drivetrain, you might have functions to get encoder or gyro data, extend or retract cylinders to change gears, drive in arcade mode/tank mode, drive in a slow/demo mode that sets power to 75%, etc.

Code:
public class Collector extends Subsystem {
	private SpeedController deploy;
	// Put methods for controlling this subsystem
    // here. Call these from Commands.

    public void initDefaultCommand() {
        // Set the default command for a subsystem here.
        //setDefaultCommand(new MySpecialCommand());
    }
    public Collector() {
    	super();
    	deploy = new Spark(4);
    }
    public void CollectorIn(){
    	deploy.set(.7);
    }
    public void CollectorOut(){
    	deploy.set(-1);
    }
    public void CollectorStop(){
    	deploy.set(0);
    }
}
Then you have your command files that then use the functions within the subsystems. From what we set up in the OI.java file, we'd also want to create CollectorOutCommand.java and CollectorStopCommand.java. You call the functions that exist within your subsystem from your commands.
Code:
public class CollectorIn extends Command {

    public CollectorInCommand() {
    	requires(Robot.collector);
    }

    // Called just before this Command runs the first time
    protected void initialize() {
    	
    }

    // Called repeatedly when this Command is scheduled to run
    protected void execute() {
    	Robot.collector.CollectorIn();
    }

    // Make this return true when this Command no longer needs to run execute()
    protected boolean isFinished() {
    	return false; //We set this up in the OI so that it would call a function to stop it when the button was released
    }

    // Called once after isFinished returns true
    protected void end() {
    	Robot.collector.CollectorStop();
    }

    // Called when another command which requires one or more of the same
    // subsystems is scheduled to run
    protected void interrupted() {
    	end();
    }
}
You can also make the command groups as discussed on WPI lib. It's simple enough to understand that I won't include an example here. The great thing about using command based programming is that if you make a change to say, how fast you want the collector to extend - it takes affect anywhere you use that command. With sample robot - if you have the collector extend in autonomous and from a button push in tele-op, you have to be careful to make sure and go change it in both places. You can also include variable in it, so you can have a command that say turns your robot X degrees, with a different parameter sent that reuses the rest of the code the same.

Hope this helped some.
__________________
Team 451 The Cat Attack, Student Alumni (2005)
Team 1646 Precision Guessworks, Mentor (2006-2008)
Team 2936 Gatorzillas, Mentor (2011-2014)
Team 5414 Pearadox, Mentor (2015-Present)

Last edited by ahartnet : 13-12-2016 at 19:24.
Reply With Quote
  #9   Spotlight this post!  
Unread 13-12-2016, 21:38
cpapplefamily cpapplefamily is offline
Registered User
FRC #3244 (Granite City Gearheads)
Team Role: Mentor
 
Join Date: May 2015
Rookie Year: 2015
Location: Minnesota
Posts: 243
cpapplefamily has a spectacular aura aboutcpapplefamily has a spectacular aura about
Re: Need help understanding command-based Robots

I have my programmers watch these 6 videos. https://www.youtube.com/watch?v=k7PaYcjDEDc&list=PLYA9eZLlgz7t9Oleid2wtlgn vhGObeKzp We are a Java team but these videos do apply to C++ as well. Last year was my first year as a coach, I watched these, Played along and simulated the programs in FRCSim. The one student program we had last year called it "cheating".
Reply With Quote
  #10   Spotlight this post!  
Unread 13-01-2017, 08:33
Ayece Ayece is offline
Registered User
FRC #5132
 
Join Date: Nov 2016
Location: Winder , GA
Posts: 1
Ayece is an unknown quantity at this point
Re: Need help understanding command-based Robots

Wow this thread is really useful for beginners such as myself good job guys.I was also having trouble understanding the subsystems as well as how we were to assign the controller to the code onto the robot but this thread cleared a lot of those problems up.Thanks Guys!
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 12:17.

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