/*----------------------------------------------------------------------------*/ /* Copyright (c) FIRST 2011-2017. All Rights Reserved. */ /* Open Source Software - may be modified and shared by FRC teams. The code */ /* must be accompanied by the FIRST BSD license file in the root directory of */ /* the project. */ /*----------------------------------------------------------------------------*/ #include "Commands/CommandGroup.h" #include "WPIErrors.h" using namespace frc; /** * Creates a new {@link CommandGroup CommandGroup} with the given name. * @param name the name for this command group */ CommandGroup::CommandGroup(const std::string& name) : Command(name) {} /** * Adds a new {@link Command Command} to the group. The {@link Command Command} * will be started after all the previously added {@link Command Commands}. * *
Note that any requirements the given {@link Command Command} has will be * added to the group. For this reason, a {@link Command Command's} * requirements can not be changed after being added to a group.
* *It is recommended that this method be called in the constructor.
* * @param command The {@link Command Command} to be added */ void CommandGroup::AddSequential(Command* command) { if (command == nullptr) { wpi_setWPIErrorWithContext(NullParameter, "command"); return; } if (!AssertUnlocked("Cannot add new command to command group")) return; command->SetParent(this); m_commands.push_back( CommandGroupEntry(command, CommandGroupEntry::kSequence_InSequence)); // Iterate through command->GetRequirements() and call Requires() on each // required subsystem Command::SubsystemSet requirements = command->GetRequirements(); auto iter = requirements.begin(); for (; iter != requirements.end(); iter++) Requires(*iter); } /** * Adds a new {@link Command Command} to the group with a given timeout. * The {@link Command Command} will be started after all the previously added * commands. * *Once the {@link Command Command} is started, it will be run until it * finishes or the time expires, whichever is sooner. Note that the given * {@link Command Command} will have no knowledge that it is on a timer.
* *Note that any requirements the given {@link Command Command} has will be * added to the group. For this reason, a {@link Command Command's} * requirements can not be changed after being added to a group.
* *It is recommended that this method be called in the constructor.
* * @param command The {@link Command Command} to be added * @param timeout The timeout (in seconds) */ void CommandGroup::AddSequential(Command* command, double timeout) { if (command == nullptr) { wpi_setWPIErrorWithContext(NullParameter, "command"); return; } if (!AssertUnlocked("Cannot add new command to command group")) return; if (timeout < 0.0) { wpi_setWPIErrorWithContext(ParameterOutOfRange, "timeout < 0.0"); return; } command->SetParent(this); m_commands.push_back(CommandGroupEntry( command, CommandGroupEntry::kSequence_InSequence, timeout)); // Iterate through command->GetRequirements() and call Requires() on each // required subsystem Command::SubsystemSet requirements = command->GetRequirements(); auto iter = requirements.begin(); for (; iter != requirements.end(); iter++) Requires(*iter); } /** * Adds a new child {@link Command} to the group. The {@link Command} will be * started after all the previously added {@link Command Commands}. * *Instead of waiting for the child to finish, a {@link CommandGroup} will * have it run at the same time as the subsequent {@link Command Commands}. * The child will run until either it finishes, a new child with conflicting * requirements is started, or the main sequence runs a {@link Command} with * conflicting requirements. In the latter two cases, the child will be * canceled even if it says it can't be interrupted.
* *Note that any requirements the given {@link Command Command} has will be * added to the group. For this reason, a {@link Command Command's} * requirements can not be changed after being added to a group.
* *It is recommended that this method be called in the constructor.
* * @param command The command to be added */ void CommandGroup::AddParallel(Command* command) { if (command == nullptr) { wpi_setWPIErrorWithContext(NullParameter, "command"); return; } if (!AssertUnlocked("Cannot add new command to command group")) return; command->SetParent(this); m_commands.push_back( CommandGroupEntry(command, CommandGroupEntry::kSequence_BranchChild)); // Iterate through command->GetRequirements() and call Requires() on each // required subsystem Command::SubsystemSet requirements = command->GetRequirements(); auto iter = requirements.begin(); for (; iter != requirements.end(); iter++) Requires(*iter); } /** * Adds a new child {@link Command} to the group with the given timeout. The * {@link Command} will be started after all the previously added * {@link Command Commands}. * *Once the {@link Command Command} is started, it will run until it * finishes, is interrupted, or the time expires, whichever is sooner. Note * that the given {@link Command Command} will have no knowledge that it is on * a timer.
* *Instead of waiting for the child to finish, a {@link CommandGroup} will * have it run at the same time as the subsequent {@link Command Commands}. * The child will run until either it finishes, the timeout expires, a new * child with conflicting requirements is started, or the main sequence runs a * {@link Command} with conflicting requirements. In the latter two cases, the * child will be canceled even if it says it can't be interrupted.
* *Note that any requirements the given {@link Command Command} has will be * added to the group. For this reason, a {@link Command Command's} * requirements can not be changed after being added to a group.
* *It is recommended that this method be called in the constructor.
* * @param command The command to be added * @param timeout The timeout (in seconds) */ void CommandGroup::AddParallel(Command* command, double timeout) { if (command == nullptr) { wpi_setWPIErrorWithContext(NullParameter, "command"); return; } if (!AssertUnlocked("Cannot add new command to command group")) return; if (timeout < 0.0) { wpi_setWPIErrorWithContext(ParameterOutOfRange, "timeout < 0.0"); return; } command->SetParent(this); m_commands.push_back(CommandGroupEntry( command, CommandGroupEntry::kSequence_BranchChild, timeout)); // Iterate through command->GetRequirements() and call Requires() on each // required subsystem Command::SubsystemSet requirements = command->GetRequirements(); auto iter = requirements.begin(); for (; iter != requirements.end(); iter++) Requires(*iter); } void CommandGroup::_Initialize() { m_currentCommandIndex = -1; } void CommandGroup::_Execute() { CommandGroupEntry entry; Command* cmd = nullptr; bool firstRun = false; if (m_currentCommandIndex == -1) { firstRun = true; m_currentCommandIndex = 0; } while (static_cast