Go to Post No matter what route you choose, it's always a good idea to keep Mike Walker's cell phone on speed dial. - Joe Ross [more]
Home
Go Back   Chief Delphi > Technical > Programming
CD-Media   CD-Spy  
portal register members calendar search Today's Posts Mark Forums Read FAQ rules

 
Closed Thread
Thread Tools Rate Thread Display Modes
  #16   Spotlight this post!  
Unread 03-01-2014, 19:25
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,113
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: Making more reusable commands

Quote:
Originally Posted by Joe Ross View Post
...after writing the same code in a subsystem for the 6th solenoid and the 3rd on/off motor,...
It sounds like you were right when you don't have the experience you need with Object Oriented programming. Instead of writing the same code in multiple places for multiple solenoids, you probably could have extended the Solenoid class with the methods you wanted. Extension though Inheritance is probably one of the best tools you can use for the kind of configurable control you're talking about.
  #17   Spotlight this post!  
Unread 03-01-2014, 19:36
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: 582
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: Making more reusable commands

Here's a nice example of a command that takes a parameter.

Code:
#include "TurnSpecifiedDegreesCommand.h"
#include "math.h"

// If we're within this # of degrees to target, then we're good.

#define DEGREES_PRECISION 2


/*
 * This command turns the number of degrees specified in the dashboard field.
 */
TurnSpecifiedDegreesCommand::TurnSpecifiedDegreesCommand(float degreesToTurn) 
	: CommandBase("TurnSpecifiedDegreesCommand") {
	Requires(chassis);
	this->degreesToTurn = degreesToTurn;
}

// Called just before this Command runs the first time
void TurnSpecifiedDegreesCommand::Initialize() {
	this->finished = false;
	this->startingAngle = sensorSubsystem->GetHorizontalAngle();
	this->goalAngle = startingAngle + this->degreesToTurn;
	printf("TurnSpecifiedDegreesCommand %f\n", this->degreesToTurn);
}

// Called repeatedly when this Command is scheduled to run
void TurnSpecifiedDegreesCommand::Execute() {
	float currentAngle = sensorSubsystem->GetHorizontalAngle();
	float angleDifference = goalAngle - currentAngle;
	
	SmartDashboard::PutNumber("Goal angle", goalAngle);
	SmartDashboard::PutNumber("Angle difference", fabs(angleDifference));
	printf("Angle difference %f goalAngle %f currentAngle %f\n", angleDifference, goalAngle, currentAngle);
	
	float turnRate = 0;
	
	if (fabs(angleDifference) < DEGREES_PRECISION) {
		chassis->Stop();
		finished = true;
	} else {
		// We slow our rate of turn as we get close to the angle we want.
		// These values are guesses.  A PID would be better here.
		if (angleDifference > 10 || angleDifference < -10) {
			turnRate = 0.7;
		} else {
			// Look at changing this at competition
			turnRate = 0.6;
		}
		
		SmartDashboard::PutNumber("turn rate", turnRate);
		
		if (angleDifference > 0) {
			chassis->TurnLeft(turnRate);
		} else {
			chassis->TurnRight(turnRate);
		}
	}
}

// Make this return true when this Command no longer needs to run execute()
bool TurnSpecifiedDegreesCommand::IsFinished() {
	return finished;	
}

// Called once after isFinished returns true
void TurnSpecifiedDegreesCommand::End() {
	printf("TurnSpecifiedDegreesCommand completed.\n");
}

// Called when another command which requires one or more of the same
// subsystems is scheduled to run
void TurnSpecifiedDegreesCommand::Interrupted() {
}
__________________
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
  #18   Spotlight this post!  
Unread 03-01-2014, 21:40
Joe Ross's Avatar Unsung FIRST Hero
Joe Ross Joe Ross is offline
Registered User
FRC #0330 (Beachbots)
Team Role: Engineer
 
Join Date: Jun 2001
Rookie Year: 1997
Location: Los Angeles, CA
Posts: 8,600
Joe Ross has a reputation beyond reputeJoe Ross has a reputation beyond reputeJoe Ross has a reputation beyond reputeJoe Ross has a reputation beyond reputeJoe Ross has a reputation beyond reputeJoe Ross has a reputation beyond reputeJoe Ross has a reputation beyond reputeJoe Ross has a reputation beyond reputeJoe Ross has a reputation beyond reputeJoe Ross has a reputation beyond reputeJoe Ross has a reputation beyond repute
Re: Making more reusable commands

Quote:
Originally Posted by Tom Bottiglieri View Post
125 did this last year a little differently by subclassing subsystem, then building Commands that could control those types of subsystems.
https://github.com/kreeve/Nutrons201...Subsystem.java
Thanks, that's very similar to what I was thinking about.
  #19   Spotlight this post!  
Unread 04-01-2014, 01:23
Jefferson Jefferson is offline
Registered User
AKA: Jeff Clements
FRC #0016 (Bomb Squad)
Team Role: Mentor
 
Join Date: Jan 2011
Rookie Year: 2010
Location: Mountain Home, AR
Posts: 258
Jefferson has a reputation beyond reputeJefferson has a reputation beyond reputeJefferson has a reputation beyond reputeJefferson has a reputation beyond reputeJefferson has a reputation beyond reputeJefferson has a reputation beyond reputeJefferson has a reputation beyond reputeJefferson has a reputation beyond reputeJefferson has a reputation beyond reputeJefferson has a reputation beyond reputeJefferson has a reputation beyond repute
Re: Making more reusable commands

Quote:
Originally Posted by notmattlythgoe View Post
I guess my question is, why not design the systems the solenoids use as a subsystem? We had subsystems this year that were just a single solenoid (trigger, shooter elevation, hopper, and pickup arm). We like to separate the solenoids into subsystems because we feel that it makes the project easier to read and practices good OOD technique by locking those devices into a subsystem that only a command requiring that subsystem is allowed access to control.
By doing it the way you describe, 4 lines of code turn into a subsystem with two additional functions and two commands. Each of those objects add to compile time, which turned into well over a minute with all of our commands in 2013. We'll just have to disagree which option is easier to read. The risk of other code writing to the solenoids, while possible, is not worth the complexity created by using commands.
  #20   Spotlight this post!  
Unread 04-01-2014, 01:47
Ziv Ziv is offline
Has code to be writing...
FRC #0125 (Nutrons)
Team Role: Alumni
 
Join Date: Mar 2010
Rookie Year: 2009
Location: Boston
Posts: 39
Ziv is a glorious beacon of lightZiv is a glorious beacon of lightZiv is a glorious beacon of lightZiv is a glorious beacon of lightZiv is a glorious beacon of light
Re: Making more reusable commands

Tom already mentioned my favorite approach to the problem . It allows for both abstracting away implementation details (the outside code never sees a solenoid) and easy parametrization (just describe what it means for a subsystem to be on or off and you get a bunch of methods and commands for free). Many shooters in 2013 (including 125's and apparently 330's) were well-suited for this approach, because, unlike shooting baskets or balancing in 2012, shooting frisbees and pyramid pull-ups generally didn't need to be done in more than one or two ways.

It's not frequent that there's such a nice common abstraction for all of a robot's subsystems, but every robot deserves a bit of thought about what code can be shared before throwing the towel in and making it in RobotBuilder. (If you're bored by repetition, don't make the repetition easier without first trying to avoid the repetition altogether. RobotBuilder does the first but not the second.) When designing a set of abstractions, I find the most important thing is to be extremely picky, even if it feels petty. You should *like* the result because you think it's *pretty* (or at least useful, if you don't see how anyone could use that adjective about code ). The 30 minutes of code architecture debate might only save you 30 seconds in the future, but the 30 minutes can be before the robot is ready to test while the 30 seconds will probably be right before a match.
Closed Thread


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:35.

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