wpilibsuite / allwpilib

Official Repository of WPILibJ and WPILibC
https://wpilib.org/
Other
1.08k stars 612 forks source link

`command.withName` crashes when run from dashboard #7352

Open pjreiniger opened 5 hours ago

pjreiniger commented 5 hours ago

Describe the bug If you publish a command over networktables and add a .withName decorator, the code crashes. Furthermore the name is no longer reflected in the buttons on the dashboard before you schedule the command

Image

Error at java.base/java.lang.Thread.run(Thread.java:840): Unhandled exception: java.lang.IllegalArgumentException: Commands that have been composed may not be added to another composition or scheduled individually!
java.lang.Exception: Originally composed at:
        at edu.wpi.first.wpilibj2.command.Command.withName(Command.java:579)
        at frc.robot.RobotContainer.<init>(RobotContainer.java:36)
        at frc.robot.Robot.<init>(Robot.java:28)
        at edu.wpi.first.wpilibj.RobotBase.runRobot(RobotBase.java:301)
        at edu.wpi.first.wpilibj.RobotBase.lambda$startRobot$0(RobotBase.java:418)
        at java.base/java.lang.Thread.run(Thread.java:840)

        at edu.wpi.first.wpilibj2.command.Command.lambda$initSendable$4(Command.java:594)
        at edu.wpi.first.wpilibj.smartdashboard.SendableBuilderImpl.lambda$addBooleanProperty$1(SendableBuilderImpl.java:332)
        at edu.wpi.first.wpilibj.smartdashboard.SendableBuilderImpl$Property.update(SendableBuilderImpl.java:87)
        at edu.wpi.first.wpilibj.smartdashboard.SendableBuilderImpl.update(SendableBuilderImpl.java:185)
        at edu.wpi.first.util.sendable.SendableRegistry.update(SendableRegistry.java:485)
        at edu.wpi.first.wpilibj.smartdashboard.SmartDashboard.updateValues(SmartDashboard.java:517)
        at edu.wpi.first.wpilibj.IterativeRobotBase.loopFunc(IterativeRobotBase.java:403)
        at edu.wpi.first.wpilibj.TimedRobot.startCompetition(TimedRobot.java:131)
        at edu.wpi.first.wpilibj.RobotBase.runRobot(RobotBase.java:350)
        at edu.wpi.first.wpilibj.RobotBase.lambda$startRobot$0(RobotBase.java:418)
        at java.base/java.lang.Thread.run(Thread.java:840)

To Reproduce

SmartDashboard.putData("SD Key", Commands.print("Hello World").withName("Name"));

Run the simulator, click the command, and the code crashes.

KangarooKoala commented 5 hours ago

Could you post a link to the full code? Note that command instances cannot be reused, so decorating a stored command is a bad idea, since then the stored command can no longer be used (except from the first time you decorated it).

Applying the following diff to a freshly generated robot project using the Robot Command Skeleton (Advanced) Java template works just fine:

diff --git a/src/main/java/frc/robot/Robot.java b/src/main/java/frc/robot/Robot.java
index b68462c..73007cd 100644
--- a/src/main/java/frc/robot/Robot.java
+++ b/src/main/java/frc/robot/Robot.java
@@ -5,8 +5,10 @@
 package frc.robot;

 import edu.wpi.first.wpilibj.TimedRobot;
+import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard;
 import edu.wpi.first.wpilibj2.command.Command;
 import edu.wpi.first.wpilibj2.command.CommandScheduler;
+import edu.wpi.first.wpilibj2.command.Commands;

 public class Robot extends TimedRobot {
   private Command m_autonomousCommand;
@@ -16,6 +18,7 @@ public class Robot extends TimedRobot {
   @Override
   public void robotInit() {
     m_robotContainer = new RobotContainer();
+    SmartDashboard.putData("SD Key", Commands.print("Hello World").withName("Name"));
   }

   @Override

(After opening the command from the SmartDashboard tab at the top of the Sim GUI, I can click Run multiple times and get a corresponding number of print statements)

pjreiniger commented 5 hours ago

Thats essentially what I have, except I did it in robot container. I didn't mention that this was with 2025.1.1-beta-1, maybe I should have made the issue in the beta repository

rzblue commented 4 hours ago

This is due to https://github.com/wpilibsuite/allwpilib/pull/6471. Calling initSendable on the wrapped command is fundamentally flawed as the wrapper is the command being sent.