Chief Delphi

Chief Delphi (http://www.chiefdelphi.com/forums/index.php)
-   Java (http://www.chiefdelphi.com/forums/forumdisplay.php?f=184)
-   -   CommandGroup questions (http://www.chiefdelphi.com/forums/showthread.php?t=126377)

pblankenbaker 13-02-2014 08:40

CommandGroup questions
 
I have a couple of questions regarding how command groups are processed.

As an example, lets assume that I want to:
  • Run CommandA first and wait for it to complete.
  • Then run CommandB and CommandC at the same time.
  • After CommandB and CommandC complete I then want to run CommandD.

I'm assuming the following would generate this sequence:

Code:

public static Command buildMyCommand() {
  CommandGroup bc = new CommandGroup();
  bc.addParallel(new CommandB());
  bc.addParallel(new CommandC());

  CommandGroup cmd = new CommandGroup();
  cmd.addSequential(new CommandA());
  cmd.addSequential(bc);
  cmd.addSequential(new CommandD());

  return cmd;
}

From my understanding of how addParallel() and addSequential() work, the above could also be written as:

Code:

public static Command buildMyCommand() {
  CommandGroup cmd = new CommandGroup();
  cmd.addSequential(new CommandA());
  // Start of first command to run in parallel
  cmd.addParallel(new CommandB());
  // End of commands to run in parallel (runs in parallel with CommandB)
  cmd.addSequential(new CommandC());
  cmd.addSequential(new CommandD());

  return cmd;
}

So, my first question is: Would the two versions of buildMyCommand() shown above produce the same results when run?

My next questions have to do with what happens to a command group when things don't complete nicely:
  • If CommandA from the example command group above was interrupted, would the entire command group be interrupted? For example, let's assume CommandA was waiting for something to move into position and CommandB performed a firing action. If CommandA was interrupted, would CommandB still run, or would the interruption stop CommandB from ever being run?
  • Secondly, Assume CommandA has used the setTimeout() method or was added to the group with a timeout option to indicate that it has 2 seconds to complete. If the timeout is reached, will the rest of the commands complete in the sequence?

Thanks,
Paul

notmattlythgoe 13-02-2014 08:42

Re: CommandGroup questions
 
Quote:

Originally Posted by pblankenbaker (Post 1342304)
I have a couple of questions regarding how command groups are processed.

As an example, lets assume that I want to:
  • Run CommandA first and wait for it to complete.
  • Then run CommandB and CommandC at the same time.
  • After CommandB and CommandC complete I then want to run CommandD.

I'm assuming the following would generate this sequence:

Code:

public static Command buildMyCommand() {
  CommandGroup bc = new CommandGroup();
  bc.addParallel(new CommandB());
  bc.addParallel(new CommandC());

  CommandGroup cmd = new CommandGroup();
  cmd.addSequential(new CommandA());
  cmd.addSequential(bc);
  cmd.addSequential(new CommandD());

  return cmd;
}

From my understanding of how addParallel() and addSequential() work, the above could also be written as:

Code:

public static Command buildMyCommand() {
  CommandGroup cmd = new CommandGroup();
  cmd.addSequential(new CommandA());
  // Start of first command to run in parallel
  cmd.addParallel(new CommandB());
  // End of commands to run in parallel (runs in parallel with CommandB)
  cmd.addSequential(new CommandC());
  cmd.addSequential(new CommandD());

  return cmd;
}

So, my first question is: Would the two versions of buildMyCommand() shown above produce the same results when run?

My next questions have to do with what happens to a command group when things don't complete nicely:
  • If CommandA from the example command group above was interrupted, would the entire command group be interrupted? For example, let's assume CommandA was waiting for something to move into position and CommandB performed a firing action. If CommandA was interrupted, would CommandB still run, or would the interruption stop CommandB from ever being run?
  • Secondly, Assume CommandA has used the setTimeout() method or was added to the group with a timeout option to indicate that it has 2 seconds to complete. If the timeout is reached, will the rest of the commands complete in the sequence?

Thanks,
Paul

I can only answer the last question for sure, yes the rest of the commands will complete after the one times out. We are doing this for our hot goal detection so we don't end up waiting the entire auto period if we don't see a hot goal for any reason.

Ginto8 13-02-2014 11:34

Re: CommandGroup questions
 
Given this expectation:
Quote:

Originally Posted by pblankenbaker (Post 1342304)
  • Run CommandA first and wait for it to complete.
  • Then run CommandB and CommandC at the same time.
  • After CommandB and CommandC complete I then want to run CommandD.

This will not work:
Quote:

Originally Posted by pblankenbaker (Post 1342304)
Code:

public static Command buildMyCommand() {
  CommandGroup cmd = new CommandGroup();
  cmd.addSequential(new CommandA());
  // Start of first command to run in parallel
  cmd.addParallel(new CommandB());
  // End of commands to run in parallel (runs in parallel with CommandB)
  cmd.addSequential(new CommandC());
  cmd.addSequential(new CommandD());

  return cmd;
}


A command added in parallel to a command group has no effect on when the commands after it run. CommandD will run when CommandC finishes, with no regard for whether or not CommandB is running. To fix this, add this line before CommandD:
Code:

cmd.addSequential(new WaitForChildren());
This will wait until all parallel commands have completed before moving on.

Quote:

Originally Posted by pblankenbaker (Post 1342304)
My next questions have to do with what happens to a command group when things don't complete nicely:
  • If CommandA from the example command group above was interrupted, would the entire command group be interrupted? For example, let's assume CommandA was waiting for something to move into position and CommandB performed a firing action. If CommandA was interrupted, would CommandB still run, or would the interruption stop CommandB from ever being run?

If you directly cancelled CommandA, the CommandGroup would continue to the next Command in line, per lines 217-230 in CommandGroup.java:
Code:

            if (cmd != null) {
                if (entry.isTimedOut()) {
                    cmd._cancel();
                }
                if (cmd.run()) {
                    break;
                } else {
                    cmd.removed();
                    m_currentCommandIndex++;
                    firstRun = true;
                    cmd = null;
                    continue;
                }
            }

However, if the interruption is due to another command that requires() the same subsystem, the whole CommandGroup will be cancelled. A CommandGroup absorbs the requirements of all Commands within it.

Quote:

Originally Posted by pblankenbaker (Post 1342304)
  • Secondly, Assume CommandA has used the setTimeout() method or was added to the group with a timeout option to indicate that it has 2 seconds to complete. If the timeout is reached, will the rest of the commands complete in the sequence?

If the timeout is reached, the command will not even terminate, unless you have an isFinished() method like this (from WaitCommand.java):
Code:

    protected boolean isFinished() {
        return isTimedOut();
    }

However, there is a way to add a timeout within a CommandGroup. addSequential and addParallel are both overloaded so that you can specify a timeout after which the Command will be cancelled and the next Command in the group will begin, like so:
Code:

addSequential(new CommandA(),2.0); // times out after 2 seconds

pblankenbaker 13-02-2014 13:50

Re: CommandGroup questions
 
Thanks for the explanations. If I understand things correctly, when the goal is to build a command group that has the following pattern:
  • Runs CommandA first and wait for it to complete.
  • Then runs CommandB and CommandC at the same time.
  • After CommandB and CommandC complete CommandD is run.

There are at least two ways to code this:

Option A: Don't mix addParallel() and addSequential() (use nested CommandGroup objects instead):

Code:

public static Command buildMyCommand() {
  CommandGroup bc = new CommandGroup();
  bc.addParallel(new CommandB());
  bc.addParallel(new CommandC());

  CommandGroup cmd = new CommandGroup();
  cmd.addSequential(new CommandA());
  cmd.addSequential(bc);
  cmd.addSequential(new CommandD());

  return cmd;
}

Option B: Mix addParallel() and addSequential(), but only if you fully understand how CommandGroups work:

Code:

public static Command buildMyCommand() {
  CommandGroup cmd = new CommandGroup();

  // CommandA is the first command to run
  cmd.addSequential(new CommandA());

  // Start a command in parallel after CommandA finishes
  cmd.addParallel(new CommandB());

  // Start a sequential command (also starts after CommandA finishes
  // runs at the same time as CommandB)
  cmd.addSequential(new CommandC());

  // Wait for CommandB and CommandC to finish
  cmd.addSequential(new WaitForChildren());

  // Now it is OK to run CommandD (both CommandB and CommandC are done)
  cmd.addSequential(new CommandD());

  return cmd;
}


Option C: Mix addParallel() and addSequential(), similar to Option B, but uses addParallel() for CommandB and CommandC (which might be slightly more intuitive to look at):

Code:

public static Command buildMyCommand() {
  CommandGroup cmd = new CommandGroup();

  // CommandA is the first command to run
  cmd.addSequential(new CommandA());

  // Start a command in parallel after CommandA finishes
  cmd.addParallel(new CommandB());

  // Start a parallel command (also starts after CommandA finishes
  // runs at the same time as CommandB)
  cmd.addParallel(new CommandC());

  // Wait for CommandB and CommandC to finish
  cmd.addSequential(new WaitForChildren());

  // Now it is OK to run CommandD (both CommandB and CommandC are done)
  cmd.addSequential(new CommandD());

  return cmd;
}

Please let me know if the three above fragments won't yield the same results as I'm going to try to explain this to our programming leads today (I suspect we will be reviewing and refactoring a lot of command groups).

I think I prefer the nested command groups (Option A) for readability (human comprehension). Unless someone tells me this won't work, I will encourage this general rule of thumb when we introduce CommandGroups to new programmers joining the team (at least to get them started).

We will also need to review our command groups and think about the different behaviors between timeouts and interrupted situations. I suspect we have some commands that need to be coded a little more defensively so we don't break things on the robot for certain time outs (if CommandA times out, we may not want to run CommandB in the sequence).

Thanks again for the information,
Paul

notmattlythgoe 13-02-2014 13:55

Re: CommandGroup questions
 
Quote:

Originally Posted by pblankenbaker (Post 1342533)
Thanks for the explanations. If I understand things correctly, when the goal is to build a command group that has the following pattern:
  • Runs CommandA first and wait for it to complete.
  • Then runs CommandB and CommandC at the same time.
  • After CommandB and CommandC complete CommandD is run.

There are at least two ways to code this:

Option A: Don't mix addParallel() and addSequential() (use nested CommandGroup objects instead):

Code:

public static Command buildMyCommand() {
  CommandGroup bc = new CommandGroup();
  bc.addParallel(new CommandB());
  bc.addParallel(new CommandC());

  CommandGroup cmd = new CommandGroup();
  cmd.addSequential(new CommandA());
  cmd.addSequential(bc);
  cmd.addSequential(new CommandD());

  return cmd;
}

Option B: Mix addParallel() and addSequential(), but only if you fully understand how CommandGroups work:

Code:

public static Command buildMyCommand() {
  CommandGroup cmd = new CommandGroup();

  // CommandA is the first command to run
  cmd.addSequential(new CommandA());

  // Start a command in parallel after CommandA finishes
  cmd.addParallel(new CommandB());

  // Start a sequential command (also starts after CommandA finishes
  // runs at the same time as CommandB)
  cmd.addSequential(new CommandC());

  // Wait for CommandB and CommandC to finish
  cmd.addSequential(new WaitForChildren());

  // Now it is OK to run CommandD (both CommandB and CommandC are done)
  cmd.addSequential(new CommandD());

  return cmd;
}


Option C: Mix addParallel() and addSequential(), similar to Option B, but uses addParallel() for CommandB and CommandC (which might be slightly more intuitive to look at):

Code:

public static Command buildMyCommand() {
  CommandGroup cmd = new CommandGroup();

  // CommandA is the first command to run
  cmd.addSequential(new CommandA());

  // Start a command in parallel after CommandA finishes
  cmd.addParallel(new CommandB());

  // Start a parallel command (also starts after CommandA finishes
  // runs at the same time as CommandB)
  cmd.addParallel(new CommandC());

  // Wait for CommandB and CommandC to finish
  cmd.addSequential(new WaitForChildren());

  // Now it is OK to run CommandD (both CommandB and CommandC are done)
  cmd.addSequential(new CommandD());

  return cmd;
}

Please let me know if the two above fragments won't yield the same results as I'm going to try to explain this to our programming leads today (I suspect we will be reviewing and refactoring a lot of command groups).

I think I prefer the nested command groups (Option A) for readability (human comprehension). Unless someone tells me this won't work, I will encourage this general rule of thumb when we introduce CommandGroups to new programmers joining the team (at least to get them started).

We will also need to review our command groups and think about the different behaviors between timeouts and interrupted situations. I suspect we have some commands that need to be coded a little more defensively so we don't break things on the robot for certain time outs (if CommandA times out, we may not want to run CommandB in the sequence).

Thanks again for the information,
Paul

I agree, I like option A the best and it will be the most readable and should be the easiest to understand.


All times are GMT -5. The time now is 22:37.

Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Copyright © Chief Delphi