symforce-org / symforce

Fast symbolic computation, code generation, and nonlinear optimization for robotics
https://symforce.org
Apache License 2.0
1.41k stars 145 forks source link

Better error messages on generating functions with abstract camera types #272

Open aaron-skydio opened 1 year ago

aaron-skydio commented 1 year ago

If you try to generate a function where one of the symbolic inputs is a CameraCal (instead of a concrete subclass) you get a pretty inscrutable error message:

f.generate():228 INFO -- Generating functions
---------------------------------------------------------------------------
NotImplementedError                       Traceback (most recent call last)
Cell In [4], line 7
      5 output_dir = Path("gen/")
----> 7 generate(output_dir=output_dir)

File f.py:242, in generate(output_dir)
--> 242 codegen.Codegen.function(
    243     my_function,
    244     config=codegen.CppConfig(),
    245 ).generate_function(output_dir=output_dir, namespace=namespace)

File symforce/symforce/codegen/codegen.py:274, in Codegen.function(cls, func, config, name, input_types, output_names, return_key, docstring)
    271 inputs = symbolic_inputs(func, input_types)
    273 # Run the symbolic arguments through the function and get the symbolic output expression(s)
--> 274 res = func(*inputs.values())
    276 # at this point replace all dataclasses in the inputs with values
    277 inputs = inputs.dataclasses_to_values()

File f.py:73, in my_function(source_pose, source_calibration, target_pose, target_calibration, source_coords, target_coords, epsilon)
     72 # compute feature and camera rays in world space
---> 73 source_camera_dir = source_calibration.camera_ray_from_pixel(source_coords, epsilon)[0]
     74 source_camera_ray = source_camera_dir / source_camera_dir.norm(epsilon=epsilon)

File symforce/symforce/cam/camera_cal.py:142, in CameraCal.camera_ray_from_pixel(self, pixel, epsilon)
    130 def camera_ray_from_pixel(
    131     self, pixel: geo.V2, epsilon: T.Scalar = sf.epsilon()
    132 ) -> T.Tuple[geo.V3, T.Scalar]:
    133     """
    134     Backproject a 2D pixel coordinate into a 3D ray in the camera frame.
    135 
   (...)
    140         is_valid: 1 if the operation is within bounds else 0
    141     """
--> 142     raise NotImplementedError()

NotImplementedError:

Might get a better message if we make those abstract methods instead?