Log in

View Full Version : How simple should commands be? And how should they be structured?


jreneew2
28-04-2016, 20:38
Hello everyone,

I was wondering how other people structured or put together commands in their command-based robots. I am always struggling with myself on how to structure them and how simple they should be.

For example, lets say I want to open and close a solenoid. Should I make a command that opens it, and a command that closes it, or just have a single command that gets passed a value to tell which valve I want to open?

I think the first way of doing that is way too "separated", so in my code I use the second method.

However, one issue I always run into is when I want to use "axis" values on a joystick in a command. For example, on our shooter, we use the right trigger on the xbox 360 controller for spinning up our shooter, but that leads to a weird situation where I had to write a special condition where if the time parameter passed in was exactly 0, it would assume it was in teleoperated mode. Here is what I am talking about:


timeCurrent = timer->Get();
if(timeTarget == 0) {
if(rightTrigger2 > 0.2) {
//Robot::shooterSubsystem->Shoot(12);
Robot::shooterSubsystem->Shoot(6000);
Robot::intakeSubsystem->Intake(-1);
}
else if(leftTrigger2 > 0.2) {
Robot::shooterSubsystem->Shoot(-1500);
Robot::intakeSubsystem->Intake(1);
Robot::shooterSubsystem->SetAngleLeftServo(0);
Robot::shooterSubsystem->SetAngleRightServo(200);
}
else {
Robot::shooterSubsystem->Shoot(0);
Robot::intakeSubsystem->Intake(0);
Robot::shooterSubsystem->SetAngleLeftServo(70);
Robot::shooterSubsystem->SetAngleRightServo(110);
}
isDone = true;
}
else {
if(timeCurrent >= timeTarget) {
Robot::shooterSubsystem->Shoot(0);
isDone = true;
}
else {
Robot::shooterSubsystem->Shoot(inputSpeed);
isDone = false;
}
}


That way of doing it seems wrong, but I'm not sure. Opinions and suggestions would be greatly appreciated!

Thanks,
Drew

414cnewq
28-04-2016, 21:22
When I needed to activate something via the Xbox 360 controller, I used the wpilib triggers functionality.
My GetTrigger.h (C++)
#ifndef GetTrigger_H
#define GetTrigger_H

#include "WPILib.h"

class GetTrigger: public Trigger
{
private:
int m_axis;
Joystick* joy;
public:
GetTrigger(int, Joystick*);
bool Get();
};

#endif
And GetTrigger.CPP

#include "GetTrigger.h"

GetTrigger::GetTrigger(int axis, Joystick* Joy)
{
joy=Joy;
m_axis=axis;
}

bool GetTrigger::Get()
{
return joy->GetRawAxis(m_axis)>0;
}


You just declare an object of Type, in this case, GetTrigger in your OI as defined in your constructor and Initialize it like a JoystickButton. If I'm too vaugue, just look in the WPIlub documentation on Triggers here (http://first.wpi.edu/FRC/roborio/release/docs/cpp/classTrigger.html).

jreneew2
28-04-2016, 21:25
Oh wow! I didn't even know that existed! Thanks!

I still would like to keep this thread up for discussion on how people use the command based framework. I find it very intresting how people structure their code.

euhlmann
28-04-2016, 22:56
For example, lets say I want to open and close a solenoid. Should I make a command that opens it, and a command that closes it, or just have a single command that gets passed a value to tell which valve I want to open?


I think it makes more sense to have a single command. The way we threw together commands like this was something like

class SomethingToggleCommand: CommandBase {
int m_mode;
public:
SomethingToggleCommand(){ // default action: toggle
m_mode = 2;
}
SomethingToggleCommand(bool isOpen){ // explicitly set open or closed
m_mode = isOpen;
}
void Execute(){
if(m_mode == 2) {
somethingSubsystem->setSomething(!somethingSubsystem->isSomethingOpen());
} else {
somethingSubsystem->setSomething(m_mode);
}
}
bool IsFinished(){
return true;
}
// etc
}



I don't think it's the best way in terms of design, but it works ¯\_(ツ)_/¯

GeeTwo
29-04-2016, 16:48
As far as I am aware, none of our commands take arguments.

As an example, for our ball pickup, we have four separate commands:


BallPickupForward()
BallPickupReverse()
BallPickupStop()
ControlIntakeMotor()

ControlIntakeMotor() reads the joystick and selects the appropriate command of the other three. (It would probably have been better named something like BallPickupOperate()).