1

Does np.linalg.solve() not work for AutoDiff? I use is to solve manipulator equation. The error message is shown below. I try a similar "double" version code, it is no issue. Please tell me how to fix it, thanks!

### here is the error message                        
vdot_ad = np.linalg.solve(M_,ggg_ad) 
    File "<__array_function__ internals>", line 5, in solve
    File "/usr/local/lib/python3.8/site-packages/numpy/linalg/linalg.py", line 394, in solve
    r = gufunc(a, b, signature=signature, extobj=extobj)
    TypeError: No loop matching the specified signature and casting was found for ufunc solve1

####. here is the code 
plant = MultibodyPlant(time_step= 0.01)
parser = Parser(plant)
parser.AddModelFromFile("double_pendulum.sdf")
plant.Finalize()
plant_autodiff = plant.ToAutoDiffXd()

####### <AutoDiff> get the error message
xu = np.hstack((x, u))
xu_ad = initializeAutoDiff(xu)[:,0]
x_ad = xu_ad[:4]
q_ad = x_ad[:2]
v_ad = x_ad[2:4]
u_ad = xu_ad[4:]
(M_, Cv_, tauG_, B_, tauExt_) = ManipulatorDynamics(plant_autodiff, q_ad, v_ad)
vdot_ad = np.linalg.solve(M_,tauG_ + np.dot(B_,u_ad) - np.dot(Cv_,v_ad)) 
Wc Chang
  • 97
  • 6
  • Sorry I didn't realize that `np.linalg.solve` doesn't work for autodiff. I would recommend that instead of computing `vdot_ad` by yourself, you could call `plant_autodiff.CalcTimeDerivatives`, which calls a function in C++. The C++ function works with Eigen's autodiff scalars. For more information on using CalcTimeDerivatives, you could refer to our tutorial https://nbviewer.jupyter.org/github/RobotLocomotion/drake/blob/nightly-release/tutorials/dynamical_systems.ipynb – Hongkai Dai Oct 29 '20 at 15:54
  • BTW, I rewrote the code in the question https://stackoverflow.com/questions/64565023/how-to-get-a-dynamic-which-we-can-be-applied-gradient-in-the-next-step-re-open/64565582#64565582 to use `CalcTimeDerivatives`. Notice that the plant is created as a continuous time system (dt=0). – Hongkai Dai Oct 29 '20 at 16:17
  • Yes, it is strange. I already work on this for a half day, vdot_ad = np.linalg.solve(M_,tauG_ + np.dot(B_,u_ad) - np.dot(Cv_,v_ad)). Maybe I miss something. I will check it again! – Wc Chang Oct 29 '20 at 16:18

1 Answers1

0

Note that in pydrake, AutoDiffXd scalars are exposed to NumPy using dtype=object.

There are some drawbacks to this approach, like what you have ran into now.
This is not necessarily an issue with Drake, but a limitation on NumPy itself given the ufunc's that are implemented on the (super old) version that is on 18.04.

To illustrate, here is what I see on Ubuntu 18.04, CPython 3.6.9, NumPy 1.13.3:

>>> import numpy as np
>>> A = np.eye(2)
>>> b = np.array([1, 2])
>>> np.linalg.solve(A, b)
array([ 1.,  2.])
>>> A = A.astype(object)
>>> b = b.astype(object)
>>> np.linalg.solve(A, b)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3/dist-packages/numpy/linalg/linalg.py", line 375, in solve
    r = gufunc(a, b, signature=signature, extobj=extobj)
TypeError: No loop matching the specified signature and casting
was found for ufunc solve1

The most direct solution would be to expose an analogous routine in pydrake, and have users leverage that.

That is what we had to do for np.linalg.inv as well:
https://github.com/RobotLocomotion/drake/pull/11173/files

Not the best solution :( However, it's simple enough!

Eric Cousineau
  • 1,944
  • 14
  • 23