001// Copyright (c) FIRST and other WPILib contributors. 002// Open Source Software; you can modify and/or share it under the terms of 003// the WPILib BSD license file in the root directory of this project. 004 005package org.wpilib.commands3; 006 007import static edu.wpi.first.util.ErrorMessages.requireNonNullParam; 008 009import java.util.ArrayList; 010import java.util.HashSet; 011import java.util.List; 012import java.util.Set; 013 014/** 015 * A sequence of commands that run one after another. Each successive command only starts after its 016 * predecessor completes execution. The priority of a sequence is equal to the highest priority of 017 * any of its commands. If all commands in the sequence are able to run while the robot is disabled, 018 * then the sequence itself will be allowed to run while the robot is disabled. 019 * 020 * <p>The sequence will <i>own</i> all mechanisms required by all commands in the sequence for the 021 * entire duration of the sequence. This means that a mechanism owned by one command in the 022 * sequence, but not by a later one, will be <i>uncommanded</i> while that later command executes. 023 */ 024public final class SequentialGroup implements Command { 025 private final String m_name; 026 private final List<Command> m_commands = new ArrayList<>(); 027 private final Set<Mechanism> m_requirements = new HashSet<>(); 028 private final int m_priority; 029 030 /** 031 * Creates a new command sequence. 032 * 033 * @param name the name of the sequence 034 * @param commands the commands to execute within the sequence 035 */ 036 SequentialGroup(String name, List<Command> commands) { 037 requireNonNullParam(name, "name", "SequentialGroup"); 038 requireNonNullParam(commands, "commands", "SequentialGroup"); 039 for (int i = 0; i < commands.size(); i++) { 040 requireNonNullParam(commands.get(i), "commands[" + i + "]", "SequentialGroup"); 041 } 042 043 m_name = name; 044 m_commands.addAll(commands); 045 046 for (var command : commands) { 047 m_requirements.addAll(command.requirements()); 048 } 049 050 m_priority = 051 commands.stream().mapToInt(Command::priority).max().orElse(Command.DEFAULT_PRIORITY); 052 } 053 054 @Override 055 public void run(Coroutine coroutine) { 056 for (var command : m_commands) { 057 coroutine.await(command); 058 } 059 } 060 061 @Override 062 public String name() { 063 return m_name; 064 } 065 066 @Override 067 public Set<Mechanism> requirements() { 068 return m_requirements; 069 } 070 071 @Override 072 public int priority() { 073 return m_priority; 074 } 075 076 @Override 077 public String toString() { 078 return "SequentialGroup[name=" + m_name + "]"; 079 } 080}