Go to Post OK guys, the robot's overweight. You know the drill. - DonRotolo [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 03-21-2014, 11:46 PM
MrRoboSteve MrRoboSteve is offline
Mentor
AKA: Steve Peterson
FRC #3081 (Kennedy RoboEagles)
Team Role: Mentor
 
Join Date: Mar 2012
Rookie Year: 2011
Location: Bloomington, MN
Posts: 566
MrRoboSteve has a reputation beyond reputeMrRoboSteve has a reputation beyond reputeMrRoboSteve has a reputation beyond reputeMrRoboSteve has a reputation beyond reputeMrRoboSteve has a reputation beyond reputeMrRoboSteve has a reputation beyond reputeMrRoboSteve has a reputation beyond reputeMrRoboSteve has a reputation beyond reputeMrRoboSteve has a reputation beyond reputeMrRoboSteve has a reputation beyond reputeMrRoboSteve has a reputation beyond repute
How to change command associated with button

We're doing some night-of-regionals programming changes, and one idea we were investigating was swapping the command associated with a button by calling WhenPressed() to replace the command bound to the button. (Our goal was to make one button that advances through a couple different states).

Looking at the WPILib code, it looks like WhenPressed() calls are additive, and it's not possible to replace the command associated with a button. Is that correct?

Our alternate approach is to maintain a state variable and vary the behavior of the associated command based on the state, but it seems less clean than replacing the command.
__________________
2016-17 events: 10000 Lakes Regional, Northern Lights Regional, FTC Burnsville Qualifying Tournament

2011 - present · FRC 3081 Kennedy RoboEagles mentor
2013 - present · event volunteer at 10000 Lakes Regional, Northern Lights Regional, North Star Regional, Lake Superior Regional, Minnesota State Tournament, PNW District 4 Glacier Peak, MN FTC, CMP
http://twitter.com/MrRoboSteve · www.linkedin.com/in/speterson
Reply With Quote
  #2   Spotlight this post!  
Unread 03-22-2014, 01:38 AM
Alan Anderson's Avatar
Alan Anderson Alan Anderson is offline
Software Architect
FRC #0045 (TechnoKats)
Team Role: Mentor
 
Join Date: Feb 2004
Rookie Year: 2004
Location: Kokomo, Indiana
Posts: 9,112
Alan Anderson has a reputation beyond reputeAlan Anderson has a reputation beyond reputeAlan Anderson has a reputation beyond reputeAlan Anderson has a reputation beyond reputeAlan Anderson has a reputation beyond reputeAlan Anderson has a reputation beyond reputeAlan Anderson has a reputation beyond reputeAlan Anderson has a reputation beyond reputeAlan Anderson has a reputation beyond reputeAlan Anderson has a reputation beyond reputeAlan Anderson has a reputation beyond repute
Re: How to change command associated with button

Another option might be to have the command call other "subcommands" based on the state variable. That way you can keep all the commands separate, with the only messiness being in the main command that does nothing except dispatch to other commands.
Reply With Quote
  #3   Spotlight this post!  
Unread 03-23-2014, 12:34 PM
MrRoboSteve MrRoboSteve is offline
Mentor
AKA: Steve Peterson
FRC #3081 (Kennedy RoboEagles)
Team Role: Mentor
 
Join Date: Mar 2012
Rookie Year: 2011
Location: Bloomington, MN
Posts: 566
MrRoboSteve has a reputation beyond reputeMrRoboSteve has a reputation beyond reputeMrRoboSteve has a reputation beyond reputeMrRoboSteve has a reputation beyond reputeMrRoboSteve has a reputation beyond reputeMrRoboSteve has a reputation beyond reputeMrRoboSteve has a reputation beyond reputeMrRoboSteve has a reputation beyond reputeMrRoboSteve has a reputation beyond reputeMrRoboSteve has a reputation beyond reputeMrRoboSteve has a reputation beyond repute
Re: How to change command associated with button

Alan -- good idea. Our programmer Ryan came up with a similar solution where a command has a Boolean state that indicates which of the two desired command actions should be executed. It then schedules the desired command, and slaves IsFinished() to the same state of the scheduled command. I'll see if I can get him to post it here so that the there's a record for the community in the future.
__________________
2016-17 events: 10000 Lakes Regional, Northern Lights Regional, FTC Burnsville Qualifying Tournament

2011 - present · FRC 3081 Kennedy RoboEagles mentor
2013 - present · event volunteer at 10000 Lakes Regional, Northern Lights Regional, North Star Regional, Lake Superior Regional, Minnesota State Tournament, PNW District 4 Glacier Peak, MN FTC, CMP
http://twitter.com/MrRoboSteve · www.linkedin.com/in/speterson
Reply With Quote
  #4   Spotlight this post!  
Unread 03-23-2014, 07:18 PM
jwakeman jwakeman is offline
Registered User
FRC #0063 (Red Barons)
Team Role: Mentor
 
Join Date: Jan 2011
Rookie Year: 2010
Location: 16510
Posts: 182
jwakeman is just really nicejwakeman is just really nicejwakeman is just really nicejwakeman is just really nicejwakeman is just really nice
Re: How to change command associated with button

Quote:
Originally Posted by MrRoboSteve View Post
one idea we were investigating was swapping the command associated with a button by calling WhenPressed() to replace the command bound to the button.
I tried to accomplish this (in java) by just creating a new button object and calling WhenPressed() on that new object when I wanted to change the command associated with a particular joystick button. It didn't really work out..and I couldn't really make sense of the behavior when testing. I didn't bother deleting (maybe java calls it disposing) the prior objects when creating new ones (since in java there is this magical thing called the garbage collector) but maybe that would have helped. My thread, http://www.chiefdelphi.com/forums/sh...d.php?t=127920 contains the code I tried to use. I think the ability clear the commands associated with a button would be a useful feature to add. Maybe I will get around to entering an artifact on the FIRST Forge project page
Reply With Quote
  #5   Spotlight this post!  
Unread 03-24-2014, 12:14 PM
DjScribbles DjScribbles is offline
Programming Mentor
AKA: Joe S
FRC #2474 (Team Excel)
Team Role: Mentor
 
Join Date: Oct 2011
Rookie Year: 2012
Location: Niles MI
Posts: 284
DjScribbles is a splendid one to beholdDjScribbles is a splendid one to beholdDjScribbles is a splendid one to beholdDjScribbles is a splendid one to beholdDjScribbles is a splendid one to beholdDjScribbles is a splendid one to beholdDjScribbles is a splendid one to beholdDjScribbles is a splendid one to behold
Re: How to change command associated with button

@jwakeman: your issue appears to be that your alternate condition was causing a new command to be created every iteration. This would cause a new command to be created, assigned to the button, and interrupt the old each iteration.

I haven't tried this code, but the pattern I used was like this:
Code:
<in class definition>
Command *mainCommand;
Command *altCommand;

<in constructor>
mainCommand = new MainCommand();
altCommand = new AlternativeCommand();

<in periodic function within the same class>
    if (condition)
    {
        button->whenPressed(altCommand);
    }
    else
    {
        button->whenPressed(mainCommand);
    }
This way, you have only have one instance of each command that can be assigned to the button.
I put this code in the OI class, and added an UpdateOI function, which is called from the teleop periodic loop.

Last edited by DjScribbles : 03-24-2014 at 12:20 PM.
Reply With Quote
  #6   Spotlight this post!  
Unread 03-25-2014, 01:09 PM
jwakeman jwakeman is offline
Registered User
FRC #0063 (Red Barons)
Team Role: Mentor
 
Join Date: Jan 2011
Rookie Year: 2010
Location: 16510
Posts: 182
jwakeman is just really nicejwakeman is just really nicejwakeman is just really nicejwakeman is just really nicejwakeman is just really nice
Re: How to change command associated with button

Quote:
Originally Posted by DjScribbles View Post
@jwakeman: your issue appears to be that your alternate condition was causing a new command to be created every iteration
Thanks for taking a look at my code. The second if condition in the actually has a 'not operator' (!) on the throwSwitch1.get() so I don't think I was creating new command every iteration.

Code:
        if(throwSwitch1.get() && oi.current_interface == oi.CONFIG_FIELD_INTERFACE)
        {
            oi.setPitInterface();
        }
        
        if(!throwSwitch1.get() && oi.current_interface == oi.CONFIG_PIT_INTERFACE)
        {
            oi.setFieldInterface();
        }
My code would probably be more readable if I used throwSwitch1.get() == false, throwSwitch1.get() == true. I like your suggestion of switching back and forth between pre-made commands instead of creating new every time I switch. This still leaves the issue of being able to unmap a command, i.e. have a button go from doing something to doing nothing. I suppose you could create a null command which does nothing and switch between that and the do something command.
Reply With Quote
  #7   Spotlight this post!  
Unread 03-25-2014, 05:29 PM
MrRoboSteve MrRoboSteve is offline
Mentor
AKA: Steve Peterson
FRC #3081 (Kennedy RoboEagles)
Team Role: Mentor
 
Join Date: Mar 2012
Rookie Year: 2011
Location: Bloomington, MN
Posts: 566
MrRoboSteve has a reputation beyond reputeMrRoboSteve has a reputation beyond reputeMrRoboSteve has a reputation beyond reputeMrRoboSteve has a reputation beyond reputeMrRoboSteve has a reputation beyond reputeMrRoboSteve has a reputation beyond reputeMrRoboSteve has a reputation beyond reputeMrRoboSteve has a reputation beyond reputeMrRoboSteve has a reputation beyond reputeMrRoboSteve has a reputation beyond reputeMrRoboSteve has a reputation beyond repute
Re: How to change command associated with button

This is what Ryan from 3081 put together. We did a bit of testing of it at Wisconsin, will be bashing it more in the next few days.

Code:
// header

class SwapCommandCommand: public CommandBase {
private:
	bool swapState;
	Command *commandOne;
	Command *commandTwo;
	Command *runningCommand;
public:
	SwapCommandCommand(Command *commandOne, Command *commandTwo);
	virtual void Initialize();
	virtual void Execute();
	virtual bool IsFinished();
	virtual void End();
	virtual void Interrupted();
	void Reset();
};


// cpp
SwapCommandCommand::SwapCommandCommand(Command *commandOne, Command *commandTwo) {
	// Use requires() here to declare subsystem dependencies
	// eg. requires(chassis);
	this->commandOne = commandOne;
	this->commandTwo = commandTwo;
	//False for command one
	//True for command Two
	this->swapState = false;
	this->runningCommand = NULL;
}

void SwapCommandCommand::Initialize() {
	if(swapState) {
		printf("[SwapCommandCommand] Scheduling Command two\n");
		this->runningCommand = commandTwo;
	} else {
		this->runningCommand = commandOne;
		printf("[SwapCommandCommand] Scheduling Command One\n");
	}
	this->runningCommand->Start();
}

void SwapCommandCommand::Execute() {
}


bool SwapCommandCommand::IsFinished() {
	return !runningCommand->IsRunning();
}

void SwapCommandCommand::End() {
	printf("[SwapCommandCommand] The command has finished\n");
	swapState = !swapState;
}

void SwapCommandCommand::Interrupted() {
	printf("[SwapCommandCommand] Interrupted canceling command\n");
	this->runningCommand->Cancel();
}


void SwapCommandCommand::Reset() {
	this->swapState = false;
}
__________________
2016-17 events: 10000 Lakes Regional, Northern Lights Regional, FTC Burnsville Qualifying Tournament

2011 - present · FRC 3081 Kennedy RoboEagles mentor
2013 - present · event volunteer at 10000 Lakes Regional, Northern Lights Regional, North Star Regional, Lake Superior Regional, Minnesota State Tournament, PNW District 4 Glacier Peak, MN FTC, CMP
http://twitter.com/MrRoboSteve · www.linkedin.com/in/speterson
Reply With Quote
  #8   Spotlight this post!  
Unread 03-26-2014, 09:54 PM
nowireless nowireless is offline
Registered User
AKA: Ryan Sjostrand
FRC #3081 (Robo Eagles)
Team Role: Alumni
 
Join Date: Jan 2013
Rookie Year: 2012
Location: Bloomington, MN
Posts: 4
nowireless is an unknown quantity at this point
Re: How to change command associated with button

Here is a updated version of the swap command. It waits a few cycles before checking to see if the command has finished, to allow the command to be scheduled and then ran by the scheduler.

Header
Code:
#ifndef SWAPCOMMANDCOMMAND_H
#define SWAPCOMMANDCOMMAND_H

#include "../CommandBase.h"

/**
 *
 *
 * @author nowireless
 */
class SwapCommandCommand: public CommandBase {
private:
	bool swapState;
	int runCount;
	Command *commandOne;
	Command *commandTwo;
	Command *runningCommand;
public:
	SwapCommandCommand(Command *commandOne, Command *commandTwo);
	virtual void Initialize();
	virtual void Execute();
	virtual bool IsFinished();
	virtual void End();
	virtual void Interrupted();
	void Reset();
};

#endif
CPP
Code:
#include "SwapCommandCommand.h"

SwapCommandCommand::SwapCommandCommand(Command *commandOne, Command *commandTwo) {
	// Use requires() here to declare subsystem dependencies
	// eg. requires(chassis);
	this->commandOne = commandOne;
	this->commandTwo = commandTwo;
	//False for command one
	//True for command Two
	this->swapState = false;
	this->runCount = 0;
	this->runningCommand = NULL;

}

// Called just before this Command runs the first time
void SwapCommandCommand::Initialize() {
	this->runCount = 0;
	if(swapState) {
		printf("[SwapCommandCommand] Scheduling Command two\n");
		this->runningCommand = commandTwo;
	} else {
		this->runningCommand = commandOne;
		printf("[SwapCommandCommand] Scheduling Command One\n");
	}
	this->runningCommand->Start();
}

// Called repeatedly when this Command is scheduled to run
void SwapCommandCommand::Execute() {
	/* 
	 * We count the number of times the execute method is called,
	 * to allow the command to be scheduled and to be ran by the scheduler.
	 * This is is done to prevent this command from ending before the selected command has had a chance to run.
	 */
	
	if(this->runCount <= 2) {
		this->runCount++;
	}
}

// Make this return true when this Command no longer needs to run execute()
bool SwapCommandCommand::IsFinished() {
	return !runningCommand->IsRunning() && this->runCount >= 3;
}

// Called once after isFinished returns true
void SwapCommandCommand::End() {
	printf("[SwapCommandCommand] The command has finished\n");
	swapState = !swapState;
}

// Called when another command which requires one or more of the same
// subsystems is scheduled to run
void SwapCommandCommand::Interrupted() {
	printf("[SwapCommandCommand] Interrupted canceling command\n");
	this->runningCommand->Cancel();
}

void SwapCommandCommand::Reset() {
	this->swapState = false;
}
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 09:16 AM.

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