Skip to content

Commit

Permalink
Reduced boilerplate
Browse files Browse the repository at this point in the history
  • Loading branch information
Daniel1464 committed Nov 7, 2024
1 parent 09cce4b commit 178ab5b
Show file tree
Hide file tree
Showing 9 changed files with 88 additions and 162 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
import static edu.wpi.first.util.ErrorMessages.requireNonNullParam;

import edu.wpi.first.units.measure.Time;

import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.function.BooleanSupplier;
Expand Down Expand Up @@ -272,6 +274,38 @@ public static Command deadline(Command deadline, Command... otherCommands) {
return new ParallelDeadlineGroup(deadline, otherCommands);
}

/**
* Throws an error if a parallel group already shares
* one or more requirements with a command
* that will be added to it.
*
* @param parallelGroup The parallel group command.
* @param toAdd The command that will be added to the parallel group.
*/
public static void ensureDisjointRequirements(Command parallelGroup, Command toAdd) {
var sharedRequirements = new HashSet<>(parallelGroup.getRequirements());
sharedRequirements.retainAll(toAdd.getRequirements());
if (!sharedRequirements.isEmpty()) {
StringBuilder sharedRequirementsStr = new StringBuilder();
boolean first = true;
for (Subsystem requirement: sharedRequirements) {
if (first) {
first = false;
} else {
sharedRequirementsStr.append(", ");
}
sharedRequirementsStr.append(requirement.getName());
}
throw new IllegalArgumentException(
String.format(
"Command %s could not be added to this parallel group"
+ " because the subsystems [%s] are already required in this command."
+ " Multiple commands in a parallel composition cannot require"
+ " the same subsystems.",
toAdd.getName(), sharedRequirementsStr));
}
}

private Commands() {
throw new UnsupportedOperationException("This is a utility class");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

package edu.wpi.first.wpilibj2.command;

import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;

Expand Down Expand Up @@ -51,27 +50,7 @@ public final void addCommands(Command... commands) {
CommandScheduler.getInstance().registerComposedCommands(commands);

for (Command command : commands) {
var sharedRequirements = new HashSet<>(this.getRequirements());
sharedRequirements.retainAll(command.getRequirements());
if (!sharedRequirements.isEmpty()) {
StringBuilder sharedRequirementsStr = new StringBuilder();
boolean first = true;
for (Subsystem requirement: sharedRequirements) {
if (first) {
first = false;
} else {
sharedRequirementsStr.append(", ");
}
sharedRequirementsStr.append(requirement.getName());
}
throw new IllegalArgumentException(
String.format(
"Command %s could not be added to this ParallelCommandGroup"
+ " because the subsystems [%s] are already required in this command."
+ " Multiple commands in a parallel composition cannot require"
+ " the same subsystems.",
command.getName(), sharedRequirementsStr));
}
Commands.ensureDisjointRequirements(this, command);
m_commands.put(command, false);
addRequirements(command.getRequirements());
m_runWhenDisabled &= command.runsWhenDisabled();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
package edu.wpi.first.wpilibj2.command;

import edu.wpi.first.util.sendable.SendableBuilder;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;

Expand Down Expand Up @@ -81,27 +80,7 @@ public final void addCommands(Command... commands) {
CommandScheduler.getInstance().registerComposedCommands(commands);

for (Command command : commands) {
var sharedRequirements = new HashSet<>(this.getRequirements());
sharedRequirements.retainAll(command.getRequirements());
if (!sharedRequirements.isEmpty()) {
StringBuilder sharedRequirementsStr = new StringBuilder();
boolean first = true;
for (Subsystem requirement: sharedRequirements) {
if (first) {
first = false;
} else {
sharedRequirementsStr.append(", ");
}
sharedRequirementsStr.append(requirement.getName());
}
throw new IllegalArgumentException(
String.format(
"Command %s could not be added to this ParallelCommandGroup"
+ " because the subsystems [%s] are already required in this command."
+ " Multiple commands in a parallel composition cannot require"
+ " the same subsystems.",
command.getName(), sharedRequirementsStr));
}
Commands.ensureDisjointRequirements(this, command);
m_commands.put(command, false);
addRequirements(command.getRequirements());
m_runWhenDisabled &= command.runsWhenDisabled();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

package edu.wpi.first.wpilibj2.command;

import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;

Expand Down Expand Up @@ -52,27 +51,7 @@ public final void addCommands(Command... commands) {
CommandScheduler.getInstance().registerComposedCommands(commands);

for (Command command : commands) {
var sharedRequirements = new HashSet<>(this.getRequirements());
sharedRequirements.retainAll(command.getRequirements());
if (!sharedRequirements.isEmpty()) {
StringBuilder sharedRequirementsStr = new StringBuilder();
boolean first = true;
for (Subsystem requirement: sharedRequirements) {
if (first) {
first = false;
} else {
sharedRequirementsStr.append(", ");
}
sharedRequirementsStr.append(requirement.getName());
}
throw new IllegalArgumentException(
String.format(
"Command %s could not be added to this ParallelCommandGroup"
+ " because the subsystems [%s] are already required in this command."
+ " Multiple commands in a parallel composition cannot require"
+ " the same subsystems.",
command.getName(), sharedRequirementsStr));
}
Commands.ensureDisjointRequirements(this, command);
m_commands.add(command);
addRequirements(command.getRequirements());
m_runWhenDisabled &= command.runsWhenDisabled();
Expand Down
28 changes: 21 additions & 7 deletions wpilibNewCommands/src/main/native/cpp/frc2/command/Command.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -220,14 +220,28 @@ void Command::InitSendable(wpi::SendableBuilder& builder) {

namespace frc2 {

std::vector<Subsystem*> GetSharedRequirements(Command* first, Command* second) {
std::vector<Subsystem*> shared;
auto&& requirementsOfSecond = second->GetRequirements();
for (auto&& requirement : first->GetRequirements()) {
if (requirementsOfSecond.find(requirement) != requirementsOfSecond.end()) {
shared.push_back(requirement);
void EnsureDisjointRequirements(Command* parallelGroup, Command* toAdd) {
std::string sharedRequirementsStr = "";
bool hasSharedRequirements = false;
auto&& requirementsToAdd = toAdd->GetRequirements();
for (auto&& requirement : parallelGroup->GetRequirements()) {
if (requirementsToAdd.find(requirement) != requirementsToAdd.end()) {
sharedRequirementsStr.append(requirement->GetName());
if (!hasSharedRequirements) {
hasSharedRequirements = true; // ensures formatting like "a, b, c"
} else {
sharedRequirementsStr.append(", ");
}
}
}
return shared;
if (hasSharedRequirements) {
throw FRC_MakeError(

Check failure on line 238 in wpilibNewCommands/src/main/native/cpp/frc2/command/Command.cpp

View workflow job for this annotation

GitHub Actions / Build - Windows

'command': undeclared identifier
frc::err::CommandIllegalUse,
"Command {} could not be added to this parallel group"
" because the subsystems [{}] are already required in this command."
" Multiple commands in a parallel composition cannot require the "
"same subsystems.",
command->GetName(), sharedRequirementsStr);
}
}
} // namespace frc2
Original file line number Diff line number Diff line change
Expand Up @@ -76,34 +76,14 @@ void ParallelCommandGroup::AddCommands(
}

for (auto&& command : commands) {
auto sharedRequirements = GetSharedRequirements(this, command.get());
if (sharedRequirements.empty()) {
command->SetComposed(true);
AddRequirements(command->GetRequirements());
m_runWhenDisabled &= command->RunsWhenDisabled();
if (command->GetInterruptionBehavior() ==
Command::InterruptionBehavior::kCancelSelf) {
m_interruptBehavior = Command::InterruptionBehavior::kCancelSelf;
}
m_commands.emplace_back(std::move(command), false);
} else {
std::string formattedRequirements = "";
bool first = true;
for (auto&& requirement : sharedRequirements) {
if (first) {
first = false;
} else {
formattedRequirements += ", ";
}
formattedRequirements += requirement->GetName();
}
throw FRC_MakeError(
frc::err::CommandIllegalUse,
"Command {} could not be added to this ParallelCommandGroup"
" because the subsystems [{}] are already required in this command."
" Multiple commands in a parallel composition cannot require the "
"same subsystems.",
command->GetName(), formattedRequirements);
EnsureDisjointRequirements(this, command.get());
command->SetComposed(true);
AddRequirements(command->GetRequirements());
m_runWhenDisabled &= command->RunsWhenDisabled();
if (command->GetInterruptionBehavior() ==
Command::InterruptionBehavior::kCancelSelf) {
m_interruptBehavior = Command::InterruptionBehavior::kCancelSelf;
}
m_commands.emplace_back(std::move(command), false);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -76,35 +76,15 @@ void ParallelDeadlineGroup::AddCommands(
}

for (auto&& command : commands) {
auto sharedRequirements = GetSharedRequirements(this, command.get());
if (sharedRequirements.empty()) {
command->SetComposed(true);
AddRequirements(command->GetRequirements());
m_runWhenDisabled &= command->RunsWhenDisabled();
if (command->GetInterruptionBehavior() ==
Command::InterruptionBehavior::kCancelSelf) {
m_interruptBehavior = Command::InterruptionBehavior::kCancelSelf;
}
m_commands.emplace_back(std::move(command), false);
} else {
std::string formattedRequirements = "";
bool first = true;
for (auto&& requirement : sharedRequirements) {
if (first) {
first = false;
} else {
formattedRequirements += ", ";
}
formattedRequirements += requirement->GetName();
}
throw FRC_MakeError(
frc::err::CommandIllegalUse,
"Command {} could not be added to this ParallelCommandGroup"
" because the subsystems [{}] are already required in this command."
" Multiple commands in a parallel composition cannot require the "
"same subsystems.",
command->GetName(), formattedRequirements);
EnsureDisjointRequirements(this, command.get());
command->SetComposed(true);
AddRequirements(command->GetRequirements());
m_runWhenDisabled &= command->RunsWhenDisabled();
if (command->GetInterruptionBehavior() ==
Command::InterruptionBehavior::kCancelSelf) {
m_interruptBehavior = Command::InterruptionBehavior::kCancelSelf;
}
m_commands.emplace_back(std::move(command), false);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,34 +63,14 @@ void ParallelRaceGroup::AddCommands(
}

for (auto&& command : commands) {
auto sharedRequirements = GetSharedRequirements(this, command.get());
if (sharedRequirements.empty()) {
command->SetComposed(true);
AddRequirements(command->GetRequirements());
m_runWhenDisabled &= command->RunsWhenDisabled();
if (command->GetInterruptionBehavior() ==
Command::InterruptionBehavior::kCancelSelf) {
m_interruptBehavior = Command::InterruptionBehavior::kCancelSelf;
}
m_commands.emplace_back(std::move(command));
} else {
std::string formattedRequirements = "";
bool first = true;
for (auto&& requirement : sharedRequirements) {
if (first) {
first = false;
} else {
formattedRequirements += ", ";
}
formattedRequirements += requirement->GetName();
}
throw FRC_MakeError(
frc::err::CommandIllegalUse,
"Command {} could not be added to this ParallelCommandGroup"
" because the subsystems [{}] are already required in this command."
" Multiple commands in a parallel composition cannot require the "
"same subsystems.",
command->GetName(), formattedRequirements);
EnsureDisjointRequirements(this, command.get());
command->SetComposed(true);
AddRequirements(command->GetRequirements());
m_runWhenDisabled &= command->RunsWhenDisabled();
if (command->GetInterruptionBehavior() ==
Command::InterruptionBehavior::kCancelSelf) {
m_interruptBehavior = Command::InterruptionBehavior::kCancelSelf;
}
m_commands.emplace_back(std::move(command));
}
}
11 changes: 6 additions & 5 deletions wpilibNewCommands/src/main/native/include/frc2/command/Command.h
Original file line number Diff line number Diff line change
Expand Up @@ -493,11 +493,12 @@ class Command : public wpi::Sendable, public wpi::SendableHelper<Command> {
};

/**
* Gets the shared requirements between two distinct commands.
* Throws an error if a parallel group already shares
* one or more requirements with a command
* that will be added to it.
*
* @param first The first command to check.
* @param second The second command to check.
* @return A vector of shared subsystem requirements.
* @param parallelGroup The parallel group command.
* @param toAdd The command that will be added to the parallel group.
*/
std::vector<Subsystem*> GetSharedRequirements(Command* first, Command* second);
void EnsureDisjointRequirements(Command* parallelGroup, Command* toAdd);
} // namespace frc2

0 comments on commit 178ab5b

Please sign in to comment.