Go to Post Haters gonna hate; kill 'em with kindness. - Taylor [more]
Home
Go Back   Chief Delphi > Technical > Programming > Java
CD-Media   CD-Spy  
portal register members calendar search Today's Posts Mark Forums Read FAQ rules

 
 
 
Thread Tools Rate Thread Display Modes
Prev Previous Post   Next Post Next
  #3   Spotlight this post!  
Unread 15-11-2015, 16:20
notmattlythgoe's Avatar
notmattlythgoe notmattlythgoe is offline
Flywheel Police
AKA: Matthew Lythgoe
FRC #2363 (Triple Helix)
Team Role: Mentor
 
Join Date: Feb 2010
Rookie Year: 2009
Location: Newport News, VA
Posts: 1,715
notmattlythgoe has a reputation beyond reputenotmattlythgoe has a reputation beyond reputenotmattlythgoe has a reputation beyond reputenotmattlythgoe has a reputation beyond reputenotmattlythgoe has a reputation beyond reputenotmattlythgoe has a reputation beyond reputenotmattlythgoe has a reputation beyond reputenotmattlythgoe has a reputation beyond reputenotmattlythgoe has a reputation beyond reputenotmattlythgoe has a reputation beyond reputenotmattlythgoe has a reputation beyond repute
Re: Java Conditional Command

Quote:
Originally Posted by randallh View Post
Be sure that the command that precedes the conditional command is a one-shot command that executes once and returns immediately. Otherwise, it will never complete and your conditional command will never get a chance to run.

If you're using Java 8, you could simplify most of your code by using lambdas rather than hard-code the comparison operations. For example, your ConditionalWaitCommand can use the `java.util.function.Predicate` functional interface to define when it is completed:

Code:
public class ConditionalWaitCommand extends Command {
	
	public static ConditionalWaitCommand waitUntil( Predicate isComplete ) {
	}

	private final Predicate isComplete;

	private ConditionalWaitCommand(Predicate isComplete) {
		this.isComplete = isComplete;
	}

	@Override
	protected void initialize() { }

	@Override
	protected void execute() {
		return isComplete().test();
	}

	protected boolean isFinished() { }

	@Override
	protected void end() { }

	@Override
	protected void interrupted() { }
}
This makes this class very simple but even more flexible than your version. Your DriveToLine command group becomes:

Code:
public class DriveToLine extends CommandGroup {
    
    public  DriveToLine() {
    	addSequential(new DriveCommand(0.5));
        addSequential(waitUntil(drivetrain.getDistance() > 50));
        addSequential(new DriveCommand(0));
    }
}
But sometimes it is much easier just to create a generic and reusable command that is easily instantiated with custom lambdas using static methods. One example might be a very simple but generic Command subclass that takes an optional lambda to run once, a predicate to know when it is complete, and an optional function to run when complete. The static factory methods make this really easy to reuse without having to create a concrete subclass.

Here's what that might look like to create a command instance that drives at 50% power while the distance is greater than 50, and once that condition has occurred then stop:

Code:
    Drivetrain driveTrain = ...
    Command myCommand = ConditionalCommand.runUntil(driveTrain.drive(0.5),
                                                    drivetrain.getDistance() > 50.0,
                                                    driveTrain.stop());
where

Code:
public class ConditionalCommand extends Command {
	
	public static ConditionalCommand waitUntil( Runnable initial, Predicate isComplete, Runnable uponComplete ) {
		return new ConditionalCommand(initial, isComplete, uponComplete);
	}

	public static ConditionalCommand waitUntil( Predicate isComplete, Runnable uponComplete ) {
		return new ConditionalCommand(initial, isComplete, uponComplete);
	}

	private final Runnable initial;
	private final Predicate isComplete;
	private final Runnable uponComplete;
	private boolean completed;

	private ConditionalCommand(Predicate isComplete) {
		this.isComplete = isComplete;
	}

	@Override
	protected void initialize() {
		if ( initial != null ) initial.run();
	}

	@Override
	protected void execute() {
		if ( isComplete().test() ) {
			if ( uponComplete != null ) uponComplete.run();
			completed = true;
		}
	}

	protected boolean isFinished() {
		return completed;
	}

	@Override
	protected void end() { }

	@Override
	protected void interrupted() { }
}
This is not the only pattern, either.
Yeah, I should have set the first command as parallel not sequential. I like the lambda ideas. Going to have to play around with them.

GeeTwo, it works because getDistance() returns an object not a value. So the getValue() call on the object at the time of the comparison will get the current value.

Last edited by notmattlythgoe : 15-11-2015 at 16:26.
Reply With Quote
 


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 10:16.

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