How simple should commands be? And how should they be structured?

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

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.

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.

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 ¯_(ツ)_/¯

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()).