From 59b072c54ad1f349af6c4d8f6684a7232e56b663 Mon Sep 17 00:00:00 2001
From: MEFThunders7035 <95276965+kytpbs@users.noreply.github.com>
Date: Mon, 6 May 2024 03:50:46 +0300
Subject: [PATCH 1/8] add Command.repeatedly(int times) to both java and c++
Also has unit tests in it!
---
.../wpi/first/wpilibj2/command/Command.java | 22 ++++++++++
.../main/native/cpp/frc2/command/Command.cpp | 4 ++
.../native/cpp/frc2/command/CommandPtr.cpp | 11 +++++
.../native/include/frc2/command/Command.h | 10 +++++
.../native/include/frc2/command/CommandPtr.h | 10 +++++
.../command/CommandDecoratorTest.java | 40 +++++++++++++++++++
.../cpp/frc2/command/CommandDecoratorTest.cpp | 33 +++++++++++++++
7 files changed, 130 insertions(+)
diff --git a/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/Command.java b/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/Command.java
index d6cd4c8860d..9a32bb3335d 100644
--- a/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/Command.java
+++ b/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/Command.java
@@ -401,6 +401,28 @@ public RepeatCommand repeatedly() {
return new RepeatCommand(this);
}
+ /**
+ * Decorates this command to run repeatedly, restarting until the command runs for the given times
+ * amount. The decorated command can still be canceled.
+ *
+ *
This is just syntactic sugar for {@code this.finallyDo(() ->
+ * counter[0]++).repeatedly().until(() -> counter[0] >= times)} which just means: runs the
+ * command, then increments the counter, repeatedly until the counter saturates.
+ *
+ *
Note: This decorator works by adding this command to a composition. The command the
+ * decorator was called on cannot be scheduled independently or be added to a different
+ * composition (namely, decorators), unless it is manually cleared from the list of composed
+ * commands with {@link CommandScheduler#removeComposedCommand(Command)}. The command composition
+ * returned from this method can be further decorated without issue.
+ *
+ * @param times the count of times to run the command (inclusively).
+ * @return the decorated command
+ */
+ public ParallelRaceGroup repeatedly(int times) {
+ int[] counter = {0};
+ return this.finallyDo(() -> counter[0]++).repeatedly().until(() -> counter[0] >= times);
+ }
+
/**
* Decorates this command to run "by proxy" by wrapping it in a {@link ProxyCommand}. Use this for
* "forking off" from command compositions when the user does not wish to extend the command's
diff --git a/wpilibNewCommands/src/main/native/cpp/frc2/command/Command.cpp b/wpilibNewCommands/src/main/native/cpp/frc2/command/Command.cpp
index af8e30a33a5..bc37be14801 100644
--- a/wpilibNewCommands/src/main/native/cpp/frc2/command/Command.cpp
+++ b/wpilibNewCommands/src/main/native/cpp/frc2/command/Command.cpp
@@ -109,6 +109,10 @@ CommandPtr Command::Repeatedly() && {
return std::move(*this).ToPtr().Repeatedly();
}
+CommandPtr Command::Repeatedly(int times) && {
+ return std::move(*this).ToPtr().Repeatedly(times);
+}
+
CommandPtr Command::AsProxy() && {
return std::move(*this).ToPtr().AsProxy();
}
diff --git a/wpilibNewCommands/src/main/native/cpp/frc2/command/CommandPtr.cpp b/wpilibNewCommands/src/main/native/cpp/frc2/command/CommandPtr.cpp
index d4125fdceb8..f017808ac67 100644
--- a/wpilibNewCommands/src/main/native/cpp/frc2/command/CommandPtr.cpp
+++ b/wpilibNewCommands/src/main/native/cpp/frc2/command/CommandPtr.cpp
@@ -50,6 +50,17 @@ CommandPtr CommandPtr::Repeatedly() && {
return std::move(*this);
}
+CommandPtr CommandPtr::Repeatedly(int times) && {
+ AssertValid();
+ std::shared_ptr countPtr = std::make_shared(0);
+ return std::move(*this)
+ .FinallyDo([countPtr = countPtr] { (*countPtr)++; })
+ .Repeatedly()
+ .Until([countPtr = countPtr, times = times] {
+ return ((*countPtr) >= times);
+ });
+}
+
CommandPtr CommandPtr::AsProxy() && {
AssertValid();
m_ptr = std::make_unique(std::move(m_ptr));
diff --git a/wpilibNewCommands/src/main/native/include/frc2/command/Command.h b/wpilibNewCommands/src/main/native/include/frc2/command/Command.h
index 4dea3eb1a5f..dd40b9e24cb 100644
--- a/wpilibNewCommands/src/main/native/include/frc2/command/Command.h
+++ b/wpilibNewCommands/src/main/native/include/frc2/command/Command.h
@@ -269,6 +269,16 @@ class Command : public wpi::Sendable, public wpi::SendableHelper {
[[nodiscard]]
CommandPtr Repeatedly() &&;
+ /**
+ * Decorates this command to run repeatedly until the given count is reached
+ * or is interrupted. The decorated command can still be canceled.
+ *
+ * @param times the number/count of times to run the command
+ * @return the decorated command
+ */
+ [[nodiscard]]
+ CommandPtr Repeatedly(int times) &&;
+
/**
* Decorates this command to run "by proxy" by wrapping it in a ProxyCommand.
* Use this for "forking off" from command compositions when the user does not
diff --git a/wpilibNewCommands/src/main/native/include/frc2/command/CommandPtr.h b/wpilibNewCommands/src/main/native/include/frc2/command/CommandPtr.h
index 81a255a9a73..7bc15c603d0 100644
--- a/wpilibNewCommands/src/main/native/include/frc2/command/CommandPtr.h
+++ b/wpilibNewCommands/src/main/native/include/frc2/command/CommandPtr.h
@@ -49,6 +49,16 @@ class CommandPtr final {
[[nodiscard]]
CommandPtr Repeatedly() &&;
+ /**
+ * Decorates this command to run repeatedly until the given count is reached
+ * or is interrupted. The decorated command can still be canceled.
+ *
+ * @param times the number of times to run the command
+ * @return the decorated command
+ */
+ [[nodiscard]]
+ CommandPtr Repeatedly(int times) &&;
+
/**
* Decorates this command to run "by proxy" by wrapping it in a ProxyCommand.
* Use this for "forking off" from command compositions when the user does not
diff --git a/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/CommandDecoratorTest.java b/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/CommandDecoratorTest.java
index 4d9ad2c06f9..5c1b5074dbd 100644
--- a/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/CommandDecoratorTest.java
+++ b/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/CommandDecoratorTest.java
@@ -420,6 +420,46 @@ void raceWithOrderTest() {
}
}
+ @Test
+ void repeatedlyTest() {
+ try (CommandScheduler scheduler = new CommandScheduler()) {
+ AtomicInteger counter = new AtomicInteger(0);
+
+ Command command = new InstantCommand(counter::incrementAndGet);
+
+ Command group = command.repeatedly();
+
+ scheduler.schedule(group);
+ for (int i = 1; i <= 50; i++) {
+ scheduler.run();
+ assertEquals(i, counter.get());
+ }
+
+ // Should still be scheduled
+ assertTrue(scheduler.isScheduled(group));
+ }
+ }
+
+ @Test
+ void repeatForTest() {
+ try (CommandScheduler scheduler = new CommandScheduler()) {
+ AtomicInteger counter = new AtomicInteger(0);
+
+ Command command = new InstantCommand(counter::incrementAndGet);
+
+ Command group = command.repeatedly(3);
+
+ scheduler.schedule(group);
+ for (int i = 0;
+ scheduler.isScheduled(group);
+ i++) { // If this causes an infinite loop, repeatedly is cooked
+ scheduler.run();
+ assertEquals(i + 1, counter.get());
+ }
+ assertEquals(3, counter.get());
+ }
+ }
+
@Test
void unlessTest() {
try (CommandScheduler scheduler = new CommandScheduler()) {
diff --git a/wpilibNewCommands/src/test/native/cpp/frc2/command/CommandDecoratorTest.cpp b/wpilibNewCommands/src/test/native/cpp/frc2/command/CommandDecoratorTest.cpp
index a0b7726f5d6..edfa7cf9706 100644
--- a/wpilibNewCommands/src/test/native/cpp/frc2/command/CommandDecoratorTest.cpp
+++ b/wpilibNewCommands/src/test/native/cpp/frc2/command/CommandDecoratorTest.cpp
@@ -383,6 +383,39 @@ TEST_F(CommandDecoratorTest, RaceWithOrder) {
EXPECT_TRUE(firstWasPolled);
}
+TEST_F(CommandDecoratorTest, Repeatedly) {
+ CommandScheduler scheduler = GetScheduler();
+
+ int counter = 0;
+
+ auto command = InstantCommand([&counter] { counter++; }, {}).Repeatedly();
+
+ scheduler.Schedule(command);
+
+ for (int i = 1; i <= 50; i++) {
+ scheduler.Run();
+ EXPECT_EQ(i, counter);
+ }
+
+ EXPECT_TRUE(scheduler.IsScheduled(command));
+}
+
+TEST_F(CommandDecoratorTest, RepeatFor) {
+ CommandScheduler scheduler = GetScheduler();
+
+ int counter = 0;
+
+ auto command = InstantCommand([&counter] { counter++; }, {}).Repeatedly(3);
+
+ scheduler.Schedule(command);
+ for (int i = 0; scheduler.IsScheduled(command); i++) {
+ scheduler.Run();
+ EXPECT_EQ(i + 1, counter);
+ }
+
+ EXPECT_EQ(3, counter);
+}
+
TEST_F(CommandDecoratorTest, Unless) {
CommandScheduler scheduler = GetScheduler();
From da6c11b246917ad137fb91aa4e6ddb0bc748cb9f Mon Sep 17 00:00:00 2001
From: Kaya <95276965+kytpbs@users.noreply.github.com>
Date: Mon, 27 May 2024 02:58:16 +0300
Subject: [PATCH 2/8] use Atomic Integer instead of array for refrence-passing.
---
.../main/java/edu/wpi/first/wpilibj2/command/Command.java | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/Command.java b/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/Command.java
index 9a32bb3335d..fada98a1618 100644
--- a/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/Command.java
+++ b/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/Command.java
@@ -15,6 +15,7 @@
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.BooleanSupplier;
/**
@@ -419,8 +420,10 @@ public RepeatCommand repeatedly() {
* @return the decorated command
*/
public ParallelRaceGroup repeatedly(int times) {
- int[] counter = {0};
- return this.finallyDo(() -> counter[0]++).repeatedly().until(() -> counter[0] >= times);
+ AtomicInteger counter = new AtomicInteger(0);
+ return this.finallyDo(counter::getAndIncrement)
+ .repeatedly()
+ .until(() -> counter.get() >= times);
}
/**
From eb91b2134586ae5be8aa01aba9f4cb242dfce8d4 Mon Sep 17 00:00:00 2001
From: Kaya <95276965+kytpbs@users.noreply.github.com>
Date: Fri, 11 Oct 2024 00:49:47 +0300
Subject: [PATCH 3/8] improve tests so they don't hang when failing
also, give better errors
Co-Authored-By: Joseph Eng <91924258+KangarooKoala@users.noreply.github.com>
---
.../first/wpilibj2/command/CommandDecoratorTest.java | 12 +++++++-----
.../native/cpp/frc2/command/CommandDecoratorTest.cpp | 8 ++++++--
2 files changed, 13 insertions(+), 7 deletions(-)
diff --git a/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/CommandDecoratorTest.java b/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/CommandDecoratorTest.java
index 5c1b5074dbd..7c5f7abf71f 100644
--- a/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/CommandDecoratorTest.java
+++ b/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/CommandDecoratorTest.java
@@ -450,13 +450,15 @@ void repeatForTest() {
Command group = command.repeatedly(3);
scheduler.schedule(group);
- for (int i = 0;
- scheduler.isScheduled(group);
- i++) { // If this causes an infinite loop, repeatedly is cooked
+ assertEquals(1, counter.get());
+ for (int i = 1; i < 3; i++) {
scheduler.run();
- assertEquals(i + 1, counter.get());
+ assertEquals(i, counter.get());
+ assertTrue(scheduler.isScheduled(group), "Expected group to be scheduled with i = " + i);
}
- assertEquals(3, counter.get());
+ scheduler.run();
+ assertEquals(3, counter.get(), "Loop should have run 3 times something went wrong");
+ assertFalse(scheduler.isScheduled(group), "This command should have gotten unscheduled");
}
}
diff --git a/wpilibNewCommands/src/test/native/cpp/frc2/command/CommandDecoratorTest.cpp b/wpilibNewCommands/src/test/native/cpp/frc2/command/CommandDecoratorTest.cpp
index edfa7cf9706..5355c2e99ac 100644
--- a/wpilibNewCommands/src/test/native/cpp/frc2/command/CommandDecoratorTest.cpp
+++ b/wpilibNewCommands/src/test/native/cpp/frc2/command/CommandDecoratorTest.cpp
@@ -408,12 +408,16 @@ TEST_F(CommandDecoratorTest, RepeatFor) {
auto command = InstantCommand([&counter] { counter++; }, {}).Repeatedly(3);
scheduler.Schedule(command);
- for (int i = 0; scheduler.IsScheduled(command); i++) {
+ EXPECT_TRUE(scheduler.IsScheduled(command));
+ for (int i = 1; i < 3; i++) {
scheduler.Run();
- EXPECT_EQ(i + 1, counter);
+ EXPECT_EQ(i, counter);
+ EXPECT_TRUE(scheduler.IsScheduled(command));
}
+ scheduler.Run();
EXPECT_EQ(3, counter);
+ EXPECT_FALSE(scheduler.IsScheduled(command));
}
TEST_F(CommandDecoratorTest, Unless) {
From faf08c2f95c16e27414079d71c05ee90dbb00654 Mon Sep 17 00:00:00 2001
From: Kaya <95276965+kytpbs@users.noreply.github.com>
Date: Fri, 11 Oct 2024 00:54:04 +0300
Subject: [PATCH 4/8] use pass by value similar to convention
I didn't know you could just pass by value by doing this thx @KangarooKoala for pointing it out.
Co-Authored-By: Joseph Eng <91924258+KangarooKoala@users.noreply.github.com>
---
.../src/main/native/cpp/frc2/command/CommandPtr.cpp | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/wpilibNewCommands/src/main/native/cpp/frc2/command/CommandPtr.cpp b/wpilibNewCommands/src/main/native/cpp/frc2/command/CommandPtr.cpp
index f017808ac67..5bc63f7ffb4 100644
--- a/wpilibNewCommands/src/main/native/cpp/frc2/command/CommandPtr.cpp
+++ b/wpilibNewCommands/src/main/native/cpp/frc2/command/CommandPtr.cpp
@@ -54,11 +54,9 @@ CommandPtr CommandPtr::Repeatedly(int times) && {
AssertValid();
std::shared_ptr countPtr = std::make_shared(0);
return std::move(*this)
- .FinallyDo([countPtr = countPtr] { (*countPtr)++; })
+ .FinallyDo([countPtr] { (*countPtr)++; })
.Repeatedly()
- .Until([countPtr = countPtr, times = times] {
- return ((*countPtr) >= times);
- });
+ .Until([countPtr, times] { return ((*countPtr) >= times); });
}
CommandPtr CommandPtr::AsProxy() && {
From 07bb16e4e41a4c9ea51fafaed2c42e5f6ce0c903 Mon Sep 17 00:00:00 2001
From: Kaya <95276965+kytpbs@users.noreply.github.com>
Date: Thu, 14 Nov 2024 02:04:20 +0300
Subject: [PATCH 5/8] improve test names
---
.../edu/wpi/first/wpilibj2/command/CommandDecoratorTest.java | 2 +-
.../src/test/native/cpp/frc2/command/CommandDecoratorTest.cpp | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/CommandDecoratorTest.java b/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/CommandDecoratorTest.java
index 7c5f7abf71f..31cdca04367 100644
--- a/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/CommandDecoratorTest.java
+++ b/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/CommandDecoratorTest.java
@@ -441,7 +441,7 @@ void repeatedlyTest() {
}
@Test
- void repeatForTest() {
+ void repeatedlyCountTest() {
try (CommandScheduler scheduler = new CommandScheduler()) {
AtomicInteger counter = new AtomicInteger(0);
diff --git a/wpilibNewCommands/src/test/native/cpp/frc2/command/CommandDecoratorTest.cpp b/wpilibNewCommands/src/test/native/cpp/frc2/command/CommandDecoratorTest.cpp
index 5355c2e99ac..a10d129191b 100644
--- a/wpilibNewCommands/src/test/native/cpp/frc2/command/CommandDecoratorTest.cpp
+++ b/wpilibNewCommands/src/test/native/cpp/frc2/command/CommandDecoratorTest.cpp
@@ -400,7 +400,7 @@ TEST_F(CommandDecoratorTest, Repeatedly) {
EXPECT_TRUE(scheduler.IsScheduled(command));
}
-TEST_F(CommandDecoratorTest, RepeatFor) {
+TEST_F(CommandDecoratorTest, RepeatedlyCount) {
CommandScheduler scheduler = GetScheduler();
int counter = 0;
From 9fec4bc1f9f72c74f1309edef64cacf511896d4a Mon Sep 17 00:00:00 2001
From: Kaya <95276965+kytpbs@users.noreply.github.com>
Date: Mon, 16 Dec 2024 15:35:40 +0100
Subject: [PATCH 6/8] Better comments and variable names
---
.../wpi/first/wpilibj2/command/Command.java | 22 ++++++++-----------
.../native/include/frc2/command/CommandPtr.h | 4 ++--
2 files changed, 11 insertions(+), 15 deletions(-)
diff --git a/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/Command.java b/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/Command.java
index fada98a1618..b9aa08f94b6 100644
--- a/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/Command.java
+++ b/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/Command.java
@@ -15,7 +15,6 @@
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
-import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.BooleanSupplier;
/**
@@ -403,12 +402,8 @@ public RepeatCommand repeatedly() {
}
/**
- * Decorates this command to run repeatedly, restarting until the command runs for the given times
- * amount. The decorated command can still be canceled.
- *
- * This is just syntactic sugar for {@code this.finallyDo(() ->
- * counter[0]++).repeatedly().until(() -> counter[0] >= times)} which just means: runs the
- * command, then increments the counter, repeatedly until the counter saturates.
+ * Decorates this command to run repeatedly, restarting until the command runs for the given
+ * number of times. The decorated command can still be canceled.
*
*
Note: This decorator works by adding this command to a composition. The command the
* decorator was called on cannot be scheduled independently or be added to a different
@@ -416,14 +411,15 @@ public RepeatCommand repeatedly() {
* commands with {@link CommandScheduler#removeComposedCommand(Command)}. The command composition
* returned from this method can be further decorated without issue.
*
- * @param times the count of times to run the command (inclusively).
+ * @param repetitions the count of times to run the command.
* @return the decorated command
*/
- public ParallelRaceGroup repeatedly(int times) {
- AtomicInteger counter = new AtomicInteger(0);
- return this.finallyDo(counter::getAndIncrement)
- .repeatedly()
- .until(() -> counter.get() >= times);
+ public ParallelRaceGroup repeatedly(int repetitions) {
+ // use an array so that it stays in the heap instead of stack.
+ // We use an array with a size of 1 instead of `AtomicInteger` because of the performance
+ // overhead
+ int[] counter = new int[1];
+ return this.finallyDo(() -> counter[0]++).repeatedly().until(() -> counter[0] >= repetitions);
}
/**
diff --git a/wpilibNewCommands/src/main/native/include/frc2/command/CommandPtr.h b/wpilibNewCommands/src/main/native/include/frc2/command/CommandPtr.h
index 7bc15c603d0..74d4f457af3 100644
--- a/wpilibNewCommands/src/main/native/include/frc2/command/CommandPtr.h
+++ b/wpilibNewCommands/src/main/native/include/frc2/command/CommandPtr.h
@@ -50,8 +50,8 @@ class CommandPtr final {
CommandPtr Repeatedly() &&;
/**
- * Decorates this command to run repeatedly until the given count is reached
- * or is interrupted. The decorated command can still be canceled.
+ * Decorates this command to run repeatedly, restarting until the command runs for the given
+ * number of times. The decorated command can still be canceled.
*
* @param times the number of times to run the command
* @return the decorated command
From f31b58cf22ff9c607970eabf6f80f1a3dd73bd3e Mon Sep 17 00:00:00 2001
From: Kaya <95276965+kytpbs@users.noreply.github.com>
Date: Mon, 16 Dec 2024 18:47:09 +0100
Subject: [PATCH 7/8] More explicitly set initial counter value
Co-authored-by: Joseph Eng <91924258+KangarooKoala@users.noreply.github.com>
---
.../src/main/java/edu/wpi/first/wpilibj2/command/Command.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/Command.java b/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/Command.java
index b9aa08f94b6..96563332826 100644
--- a/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/Command.java
+++ b/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/Command.java
@@ -418,7 +418,7 @@ public ParallelRaceGroup repeatedly(int repetitions) {
// use an array so that it stays in the heap instead of stack.
// We use an array with a size of 1 instead of `AtomicInteger` because of the performance
// overhead
- int[] counter = new int[1];
+ int[] counter = {0};
return this.finallyDo(() -> counter[0]++).repeatedly().until(() -> counter[0] >= repetitions);
}
From d968cb35b755b5c6deaad1b89be31ba667baf7d4 Mon Sep 17 00:00:00 2001
From: Kaya <95276965+kytpbs@users.noreply.github.com>
Date: Sun, 22 Dec 2024 21:17:18 +0300
Subject: [PATCH 8/8] Improve comments & Add failure messages to C++
---
.../main/java/edu/wpi/first/wpilibj2/command/Command.java | 5 ++---
.../src/main/native/include/frc2/command/CommandPtr.h | 4 ++--
.../test/native/cpp/frc2/command/CommandDecoratorTest.cpp | 8 +++++---
3 files changed, 9 insertions(+), 8 deletions(-)
diff --git a/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/Command.java b/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/Command.java
index 96563332826..b940bca641d 100644
--- a/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/Command.java
+++ b/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/Command.java
@@ -415,9 +415,8 @@ public RepeatCommand repeatedly() {
* @return the decorated command
*/
public ParallelRaceGroup repeatedly(int repetitions) {
- // use an array so that it stays in the heap instead of stack.
- // We use an array with a size of 1 instead of `AtomicInteger` because of the performance
- // overhead
+ // Use an array so that it stays in the heap instead of stack.
+ // We use an array with a size of 1 instead of `AtomicInteger` because of performance difference
int[] counter = {0};
return this.finallyDo(() -> counter[0]++).repeatedly().until(() -> counter[0] >= repetitions);
}
diff --git a/wpilibNewCommands/src/main/native/include/frc2/command/CommandPtr.h b/wpilibNewCommands/src/main/native/include/frc2/command/CommandPtr.h
index 74d4f457af3..ae770e15a6e 100644
--- a/wpilibNewCommands/src/main/native/include/frc2/command/CommandPtr.h
+++ b/wpilibNewCommands/src/main/native/include/frc2/command/CommandPtr.h
@@ -50,8 +50,8 @@ class CommandPtr final {
CommandPtr Repeatedly() &&;
/**
- * Decorates this command to run repeatedly, restarting until the command runs for the given
- * number of times. The decorated command can still be canceled.
+ * Decorates this command to run repeatedly, restarting until the command runs
+ * for the given number of times. The decorated command can still be canceled.
*
* @param times the number of times to run the command
* @return the decorated command
diff --git a/wpilibNewCommands/src/test/native/cpp/frc2/command/CommandDecoratorTest.cpp b/wpilibNewCommands/src/test/native/cpp/frc2/command/CommandDecoratorTest.cpp
index a10d129191b..0facb2860a2 100644
--- a/wpilibNewCommands/src/test/native/cpp/frc2/command/CommandDecoratorTest.cpp
+++ b/wpilibNewCommands/src/test/native/cpp/frc2/command/CommandDecoratorTest.cpp
@@ -412,12 +412,14 @@ TEST_F(CommandDecoratorTest, RepeatedlyCount) {
for (int i = 1; i < 3; i++) {
scheduler.Run();
EXPECT_EQ(i, counter);
- EXPECT_TRUE(scheduler.IsScheduled(command));
+ EXPECT_TRUE(scheduler.IsScheduled(command))
+ << "Expected group to be scheduled with i = " << i;
}
scheduler.Run();
- EXPECT_EQ(3, counter);
- EXPECT_FALSE(scheduler.IsScheduled(command));
+ EXPECT_EQ(3, counter) << "Loop should have run 3 times something went wrong";
+ EXPECT_FALSE(scheduler.IsScheduled(command))
+ << "This command should have gotten unscheduled";
}
TEST_F(CommandDecoratorTest, Unless) {