RobotLocomotion / drake

Model-based design and verification for robotics.
https://drake.mit.edu
Other
3.36k stars 1.27k forks source link

Support print functionality for pydrake objects #8586

Closed thduynguyen closed 8 months ago

thduynguyen commented 6 years ago

This applies to most pydrake objects.

As an example, right now:

In [105]: camera_info = CameraInfo(640., 480., 400.)

In [106]: print camera_info
<pydrake.systems.sensors.CameraInfo object at 0x7f74661bc370>

An example of what ~it's supposed to be~ Duy would like it to be:

In [109]: pose = Isometry3()

In [110]: print pose
[[ 1.  0.  0.  0.]
 [ 0.  1.  0.  0.]
 [ 0.  0.  1.  0.]
 [ 0.  0.  0.  1.]]

EDIT(eric): Clarified "should" vs. "want".

EricCousineau-TRI commented 4 years ago

On this front, I think this should only be tackled if Drake components themselves have some sort of fixed formula for to_string. I disprefer a slew of Python-custom one-offs if possible. (This means the strings will be C++-specific, but I think we can spiff those up if need be.)

@sherm1 @SeanCurtis-TRI Can I ask if y'all have already discussed this before?

EricCousineau-TRI commented 4 years ago

See some relevant discussion in: https://github.com/RobotLocomotion/drake/pull/13384#issuecomment-632719916

EricCousineau-TRI commented 4 years ago

Also, important when unittesting: https://github.com/RobotLocomotion/drake/issues/12257#issuecomment-632794480

If nothing else, the current pydrake unit test was not clear enough to Drake maintainers that the exact string output under test was important as a golden answer, and should not be changed (at least not without consulting the SMEs). We will need to improve the clarity of the test.

sherm1 commented 4 years ago

It's not clear to me that we want the same formatting for these objects in pydrake and C++ drake. So would a to_string() method solve the problem? Do we need a to_python_string()? I expect we want Eigen-like formatting in C++ and Numpy-like formatting in Python.

EricCousineau-TRI commented 4 years ago

Late to the game, but yeah, we definitely want Pythonic strings when possible, specifically for repr: https://docs.python.org/3.6/reference/datamodel.html#object.__repr__

image

EricCousineau-TRI commented 4 years ago

One hacky formulation:

from pydrake.math import RigidTransform

def merp(X):
    R = X.rotation().matrix().tolist()
    return (
        f"RigidTransform(\n"
        f"  R=RotationMatrix([\n"
        f"    {R[0]},\n"
        f"    {R[1]},\n"
        f"    {R[2]},\n"
        f"  ]),\n"
        f"  p={X.translation().tolist()},\n"
        f")"
    )

RigidTransform.__repr__ = merp

Preview:

RigidTransform(
  R=RotationMatrix([
    [0.43993107404559745, 0.8028041897775012, -0.4024500999686495],
    [0.8976806525159292, -0.4056536462558163, 0.17208882990460417],
    [-0.025101716826976452, -0.43697889211614105, -0.8991214332098241],
  ]),
  p=[-1.668049090070875e-05, 1.985772726274851e-05, 0.0009829970598220826],
)
jwnimmer-tri commented 1 year ago

In #17442, I will be adding fmt::formatter<T> specializations for many objects.

Since fmt is so very awesome, it supports user extensions to its format specification mini-language for customizing the output.

We could easily imagine doing fmt::format("{:!r}", camera_info) to calculate the Python repr, implemented in C++ code, and sharing most of its implementation details with the C++ string output.

jwnimmer-tri commented 8 months ago

I support the idea of having good print and repr output for pydrake. I'm not sure that an Epic issue to request it globally is actionable, though.