In many real life applications where we wish to evaluate a function, we are only able to define the relationship that the derivative of that function must satisfy. One example is the dynamics of a vehicle in which we wish to determine the velocity or acceleration, however the unknowns are specified only in terms of ordinary differential equations (ODEs) and initial conditions. In this note we wish to show one approach to the numerical solution of ODEs using MATLAB and the Classical fourth order Runge-Kutta method. This is a very personal approach and is somewhat different to that normally used, however I will try to justify it further on. The approach will be developed and illustrated in terms of two case studies.
Consider a simple pendulum having length L,
mass m and instantaneous angular displacement q (theta), as shown below:
Fortunately we can always reduce a n-th order ODE into a n-vector set of first order ODEs. Thus we need only concentrate on developing numerical techniques for solving first order ODEs. Processing vectors by computer simply requires looping sequentially through the indices of the vector, and MATLAB is particularly geared to this type of analysis.
Consider now the practical aspects of writing
a function for evaluating this set of derivatives. One problem
is that vectors are usually assigned generic names such as y for
the set of dependent variables and dy for their derivatives, however
we would like to retain their identity in terms of q (theta) and
(omega). This can be done by means of indices, as shown in the
MATLAB function below:
function [y,dy] = dpend(t,y) %Pendulum differential equations % G [m/s^2] acceleration due to gravity % LENGTH [m] pendulum length % Izzi Urieli - Jan 21, 2002 global G LENGTH THETA = 1; % index of angle [radians] OMEGA = 2; % index of angular velocity [rads/sec] dy(THETA) = y(OMEGA); dy(OMEGA) = -(G/LENGTH)*sin(y(THETA)); dy = [dy(THETA);dy(OMEGA)]; % Column vector
Consider now a typical main function for this
%Solve the large angle pendulum problem % Izzi Urieli - Jan 21, 2002 THETA = 1; % index of angle [radians] OMEGA = 2; % index of angular velocity [rads/sec] global G LENGTH G = 9.807; % [m/s/s} accel. due to gravity LENGTH = input('Enter pendulum length [m] >'); angle0 = input('Enter initial pendulum angle [degrees] >'); period = 2*pi*sqrt(LENGTH/G); fprintf('small angle period is %.3f seconds\n',period); tfinal = 2*period; n = input('Enter the number of solution points >'); dt = tfinal/(n - 1); t = 0; y = [angle0*pi/180;0]; % Initialise y as a Column vector time(1) = t; angle(1) = angle0; for i = 2:n [t, y, dy] = rk4('dpend',2,t,dt,y); time(i) = t; angle(i) = y(THETA)*180/pi; fprintf('%10.3f%10.3f\n',time(i),angle(i)); end plot(time,angle)
[t, y, dy] = rk4('dpend',2,t,dt,y);
Thus the input arguments are the string constant representing the derivative function 'dpend', the number of differential equations in the set (2), the independent variable and increment (t,dt), and the dependent variable vector (y). The output arguments are the solution variables and derivatives (t,y,dy) integrated over one time step dt.
MATLAB provides five separate routines for
solving ODEs of the form dy
= f(x,y) where x is the independent
variable and y and dy are the solution and derivative vectors. They are
extremely simple to use, however they do not provide the versatility
that I am looking for, including choosing the step size dx and overloading
(see case study following) so I decided to write my own routine.
One of the most widely used of all the single step Runge-Kutta
methods (which include the Euler and Modified Euler methods) is
the so called 'Classical' fourth order method with Runge's coefficients.
Being a fourth order method (equivalent in accuracy to including
the first five terms of the Taylor series expansion of the solution)
it requires four evaluations of the derivatives over each increment
denoted respectively by dy1, dy2, dy3, dy4. These are then weighted and summed in a very specific
manner to obtain the final derivative dy.
function [x, y, dy] = rk4(deriv,n,x,dx,y) %Classical fourth order Runge-Kutta method %Integrates n first order differential equations %dy(x,y) over interval x to x+dx %Izzi Urieli - Jan 21, 2002 x0 = x; y0 = y; [y,dy1] = feval(deriv,x0,y); for i = 1:n y(i) = y0(i) + 0.5*dx*dy1(i); end xm = x0 + 0.5*dx; [y,dy2] = feval(deriv,xm,y); for i = 1:n y(i) = y0(i) + 0.5*dx*dy2(i); end [y,dy3] = feval(deriv,xm,y); for i = 1:n y(i) = y0(i) + dx*dy3(i); end x = x0 + dx; [y,dy] = feval(deriv,x,y); for i = 1:n dy(i) = (dy1(i) + 2*(dy2(i) + dy3(i)) + dy(i))/6; y(i) = y0(i) + dx*dy(i); end
The most interesting aspect of this function is the use of the MATLAB function 'feval' to evaluate the function argument which is passed as a string. This is a fundamental aspect of MATLAB programming, and understanding this is essential to developing MATLAB programs.
The plotting capabilities of MATLAB are extremely
simple to use and very versatile. I show a typical output plot
for the pendulum case study as follows:
We see that 20 degrees is about the limit of the small angle period (2.006 s), however at 80 degrees the period is seen to be much larger (2.293 s). This could only have been determined by numerically solving the differential equation set.
Since September 2001 I have been designing
an electric bicycle (refer: www.eBiciBikes.com).
In this case study I would like to indicate how I am using the
above method to do a dynamic simulation of the eBici bike in order
to understand the behaviour of the vehicle under acceleration
from a complete stop. Consider the main function as follows:
%trialrun.m - of eBici % y(DIS) = distance covered (m) % y(VEL) = velocity (m/s) % y(POW) = instantaneous power (watts) % y(AMP) = motor current (amps) % Izzi Urieli - Jan 25, 2002 DIS = 1; VEL = 2; POW = 3; AMP = 4; global VBAT SLOPE tfinal = 30; % (s) time span to integrate over VBAT = 36; % Volts SLOPE = 0; % Zero slope for this trial npoints = 100; % number of solution points dt = tfinal/(npoints - 1); t = 0; % Initialise independent variable time y = [0;0;0;0]; % initial [dist;velo;power;amps] time(1) = t; dist(1) = y(DIS); velo(1) = y(VEL)*9/4; % meters/sec to mph power(1) = y(POW)/20; % watts/20 - for plot scale amps(1) = y(AMP); for i = 2:npoints [t, y, dy] = rk4('deBici',2,t,dt,y); time(i) = t; dist(i) = y(DIS); velo(i) = y(VEL)*9/4; power(i) = y(POW)/20; amps(i) = y(AMP); end plot(time,velo,'k') axis([0,30,0,40]) grid on hold on plot(time,power,'r') plot(time,amps,'b')
function [y,dy] = deBici(t,y) %deBici - eBici differential equations of motion % y(DIS) = distance covered (m) % y(VEL) = velocity (m/s) % y(POW) = instantaneous power (watts) % y(AMP) = motor current (amps) % Izzi Urieli - Jan 21, 2002 DIS = 1; VEL = 2; POW = 3; AMP = 4; global VBAT SLOPE % eBici basic parameters: mt = 100.0; % [kg] total mass of bike + rider mw = 1.0; % [kg] mass of each wheel rw = 0.2115; % [m] radius of wheel jw = mw*(rw^2); % [kg m^2] moment of inertia of each wheel (kg m^2) % equivalent inertial mass of bike + rider: mi = mt + 2*jw/(rw^2); % motor/generator mg62 specs: winding = 0.395; % [ohms] resistance kt = 0.62; % [Nm/A] torque constant imax = 32; % [amps] current limit setting on controller % wheel/motor gear ratio: n = 30/22; % wheel_torque / motor_torque % applied torque at rear wheel tw: tw = (n*kt/winding)*(VBAT - kt*n*y(VEL)/rw); twmax = n*kt*imax; % current limit setting on controller if tw > twmax % stall torque by current limit tw = twmax; end % current drain y(AMP) = tw/(n*kt); % mechanical power (force*velocity (watts)): y(POW) = (tw/rw)*y(VEL); % resistive forces: drag, slope, rolling resistance cda = 0.4; % [m^2] coef. of drag * frontal area density = 1.18; % [kg/m^3] air density drag = cda*density*y(2).^2/2; cr = 0.005; % coefficient of rolling resistance g = 9.807; % [m/s^2] gravity resist = mt*g*(cr + SLOPE); dy(DIS) = y(VEL); % velocity dy(VEL) = (tw/rw - (drag + resist))/mi; % acceleration dy = [dy(DIS); dy(VEL)]; % must be a column vector
The ability to load the y-vector with the motor
current and power values allowed me to develop the following transient
performance plot from the main function:
Note that if we wanted to limit the speed to below 10 mph then all that we would to do is reduce the battery voltage from 36 volts to 18 volts. This is because the back emf (induced voltage) of a permanent magnet motor is linearly proportional to the motor rotational speed. Thus the following plot results: