robotpy / robotpy-commands-v2

Python implementation of the WPILib Command Framework (2020+)
Other
2 stars 14 forks source link

Impossible to diagnose issue with functional commands #23

Closed virtuald closed 1 year ago

virtuald commented 1 year ago

Easy reproducer:

>>> import commands2.cmd
>>> r = commands2.cmd.run(None, [])
>>> r.execute()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: bad_function_call

The actual situation where this occurred was when one of our examples called a function instead of using a lambda:

@@ -56,13 +56,13 @@ class RobotContainer:

         # Move the arm to 2 radians above horizontal when the 'A' button is pressed.
         self.driver_controller.A().onTrue(
-            commands2.cmd.run(self.moveArm(2), [self.robot_arm])
+            commands2.cmd.run(lambda: self.moveArm(2), [self.robot_arm])
         )

         # Move the arm to neutral position when the 'B' button is pressed
         self.driver_controller.B().onTrue(
             commands2.cmd.run(
-                self.moveArm(constants.ArmConstants.kArmOffsetRads), [self.robot_arm]
+                lambda: self.moveArm(constants.ArmConstants.kArmOffsetRads), [self.robot_arm]
             )
         )
virtuald commented 1 year ago

FWIW, I don't exactly understand why this is possible. The type caster for std::function doesn't... oh, the problem is that it accepts None as a valid argument and converts it to an empty function. Womp.

Here's how we do it: https://pybind11.readthedocs.io/en/stable/advanced/functions.html#allow-prohibiting-none-arguments. It is a weird footgun that it allows None by default.

virtuald commented 1 year ago

Fixed in 2023.3.2.2