Python: Unable to solve a differential equation using odeint with signum function

[亡魂溺海] 提交于 2020-01-02 06:52:21

问题


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:

  1. Choose your step size such that the sign flip exactly falls on a step. (This may be horribly tedious.)

  2. 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!