Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[cmd] Add Commands.choose (aka SendableChooserCommand) #6355

Open
wants to merge 8 commits into
base: main
Choose a base branch
from

Conversation

Starlight220
Copy link
Member

No description provided.

@Alextopher
Copy link
Contributor

Alextopher commented Feb 27, 2024

I implemented something similar recently.

The Consumer<Sendable> rubs me the wrong way (so does hard coding SmartDashboard like I did). It's a good way to add this change within the existing APIs. I'm just not a fan of how this singular idea SendableChooserCommand requires putting 2 things onto a Dashboard for complete functionality.

Command chooser = Commands.choose(
   chooser -> SmartDashboard.putData("Drive Command Chooser", chooser),
   tankDrive, arcadeDrive, curvatureDrive
);
SmartDashboard.putData("Drive Command", chooser);

I wonder if this change could increase in scope and if SendableChooserCommand could be a new, unique, widget (setSmartDashboardType()), on the same footing as "Command" or "String Chooser".

var chooser = new SendableChooserCommand(tankDrive, arcadeDrive, curvatureDrive);
// Does nothing unless sent to a Dashboard
SmartDashboard.putData("Drive Command", chooser);

@Starlight220
Copy link
Member Author

Why do you need to publish the command to the dashboard?

@Starlight220
Copy link
Member Author

Starlight220 commented Feb 28, 2024

Sure. That's separate functionality, and isn't needed for SendableChooserCommand.

The primary use case for SendableChooser is selecting a command for auto, and the SendableChooser needs to be published for selections to be possible; there's no need (and practically no benefit) to put the command on the dashboard as well.

@Starlight220 Starlight220 force-pushed the sendablechoosercommand branch from c85ea89 to 11e62a9 Compare April 1, 2024 19:34
@KangarooKoala
Copy link
Contributor

#7340 might be resolved by this, though the discussion of the impl in that issue is different from the impl in this PR. (Hence why I'm avoiding the auto-linking words for now)

@Starlight220
Copy link
Member Author

Starlight220 commented Nov 4, 2024

Wow I forgot I wrote this. This PR does what I was thinking of in that issue.

Is this missing something?

@Starlight220 Starlight220 marked this pull request as ready for review November 4, 2024 15:57
@Starlight220 Starlight220 requested a review from a team as a code owner November 4, 2024 15:57
@Daniel1464
Copy link
Contributor

I think there should be an overload that accepts a string and a command vararg in addition to the sendable chooser lambda overload.

@Starlight220
Copy link
Member Author

What would that string be used for, and what's the motivation for that overload?

@Daniel1464
Copy link
Contributor

Daniel1464 commented Nov 5, 2024

What would that string be used for, and what's the motivation for that overload?

Commands.choose(
      "AutoCommandChoice",
       commands
)

Commands.choose(
      (chooser) -> SmartDashboard.putData("AutoCommandChoice", chooser),
      commands
)

@Starlight220
Copy link
Member Author

It shouldn't be coupled to SmartDashboard.

Accepting an absolute NT key would be good, though.

@KangarooKoala
Copy link
Contributor

There doesn't appear to be a standard way to add a sendable to an arbitrary NT key, unfortunately. Maybe fix the merge conflicts for this PR and make an issue to add that capacity later?

@Starlight220 Starlight220 force-pushed the sendablechoosercommand branch 2 times, most recently from 2976c3d to a125981 Compare November 29, 2024 07:58
Copy link
Member

@rzblue rzblue left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The c++ version needs a test- it doesn't compile currently.

Comment on lines 181 to 194
template <std::convertible_to<CommandPtr>... CommandPtrs>
[[nodiscard]]
CommandPtr Choose(std::function<void(wpi::Sendable*)> publish,
CommandPtrs&&... commands) {
frc::SendableChooser<std::string_view> chooser;
((void)chooser.AddOption(commands.GetName(), commands.GetName()), ...);
publish(&chooser);
return Select(
[sendableChooser = std::move(chooser)]() mutable {
return sendableChooser.GetSelected();
},
(std::pair{commands.GetName(), std::move(commands)}, ...));
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't compile

@github-actions github-actions bot added the component: command-based WPILib Command Based Library label Dec 20, 2024
@Starlight220 Starlight220 force-pushed the sendablechoosercommand branch 3 times, most recently from 0d2b280 to 8157c91 Compare December 20, 2024 11:59
@Starlight220 Starlight220 force-pushed the sendablechoosercommand branch from 8157c91 to c2294d5 Compare December 20, 2024 12:10
@KangarooKoala
Copy link
Contributor

Tried fixing this locally, and while some issues could be fixed, a fundamental issue is that SelectCommand requires a std::function (which must be copyable), but SendableChooser is not copyable, so the lambda storing it can't be copyable either.

@Starlight220
Copy link
Member Author

Starlight220 commented Dec 22, 2024

shared_ptr it?

Thanks for looking into this!
Apparently the template errors were very inaccurate.

@KangarooKoala
Copy link
Contributor

Here's a patch that makes tests pass:

diff --git a/wpilibNewCommands/src/main/native/include/frc2/command/Commands.h b/wpilibNewCommands/src/main/native/include/frc2/command/Commands.h
index 7dea6f2c9..787497590 100644
--- a/wpilibNewCommands/src/main/native/include/frc2/command/Commands.h
+++ b/wpilibNewCommands/src/main/native/include/frc2/command/Commands.h
@@ -183,14 +183,14 @@ template <std::convertible_to<CommandPtr>... CommandPtrs>
 [[nodiscard]]
 CommandPtr Choose(std::function<void(wpi::Sendable*)> publish,
                   CommandPtrs&&... commands) {
-  frc::SendableChooser<std::string_view> chooser;
-  ((void)chooser.AddOption(commands.GetName(), commands.GetName()), ...);
-  publish(&chooser);
-  return Select(
-      [sendableChooser = std::move(chooser)]() mutable {
-        return sendableChooser.GetSelected();
+  auto chooser = std::make_shared<frc::SendableChooser<std::string_view>>();
+  ((void)chooser->AddOption(commands.get()->GetName(), commands.get()->GetName()), ...);
+  publish(chooser.get());
+  return Select<std::string_view>(
+      [sendableChooser = chooser]() mutable {
+        return sendableChooser->GetSelected();
       },
-      (std::pair{commands.GetName(), std::move(commands)}, ...));
+      std::pair{std::string_view{commands.get()->GetName()}, std::move(commands)}...);
 }
 
 /**
diff --git a/wpilibNewCommands/src/test/native/cpp/frc2/command/SendableChooserCommandTest.cpp b/wpilibNewCommands/src/test/native/cpp/frc2/command/SendableChooserCommandTest.cpp
index 0d419d855..25e67eb7a 100644
--- a/wpilibNewCommands/src/test/native/cpp/frc2/command/SendableChooserCommandTest.cpp
+++ b/wpilibNewCommands/src/test/native/cpp/frc2/command/SendableChooserCommandTest.cpp
@@ -23,7 +23,7 @@ using namespace frc2;
 using SendableChooserTestPublisherFunc = std::function<void(wpi::Sendable*)>;
 using SendableChooserTestArgs =
     std::pair<std::function<frc2::CommandPtr(SendableChooserTestPublisherFunc)>,
-              std::vector<std::string_view>>;
+              std::vector<std::string>>;
 
 class SendableChooserCommandTest
     : public CommandTestBaseWithParam<SendableChooserTestArgs> {
@@ -50,7 +50,7 @@ TEST_P(SendableChooserCommandTest, OptionsAreCorrect) {
 }
 
 namespace utils {
-static const frc2::CommandPtr CommandNamed(std::string_view name) {
+static frc2::CommandPtr CommandNamed(std::string_view name) {
   return frc2::cmd::Print(name).WithName(name);
 }
 
@@ -58,17 +58,17 @@ static const std::vector<SendableChooserTestArgs> OptionsAreCorrectParams() {
   SendableChooserTestArgs empty{[](SendableChooserTestPublisherFunc func) {
                                   return frc2::cmd::Choose(func);
                                 },
-                                std::vector<std::string_view>()};
+                                std::vector<std::string>()};
 
   SendableChooserTestArgs duplicateName{
       [](SendableChooserTestPublisherFunc func) {
         return frc2::cmd::Choose(func, CommandNamed("a"), CommandNamed("b"), CommandNamed("a"));
-      }, make_vector<std::string_view>("a", "b")};
+      }, make_vector<std::string>("a", "b")};
 
   SendableChooserTestArgs happyPath{
       [](SendableChooserTestPublisherFunc func) {
         return frc2::cmd::Choose(func, CommandNamed("a"), CommandNamed("b"), CommandNamed("c"));
-      }, make_vector<std::string_view>("a", "b", "c")};
+      }, make_vector<std::string>("a", "b", "c")};
 
   return make_vector<SendableChooserTestArgs>(empty, duplicateName, happyPath);
 }

Good thinking about the shared_ptr, I completely forgot about that. Just as for posterity, here's the fixes:

  • Use a shared_ptr to allow copying the lambda (necessary for use in a std::function for SelectCommand)
  • Use commands.get()->GetName(), since CommandPtr doesn't actually have a GetName() method
  • Specify the type parameter of Select() because type deduction was being weird
  • Fix the parameter pack expansion in a function argument list (before, it was a fold expression over the sequencing operator ,)
  • Change SendableChooserTestArgs to use std::string instead of std::string_view so that it matches the return type of optionsSubscriber.get() in the CHECK_EQ() macro.
  • Make CommandNamed() return a non-const CommandPtr because Choose() needs non-const CommandPtrs.

So yeah, some of the errors were poorly wording/misleading, others just were a bit tricky to figure out because there were so many.

@Starlight220
Copy link
Member Author

Wow -- thank you very much!
I'll apply your patch tonight and finish this up.

@Starlight220 Starlight220 requested a review from rzblue December 25, 2024 21:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component: command-based WPILib Command Based Library
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants