Go to Post The sign applause was definately one of the best moments I had ever witnessed at a FIRST event. Who knew silence could be so loud? - Koko Ed [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 23-02-2013, 11:14
ssong1995 ssong1995 is offline
Registered User
FRC #1403
 
Join Date: Oct 2011
Location: Belle Mead
Posts: 12
ssong1995 is an unknown quantity at this point
Command-Based robot button toggle question

We are having a problem regarding making a toggle method for the button class. In the OI file, we plan to code certain buttons such that the first time its pressed one command would execute, the next time a different command would, and it would alternate between (thus toggling between these two states).

One of the powerpoints we came across described going into the Button source code file and adding a new method, so we wrote a new one that accepts two commands as the parameters and have worked out the logic for the toggle. It doesn't seem to be working, so could someone explain the proper way to code it? Thank you very much.

state is set to false in the beginning, and:

void Button::WhenToggled(Command *command1, Command *command2){

if(state){
WhenActive(command2);
state = false;
} else {
WhenActive(command1);
state = true;
}
}
Reply With Quote
  #2   Spotlight this post!  
Unread 23-02-2013, 11:21
Ether's Avatar
Ether Ether is offline
systems engineer (retired)
no team
 
Join Date: Nov 2009
Rookie Year: 1969
Location: US
Posts: 8,098
Ether has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond repute
Re: Command-Based robot button toggle question


In order to toggle, you first have to detect the rising edge of your joystick button (because you want it to toggle only once when you press the button, not repeatedly while you're holding the button down).

Then you toggle a boolean each time a rising edge is detected. Then use the value in that boolean to determine what action to take.

For example:

Code:
button1 = getButton(1);
if (button1 && ! button1previous) toggle = ! toggle;
button1previous = button1;


Last edited by Ether : 23-02-2013 at 11:23.
Reply With Quote
  #3   Spotlight this post!  
Unread 23-02-2013, 12:35
Itamar's Avatar
Itamar Itamar is offline
Registered User
FRC #1943 (NeatTeam) & FRC #4590 (GreenBlitz)
Team Role: Mentor
 
Join Date: Jan 2010
Rookie Year: 2010
Location: Israel
Posts: 83
Itamar is an unknown quantity at this point
Re: Command-Based robot button toggle question

Changing WPILib's code is a bit risky, I wouldn't do that. You could, however, write some classes of your own that demonstrate similar principles. What I would do is define a "ToggledPressedButtonScheduler" class:

http://pastebin.com/agFtqpAN
http://pastebin.com/bZwmbD21

It's based on "PressedButtonScheduler", but starts a different command every time the button is clicked. Here's how you should use it:

http://pastebin.com/SmBGNhFu

Please note that the code was written in pastebin and was not tested (or compiled).
Reply With Quote
  #4   Spotlight this post!  
Unread 23-02-2013, 12:36
Fifthparallel Fifthparallel is offline
Registered User
AKA: Sam Chen
FRC #1410
 
Join Date: Dec 2012
Rookie Year: 2011
Location: Denver, CO
Posts: 65
Fifthparallel is an unknown quantity at this point
Re: Command-Based robot button toggle question

Are the two commands related in any way? (i.e., could you use one command for both actions?). If so, you may want to consider refactoring either your subsystem or command code so that you have this functionality.

OR, you could put them all inside a command group with a bool that holds state, and based on that run either of two commands. Just make sure your "state" variable inside of whatever subsystem is actually being toggled back to whatever is needs to be.

Code:
//In the CommandGroup foo, you could either have a state that is toggled from within one of your subsystems,
//ala GetterSetter pattern and use this state to make a decision.

//OI code
JoystickButton *xyz = new JoystickButton(stick1, 11);
xyz->WhenPressed(new foo());

//CommandGroup 'foo' code

subsystemOne.ChangeStateOfFooBar();
if(subsystemOne.GetStateOfFooBar())
{
     AddSequential(new bar());
}
else
{
     AddSequential(new baz());
}
__________________
sudo chmod u+x helloworld.sh
gotta start somewhere.

Last edited by Fifthparallel : 23-02-2013 at 14:11.
Reply With Quote
  #5   Spotlight this post!  
Unread 23-02-2013, 13:17
Itamar's Avatar
Itamar Itamar is offline
Registered User
FRC #1943 (NeatTeam) & FRC #4590 (GreenBlitz)
Team Role: Mentor
 
Join Date: Jan 2010
Rookie Year: 2010
Location: Israel
Posts: 83
Itamar is an unknown quantity at this point
Re: Command-Based robot button toggle question

Quote:
Originally Posted by Fifthparallel View Post
Are the two commands related in any way? (i.e., could you use one command for both actions?). If so, you may want to consider refactoring either your subsystem or command code so that you have this functionality.

OR, you could put them all inside a command group with a bool that holds state, and based on that run either of two commands. Just make sure your "state" variable inside of whatever subsystem is actually being toggled back to whatever is needs to be.

Code:
//In the CommandGroup foo, you could either have a state that is toggled from within one of your subsystems,
//ala GetterSetter pattern and use this state to make a decision.

//OI code
JoystickButton *xyz = new JoystickButton(stick1, 11);
xyz->WhenPressed(new foo());

//CommandGroup code

subsystemOne.ChangeStateOfFooBar();
if(subsystemOne.GetStateOfFooBar())
{
     AddSequential(new bar());
}
else
{
     AddSequential(new baz());
}
Don't forget that the calls to "AddSequential" should be in the CommandGroup's constructor, which means they run only when an instance is created (probably when the code first runs). The condition you put there will not have the effect you expect it to have. The created CommandGroup will always run either "bar" or "baz", depending on the value "GetStateOfFooBar" returned when the constructor was called.
Reply With Quote
  #6   Spotlight this post!  
Unread 23-02-2013, 13:51
Itamar's Avatar
Itamar Itamar is offline
Registered User
FRC #1943 (NeatTeam) & FRC #4590 (GreenBlitz)
Team Role: Mentor
 
Join Date: Jan 2010
Rookie Year: 2010
Location: Israel
Posts: 83
Itamar is an unknown quantity at this point
Re: Command-Based robot button toggle question

Quote:
Originally Posted by Fifthparallel View Post
That's right. A CommandGroup inherits from Command. Whenever you press a button in the OI, it spawns a new object of XYZ CommandGroup. That is, it runs the constructor then and there on that button press (for a new Command/CommandGroup), which is exactly the functionality you want to have. On a quick test, it worked a few weeks earlier for me.
If you write in your OI constructor:

Code:
button->WhenPressed(new DoStuff());
That means one DoStuff instance is created, and that instance is passed to the "WhenPressed" function. It will be that same instance that runs every time the button is pressed. I don't see how this code will cause a new instance to be created every time the button is pressed.
Reply With Quote
  #7   Spotlight this post!  
Unread 23-02-2013, 14:13
Itamar's Avatar
Itamar Itamar is offline
Registered User
FRC #1943 (NeatTeam) & FRC #4590 (GreenBlitz)
Team Role: Mentor
 
Join Date: Jan 2010
Rookie Year: 2010
Location: Israel
Posts: 83
Itamar is an unknown quantity at this point
Re: Command-Based robot button toggle question

Quote:
Originally Posted by Fifthparallel View Post
It lies in the "new" keyword. The command you're instantiating is not a singleton, nor is it atomic. On that note, the WPILib function WhenPressed for a Joystick Button takes an argument for a command. You can insert new to make it create a new instance of that Command, i.e., the constructor for a new Command will run every time that button is pressed.
Uh... no, sorry, that's not how it works. If you look at the documentation, you'll see the following line:

Code:
void WhenActive (Command *command)
That means the function receives a pointer pointing at a Command object. When you write:

Code:
new DoStuff()
The type you get from that expression is a pointer to a DoStuff object (the one you just created). If you can point me to any piece of code that suggests it somehow uses that object to create more objects of that kind, please do.

Looking deeper into the code, you can see that instance ends up being stored in an instance of "PressedButtonScheduler", which takes it upon itself to check the state of the button and start the command instance if necessary (not create another instance).
Reply With Quote
  #8   Spotlight this post!  
Unread 23-02-2013, 14:28
Fifthparallel Fifthparallel is offline
Registered User
AKA: Sam Chen
FRC #1410
 
Join Date: Dec 2012
Rookie Year: 2011
Location: Denver, CO
Posts: 65
Fifthparallel is an unknown quantity at this point
Re: Command-Based robot button toggle question

So then would the OP be able to use a Command, but not a CommandGroup, and inside the Initialize() method get the state of whatever subsystem and run other commands from inside the Execute or Initialize methods?

Sorry, I did not look carefully and did not realize all of these happened in the constructor (I have been passing in values to command's constructors to have them do two different things during runtime, although all of that logic was in the subsystem's functions, not the command.)
__________________
sudo chmod u+x helloworld.sh
gotta start somewhere.
Reply With Quote
  #9   Spotlight this post!  
Unread 23-02-2013, 22:25
kylelanman's Avatar
kylelanman kylelanman is offline
Programming Mentor
AKA: Kyle
FRC #2481 (Roboteers)
Team Role: Mentor
 
Join Date: Feb 2008
Rookie Year: 2007
Location: Tremont Il
Posts: 189
kylelanman is a name known to allkylelanman is a name known to allkylelanman is a name known to allkylelanman is a name known to allkylelanman is a name known to allkylelanman is a name known to all
Re: Command-Based robot button toggle question

While I would be interested in a ToggleButton type that provides this functionality we found the following much easier.

Example of how our shooter works.

We use the following pattern for structuring our subsystems.
Code:
void raiseShooter();
void lowerShooter();
bool isRaised();
Then we have 3 commands.

RaiseShooterCommand:
Code:
void Execute() {
        shooter->raiseShooter();
}
LowerShooterCommand:
Code:
void Execute() {
        shooter->lowerShooter();
}
ToggleShooterCommand:
Code:
void Execute() {
    if (shooter->isRaised())
        shooter->lowerShooter();
    else
        shooter->raiseShooter();
}
The controls use the ToggleShooterCommand. Any command groups for sequences or auton use the explicit RaiseShooterCommand and LowerShooterCommand.
__________________
"May the coms be with you"

Is this a "programming error" or a "programmer error"?

Reply With Quote
  #10   Spotlight this post!  
Unread 27-02-2013, 18:53
ssong1995 ssong1995 is offline
Registered User
FRC #1403
 
Join Date: Oct 2011
Location: Belle Mead
Posts: 12
ssong1995 is an unknown quantity at this point
Re: Command-Based robot button toggle question

Thanks guys, we ended up going with the put-toggle-code-into-subsystems approach, and it works, so we're happy on that note.
Reply With Quote
  #11   Spotlight this post!  
Unread 04-03-2013, 17:34
JefferMC JefferMC is offline
Registered User
AKA: Jeff Corbett
FRC #1319 (Flash)
Team Role: Mentor
 
Join Date: Nov 2012
Rookie Year: 2005
Location: United States
Posts: 44
JefferMC will become famous soon enough
Re: Command-Based robot button toggle question

We originally did something very much like this final solution. Then we did something more like the command group idea:

Currently we have commands for Do, Undo and Toggle. On Toggle we ask the subsystem what the state is, then do a Start() on the appropriate Do or Undo command to go the other way.

We did this because we want the command to indicate which operation is ongoing (Do or Undo) for such reasons as display on the SmartDashboard and logging.
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 03:32.

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