HIPS / autograd

Efficiently computes derivatives of NumPy code.
MIT License
7k stars 912 forks source link

Reshaping result throws exception #461

Open dawgster opened 5 years ago

dawgster commented 5 years ago

Hi! When trying to get the Jacobian of a function i get the following error:

Traceback (most recent call last): File "C:\Users\Jakub\AppData\Local\Programs\Python\Python36-32\lib\site-packages\numpy\core\fromnumeric.py", line 52, in _wrapfunc return getattr(obj, method)(*args, **kwds) TypeError: 'ListVSpace' object cannot be interpreted as an integer

During handling of the above exception, another exception occurred:

Traceback (most recent call last): File "C:/Users/Jakub/PycharmProjects/Driverless/Spline/test/splinetest.py", line 36, in model.getLinearizedModelAuto(model, [0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0]) File "C:\Users\Jakub\AppData\Local\Programs\Python\Python36-32\lib\site-packages\autograd\wrap_util.py", line 20, in nary_f return unary_operator(unary_f, x, *nary_op_args, nary_op_kwargs) File "C:\Users\Jakub\AppData\Local\Programs\Python\Python36-32\lib\site-packages\autograd\differential_operators.py", line 55, in jacobian return np.reshape(np.stack(grads), jacobian_shape) File "C:\Users\Jakub\AppData\Local\Programs\Python\Python36-32\lib\site-packages\autograd\tracer.py", line 48, in f_wrapped return f_raw(*args, *kwargs) File "C:\Users\Jakub\AppData\Local\Programs\Python\Python36-32\lib\site-packages\numpy\core\fromnumeric.py", line 257, in reshape return _wrapfunc(a, 'reshape', newshape, order=order) File "C:\Users\Jakub\AppData\Local\Programs\Python\Python36-32\lib\site-packages\numpy\core\fromnumeric.py", line 62, in _wrapfunc return _wrapit(obj, method, args, kwds) File "C:\Users\Jakub\AppData\Local\Programs\Python\Python36-32\lib\site-packages\numpy\core\fromnumeric.py", line 42, in _wrapit result = getattr(asarray(obj), method)(*args, **kwds) TypeError: 'ListVSpace' object cannot be interpreted as an integer

Process finished with exit code 1

Here is how I have the Jacobian set up:

self.getLinearizedModelAutoGrad = jacobian(VehicleModel.getStateDerivative, argnum=(1, 2))

Example of how I call it:

model.getLinearizedModelAutoGrad(model, [0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0])

And finally the function I'm trying to get the Jacobian of (sorry, not experienced enough with Autograd yet to tell which information is relevant here):

 def getStateDerivative(self, X, U):

        x, y, phi, vx, vy, omega = X
        delta1, delta2, a = U

        Fx1 = min(a, 0.0)  
        Fx2 = min(a, 0.0)
        Fx3 = a
        Fx4 = a

        eps = 10e-5
        Fy1 = self.tire_model.getLateralForce(np.arctan(
            (vy + self.a_f * omega) / (vx + .5 * self.b_f * omega + eps)) - delta1,
                                                  9.81 * self.mass / 4, np.deg2rad(1.0), 0.7)
        Fy2 = self.tire_model.getLateralForce(np.arctan(
            (vy + self.a_f * omega) / (vx - .5 * self.b_f * omega + eps)) - delta2,
                                                  9.81 * self.mass / 4, np.deg2rad(1.0), 0.7)
        Fy3 = self.tire_model.getLateralForce(np.arctan(
            (vy - self.a_r * omega) / (vx - .5 * self.b_r * omega + eps)) - self.delta3,
                                                  9.81 * self.mass / 4, np.deg2rad(1.0), 0.7)
        Fy4 = self.tire_model.getLateralForce(np.arctan(
            (vy - self.a_r * omega) / (vx + .5 * self.b_r * omega + eps)) - self.delta4,
                                                  9.81 * self.mass / 4, np.deg2rad(1.0), 0.7)
        forces = np.array([Fx1, Fy1, Fx2, Fy2, Fx3, Fy3, Fx4, Fy4])

        mat = np.array([[np.cos(delta1), np.sin(delta1), np.cos(delta2), np.sin(delta2), np.cos(self.delta3), np.sin(self.delta3),
                         np.cos(self.delta4), np.sin(self.delta4)],
                        [np.sin(delta1), np.cos(delta1), np.sin(delta2), np.cos(delta2), np.sin(self.delta3), np.cos(self.delta3),
                         np.sin(self.delta4), np.cos(self.delta4)],
                        [self.a_f * np.sin(delta1) - .5 * self.b_f * np.cos(delta1),
                         self.a_f * np.cos(delta1) - .5 * self.b_f * np.sin(delta1),
                         self.a_f * np.sin(delta2) + .5 * self.b_f * np.cos(delta2),
                         self.a_f * np.cos(delta2) + .5 * self.b_f * np.sin(delta2),
                         -self.a_r * np.sin(self.delta3) + .5 * self.b_r * np.cos(self.delta3),
                         -self.a_r * np.cos(self.delta3) + .5 * self.b_r * np.sin(self.delta3),
                         -self.a_r * np.sin(self.delta4) - .5 * self.b_r * np.cos(self.delta4),
                         -self.a_r * np.cos(self.delta4) - .5 * self.b_r * np.sin(self.delta4)]])

        constants = np.array([1 / self.mass, 1 / self.mass, 1 / self.inertia])
        external = np.array([-np.sign(vx) * 1.35 * vx ** 2,
                             -np.sign(vy) * 1.35 * vy ** 2,
                             -np.sign(omega) * (1.35 * omega ** 2) * (self.a_f + self.a_r)])  # checked

        ax,ay, omegadot = omega * np.array([vy, -vy, 0.0]) + constants * (
                 np.dot(mat, forces) + external)

        return np.array([vx, vy, omega, ax, ay, omegadot])

I'm using the current version provided by pip. I would be very grateful for any input on this problem. Thanks and have a happy new year!

neonwatty commented 5 years ago

I don't have the "silver bullet' solution to your problem, but a few thoughts and potential leads (I hope)

  1. There's a lot going on here - can you uncomplicate your code and try differentiating smaller chunks to aid in debugging?

  2. I could be reading your calls incorrectly, but I believe that you want to differentiate

getStateDerivative(self, X, U)

with respect to X and U - is that correct? If so then the jacobian call here

self.getLinearizedModelAutoGrad = jacobian(VehicleModel.getStateDerivative, argnum=(1, 2))

should produce an error due to indexing - I believe you want argnum=(0, 1) not argnum=(1, 2).

  1. Depending on how they are being processed, the inputs X and U should be transformed into autograd-numpy arrays. Inputing each as a list might cause a problem depending on what you're doing inside getStateDerivative