问题
I am trying to solve this problem:
where U is
here:
s=c*e(t)+e_dot(t)
and
e(t)=theta(t)-thetad(t)
and
e_dot(t)=theta_dot(t)-thetad_dot(t)
where thetad(theta desired)=sin(t)-- i.e signal to be tracked! and thetad_dot=cos(t),J=10,c=0.5,eta=0.5
I tried first with odeint- it gave error after t=0.4 that is theta(solution of above differential equation) fell flat to 0 and stayed thereafter. However when I tried to increase mxstep to 5000000 I could get somewhat correct graph till t=4.3s.
I want to get a pure sinusoidal graph. That is I want theta(solution of the above differential equation) to track thetad i.e sin(t). But it is not able to accurately track thetad after t=4.3sec. After this time theta(solution of the above differential equation) simply falls off to 0 and stays there.
here is my code-
from scipy.integrate import odeint
import numpy as np
import matplotlib.pyplot as plt
c=0.5
eta=0.5
def f(Y,t):
x=Y[0]
y=Y[1]
e=x-np.sin(t)
de=y-np.cos(t)
s=c*e+de
return [y,-c*(de)-np.sin(t)-eta*np.sign(s)]
t=np.linspace(0,10,1000)
y0=[0.5,1.0]
sol=odeint(f,y0,t,mxstep=5000000)
#sol=odeint(f,y0,t)
print(sol)
angle=sol[:,0]
omega=sol[:,1]
error=angle-np.sin(t)
derror=omega-np.cos(t)
plt.subplot(4,2,1)
plt.plot(t,angle)
plt.plot(t,error,'r--')
plt.grid()
plt.subplot(4,2,2)
plt.plot(t,omega)
plt.plot(t,derror,'g--')
plt.grid()
plt.subplot(4,2,3)
plt.plot(angle,omega)
plt.grid()
plt.subplot(4,2,4)
plt.plot(error,derror,'b--')
plt.savefig('signum_graph.eps')
plt.show()
回答1:
The integrator employed by odeint
(and probably all integrators you find implemented) are based on the assumption that your derivative (f
) is continuous (and has a continuous derivative) during each step. The signum function obviously breaks this requirement. This causes the error estimates to be very high, no matter how small the step size, which in turn leads to an overly small step size and the problems you have been experiencing.
There are two general solutions to this:
Choose your step size such that the sign flip exactly falls on a step. (This may be horribly tedious.)
Replace the signum function with a very steep sigmoid, which should be fine and even more realistic for most applications. In your code, you could use
sign = lambda x: np.tanh(100*x)
instead of
np.sign
. The factor 100 here controls the steepness of the sigmoid. Choose it sufficiently high to reflect the behaviour you actually need. If you choose it excessively high, this may negatively affect your runtime as the integrator will adapt the step size to be unnecessarily small.
In your case, setting a small absolute tolerance also seems to be working, but I would not rely on this:
sol = odeint(f,y0,t,mxstep=50000,atol=1e-5)
来源:https://stackoverflow.com/questions/43841872/python-unable-to-solve-a-differential-equation-using-odeint-with-signum-functio