0

I am trying to access the contact information of the plant as below, by declaring an AbstractInputPort following this comment.

self.DeclareAbstractInputPort('contact_force', AbstractValue.Make(ContactResults()))

Then I an trying to access the actual contact information from the declared input port (2) using,

contact_info = self.EvalAbstractInput(context, 2).get_value()

However, I get a RecursionError: maximum recursion depth exceeded, whenever I try to simulate the system.

Any idea what's going wrong?


Edit

Trying to evaluate the method outside the simulation loop by,

contact_info = plant.get_contact_results_output_port().Eval(plant_context)

returns expected results when querying for i^th contact force using,

contact_info.point_pair_contact_info(i).contact_force()

My simulation setup requires computing the contact force at each instant during the simulation. I have a custom system which has an abstract input port declared as mentioned above. The input port is then connected to get contact results by,

builder.Connect(plant.get_contact_results_output_port(), my_system.get_input_port(2))

Now, while trying to extract the value within my_system using get_value() as above, I get the recursion error.

Is the port I use to obtain contact results correct? Or is there a another way to get contact results during simulation?

  • I don't see how those two lines can be at fault. Are you sure that is the line that is causing the error? Once you have a context for that system, you could try evaluating just that method (not in a simulation loop) to make sure? Otherwise I would need a more complete example to help. – Russ Tedrake Jan 30 '22 at 00:42
  • I tried evaluating the method outside the simulation loop as suggested and that works. I added more information too. I now suspect that the port I use to obtain contact results might not be the right one. – nightmareforev Feb 01 '22 at 12:19
  • I tried a simple example for reading the contact force following examples [here](https://github.com/gpldecha/pydrake-examples/blob/master/drake/box_example.py) and [here](https://github.com/RobotLocomotion/drake/blob/master/bindings/pydrake/systems/perception.py). I do not get the `RecursionError` whenever I use `FixValue` for the plants `get_actuation_input_port`. However, when the value is not fixed but an output from one of the `systems`, I get the `RecursionError` again. The error occurs only when I try to publish the context using, `diagram.Publish(context)`, until then I see no error. – nightmareforev Feb 11 '22 at 17:27

2 Answers2

0

I ran the code you linked.

box_example.py

There were a bunch of errors in there that needed to be fixed before it could be run, and it's clear that you're running on an older version of drake (still importing from attic which is long removed). Perhaps the new version will give you better error messages?

The one change that could have been more mysterious in an older version is that you were calling SetPositions with the wrong context. I've changed it to use the plant_context, not context: plant.SetPositions(plant_context, object_instance, [0, 0, 0, 1, 0, 0, 0]). With that fix (and fixing/updating the imports), that file runs fine for me.

perception.py

didn't actually have any runnable code. So I'm not sure what I'm supposed to see there.

Russ Tedrake
  • 4,703
  • 1
  • 7
  • 10
  • Thank you for the details. I did update drake and still have the same error. I have a simpler version of the code I'm running, which can reproduce the error, [here](https://deepnote.com/project/sololegjump-controller-22-02-11-reference-force-simple-contact-loggeripynb-wDoFrYnzTnqyuCZTLCdlqg/%2Fsolo_leg_jump-controller-22-02-11-reference-force-simple-contact-logger.ipynb). I'm using the background setup from one of the example Deepnotes from the textbook (so it should run without any issue on a different PC). – nightmareforev Feb 15 '22 at 13:49
  • I've added a line to your notebook to draw the diagram you've constructed. I suspect you know what's happening, but it helped me see the problem. You have created an algebraic loop. Contact forces are "direct feedthrough" from the actuation input port. The standard solution here would be to add a `ZeroOrderHold` system between the contact results and your `ContactForceEval` system. I've opened this issue to see if we can provide a more immediate/helpful error messages for this case in the future. https://github.com/RobotLocomotion/drake/issues/16636 – Russ Tedrake Feb 20 '22 at 17:06
0

Posting the solution provided in this comment as the answer for clarity.

As mentioned, the contact force is an input into the simulation and are a "direct feedthrough", forming an algebraic loop (Have a look at this for a Matlab reference).

The solution is to simply add a ZeroOrderHold as suggested:

zoh = builder.AddSystem(ZeroOrderHold(time_step, AbstractValue.Make(ContactResults())))
builder.Connect(plant.get_contact_results_output_port(), zoh.get_input_port())
builder.Connect(zoh.get_output_port(), my_system.get_input_port())

A corresponding GitHub issue is also linked in the comment.