I have been designing a controller for a motion system. The controller contains a gain, Proportional integrator(PI) and a lead filter in series. I have tuned the gain of the controller manually to obtain a desired bandwidth(cross over frequency). The frequency of lead and PI are based on rule of thumb(for lead, bandwidth/3 in the numerator, bandwidth*3 in the denominator and for integrator its bandwidth/5).
How can I decide on the gain of the controller to obtain automatically just by mentioning desired bandwidth. Is there any rule of thumb to be followed? How does it change according to sampling frequency?
PID controller design is an inherently difficult problem. You can't do it via simple matters unless your system allows you to derive certain expressions due to simplicity.
One way to do it is to resort back to nonconvex nonsmooth optimization algorithms such as Matlab's own systune or HIFOO or some other tools that solve for "a" solution but not "the" solution.
There are examples for loop shaping and bandwidth constraints on the documentation.
Well you could simply use your rules of thumb regarding for the I action and the lead filter. Then you simply check the bode diagram of the open-loop. Check the magnitude of the system at the frequency where you want your bandwidth. Then you can simply calculate how much gain you need to apply to move the point upwards to 0 dB, the bandwidth.
Furthermore, the rules of thumb assume a high enough sampling frequency. But, in general, if the sampling frequency becomes lower your gain also will be lower, however the frequencies of the I action and the lead filter will also change.
-edit-
I made a small script for you. The script is self explaining.
The same methods can be applied in the discrete domain. Furthermore, I would not design the controller in discrete domain, but rather in continuous time-domain. Following, I would use a discretization method to convert the controller from continuous time to discrete time, such as the Bilinear transform. http://nl.mathworks.com/help/control/ref/c2d.html provides information how you can do this in Matlab.
In addition, I would like to recommend this tool for you, http://cstwiki.wtb.tue.nl/index.php?title=Home_of_ShapeIt
clear all;
close all;
clc;
%% Initialize parameters
s = tf('s');
% Mass of plant
m = 10;
% Desired bandwidth
BW = 10;
%% Define plant
P = 1/(m*s^2);
%% Define filters
% Lead lag filter
f1 = (1/(2*pi*BW/3)*s + 1)/(1/(2*pi*BW*3)*s + 1);
% Integrator
f2 = (s + 2*pi*BW/5)/s;
% define Controller
C = f1*f2;
%% Determine gain
% Open loop
OL = C*P;
% Evaluate at bandwidth and get magnitude
mag = abs(evalfr(OL,2*pi*BW));
% Desired gain is 1/mag
C = 1/mag*C;
% Recalculate open loop
OL = C*P;
% Evaluate at bandwidth, magnitude should be 1
sprintf('Magnitude at bandwidth: %f\n',abs(evalfr(OL,2*pi*BW)));
%% Compute other stuff
% Sensnitivity
SS = 1/(1 + OL);
% Closed loop, complementary sensitivity
CL = OL*SS;
% Process sensitivity
PS = P*SS;
% Controller sensitivity
CS = C*SS;
%% Create some plots
% Open loop
figure(1);
bode(OL);
title('Open loop');
% Nyquist
figure(2);
nyquist(OL);
% Other sensitivities
figure(3);
subplot(2,2,1);
bodemag(CL);
title('Closed loop');
subplot(2,2,2);
bodemag(SS);
title('Sensitivity');
subplot(2,2,3);
bodemag(PS);
title('Process sensitivity');
subplot(2,2,4);
bodemag(CS);
title('Controller sensitivity');
% Step
figure(4);
step(CL);
title('Step response');
Related
I am currently trying to solve a problem with Mixed-Integer linear problems. I have a component, which capacity and operation I want to optimize. This component has a lower limit of operation, p_low. The optimization can either run the component between its upper limit (the capacity) or p_low, but it should also be able to shut-down the component.
Here starts the issue: I have no idea how to implement both possibilities, as a shut-down would violate the minimal power constraint.
I thought about using binary variables for decision (b_status), but I have a problem with the the capacity of the component, because it is optimized as well and combining the capacity variable with the binary variable:
p >= p_low * capacity * b_status -> if b_status is 0 -> p >= 0; else: p >= p_low * capacity
... would result in a non-linear problem as the combination of capacity and b_status is not allowed in linear models (both variables).
Does someone know a way to implement this? I know this is not the main topic here, but it might be worth the try asking.
You are almost there...
You are correct, you will need 2 variables to model this equipment. Let:
x_on = {0, 1} a binary variable to indicate whether system is on/off
x_load = {x: x >= 0 } a continuous, non-negative variable to indicate the current load
Then you will need to creatively use x_on as an indicator variable within the constraints to either set x_load at zero or between the low-high limits...
High constraint: x_load <= x_on * high_limit
Low constraint: x_load >= x_on * low_limit
Those are linear. Plug in some values to ensure you believe them. :). Presumably somewhere in your model you are minimizing x_load and this will get it done.
=================
Edit for variable capacity
I misread your problem. Per your comment, I think you are again on the right track and using a big-M constraint can do this.
In addition to the above variables x_on and x_load let
C = {x : x >=0} a continuous non-negative variable to represent the capacity of the machine
M = any reasonable upper bound on C
You have a workable solution for the low limit. By using 2 constraints for the high (3 constraints total), you can incorp the big-M for the high also
Low: x_load >= low_lim * C - M * (1 - x_on)
High: x_load <= C
Off: x_load <= M * x_on
I have this function here
def gravitationalForce(p1,p2):
G = 1=
rVector = p1.pos - p2.pos
# if vp.mag(rVector) <.01:
# planet1.pos =- planet1.pos
# star.pos = - star.pos
rMagnitude = vp.mag(rVector)
rHat = rVector / rMagnitude
F = - rHat * G * p1.mass * p2.mass /rMagnitude**2
return F
and what I'm trying to do is make a single object/sphere that starts with a momentum of zero, some distance from a massive object. Over time the object pulls it in, and then it flies through to the other side, slowing down, and osculating back and forth. My issue is that while I am accurately simulating gravity between the two points, the moment the magnitude of the radius hits 0, the force seems to go to infinity, shooting the particle out at very high speeds in the following time steps, before it has a chance to be slowed down my the force of gravity on the other side. I tried to skip over the center when it was some small radius by implementing the conditional
# if vp.mag(rVector) <.01:
# planet1.pos =- planet1.pos
# star.pos = - star.pos
but this made no change and the object still shoots out.
Here are the given objects I generate
star = vp.sphere(pos=vp.vector(0,0,0), radius=0.2, color=vp.color.yellow,
mass = 2.0*10000, momentum=vp.vector(0,0,0), make_trail=True)
planet1 = vp.sphere(pos=vp.vector(-1,0,0), radius=0.05, color=vp.color.green,
mass = 1, momentum=vp.vector(10,0,0), make_trail=True)
You need to check to see whether the next step would, if carried out, put the planet inside the star. If so, you might move to the near side of the star, then move at (say) a constant speed to the other side of the star and turn on gravity again. The alternative would be to take very short steps while inside the star. This isn't quite physical, because you really need to use Gauss's law to calculate (in the approximation of a constant density for the star) the actual gravitational force.
I am trying to do a linear buckling analysis (sol 105) with Nastran on a cylindrical shell structure. My understanding is that the compressive load that I apply to the structure must be multiplied by the resulting eigenvalue to get the buckling load. This gives me results that I expect.
However, now I apply a single perturbation load (SPL), a small transverse force acting midway along the cylinder on a single grid point. My understanding is that the magnitude of the SPL stays the way it is, (Unlike the compressive load where I multiply it with the eigenvalue to obtain buckling load.) The results I obtain are not what I expect, as the buckling load should not reduce so much as the SPL increases, according to the theory on this topic.
I am wondering if anyone knows what I am doing wrong. I feel like my mistake is probably very easy, but I haven't been able to solve it yet. Here is some more information on my implementation:
Axial compressive force spread over top grid points of cylinder.
Both SPL (the transverse point load) and axial loads are added to the static analysis subcase. Then the buckling subcase uses the static subcase for its analysis. This is how I understand it should be done.
boundary conditions:
SPC1 restraining 123 (xyz) directions at bottom grid points.
SPC1 restraining 12 (xy) directions at top grid points.
I'm not a Nastran user but I've done a lot of buckling analysis with Cast3M software.
The linear buckling analysis does not need perturbation loading, but only your main axial loading (F^0).
To recap,
Solve the linear problem for axial loading :
solve for u^0 : [K] * u^0 = F^0
get the linear stresses from the Hooke law : \sigma^0 = D * B * u^0
Solve the eigenvalue buckling problem :
[ K + \lambda Kgeo(\sigma^0)] * X = 0
Then, if you want to perform a non-linear (large displacement) post-buckling analysis, it is recommended to introduce a small perturbation which "excites" the buckling mode.
If you introduce the perturbation loading before the linear buckling analysis, maybe Nastran is adding it to F^0 and it is then logical that the result of buckling changes.
Hope this can help you.
There is a way to scale some loads and hold others constant. Create 2 Static Subcases with 2 (different) sets of loads:
Constant loads (that are not scaled, like a preload or internal pressure)
Those that will be scaled by the eigenvalue
Order does not matter
Use the Nastran STATSUB entry to define. It looks like this:
SUBCASE 100
LOAD = 1 $ Static pre-load
SUBCASE 200
LOAD = 2 $ Varying buckling load
$ -------------
SUBCASE 1000
STATSUB(PRELOAD) = 100
STATSUB(BUCKLING) = 200
METHOD = 10
The eigensolution is modified to include influence of static and varying loads.
so I am making a simple simulation of different planets with individual velocity flying around space and orbiting each other.
I plan to simulate their pull on each other by considering each planet as projecting their own "gravity vector field." Each time step I'm going to add the vectors outputted from each planets individual vector field equation (V = -xj + (-yj) or some notation like it) except the one being effected in the calculation, and use the effected planets position as input to the equations.
However this would inaccurate, and does not consider the gravitational pull as continuous and constant. Bow do I calculate the movement of my planets if each is continuously effecting the others?
Thanks!
In addition to what Blender writes about using Newton's equations, you need to consider how you will be integrating over your "acceleration field" (as you call it in the comment to his answer).
The easiest way is to use Euler's Method. The problem with that is it rapidly diverges, but it has the advantage of being easy to code and to be reasonably fast.
If you are looking for better accuracy, and are willing to sacrifice some performance, one of the Runge-Kutta methods (probably RK4) would ordinarily be a good choice. I'll caution you that if your "acceleration field" is dynamic (i.e. it changes over time ... perhaps as a result of planets moving in their orbits) RK4 will be a challenge.
Update (Based on Comment / Question Below):
If you want to calculate the force vector Fi(tn) at some time step tn applied to a specific object i, then you need to compute the force contributed by all of the other objects within your simulation using the equation Blender references. That is for each object, i, you figure out how all of the other objects pull (apply force) and those vectors when summed will be the aggregate force vector applied to i. Algorithmically this looks something like:
for each object i
Fi(tn) = 0
for each object j ≠ i
Fi(tn) = Fi(tn) + G * mi * mj / |pi(tn)-pj(tn)|2
Where pi(tn) and pj(tn) are the positions of objects i and j at time tn respectively and the | | is the standard Euclidean (l2) normal ... i.e. the Euclidean distance between the two objects. Also, G is the gravitational constant.
Euler's Method breaks the simulation into discrete time slices. It looks at the current state and in the case of your example, considers all of the forces applied in aggregate to all of the objects within your simulation and then applies those forces as a constant over the period of the time slice. When using
ai(tn) = Fi(tn)/mi
(ai(tn) = acceleration vector at time tn applied to object i, Fi(tn) is the force vector applied to object i at time tn, and mi is the mass of object i), the force vector (and therefore the acceleration vector) is held constant for the duration of the time slice. In your case, if you really have another method of computing the acceleration, you won't need to compute the force, and can instead directly compute the acceleration. In either event, with the acceleration being held as constant, the position at time tn+1, p(tn+1) and velocity at time tn+1, v(tn+1), of the object will be given by:
pi(tn+1) = 0.5*ai(tn)*(tn+1-tn)2 + vi(tn)*(tn+1-tn)+pi(tn)
vi(tn+1) = ai(tn+1)*(tn+1-tn) + vi(tn)
The RK4 method fits the driver of your system to a 2nd degree polynomial which better approximates its behavior. The details are at the wikipedia site I referenced above, and there are a number of other resources you should be able to locate on the web. The basic idea is that instead of picking a single force value for a particular timeslice, you compute four force vectors at specific times and then fit the force vector to the 2nd degree polynomial. That's fine if your field of force vectors doesn't change between time slices. If you're using gravity to derive the vector field, and the objects which are the gravitational sources move, then you need to compute their positions at each of the four sub-intervals in order compute the force vectors. It can be done, but your performance is going to be quite a bit poorer than using Euler's method. On the plus side, you get more accurate motion of the objects relative to each other. So, it's a challenge in the sense that it's computationally expensive, and it's a bit of a pain to figure out where all the objects are supposed to be for your four samples during the time slice of your iteration.
There is no such thing as "continuous" when dealing with computers, so you'll have to approximate continuity with very small intervals of time.
That being said, why are you using a vector field? What's wrong with Newton?
And the sum of the forces on an object is that above equation. Equate the two and solve for a
So you'll just have to loop over all the objects one by one and find the acceleration on it.
I've tried the typical physics equations for this but none of them really work because the equations deal with constant acceleration and mine will need to change to work correctly. Basically I have a car that can be going at a large range of speeds and needs to slow down and stop over a given distance and time as it reaches the end of its path.
So, I have:
V0, or the current speed
Vf, or the speed I want to reach (typically 0)
t, or the amount of time I want to take to reach the end of my path
d, or the distance I want to go as I change from V0 to Vf
I want to calculate
a, or the acceleration needed to go from V0 to Vf
The reason this becomes a programming-specific question is because a needs to be recalculated every single timestep as the car keeps stopping. So, V0 constantly is changed to be V0 from last timestep plus the a that was calculated last timestep. So essentially it will start stopping slowly then will eventually stop more abruptly, sort of like a car in real life.
EDITS:
All right, thanks for the great responses. A lot of what I needed was just some help thinking about this. Let me be more specific now that I've got some more ideas from you all:
I have a car c that is 64 pixels from its destination, so d=64. It is driving at 2 pixels per timestep, where a timestep is 1/60 of a second. I want to find the acceleration a that will bring it to a speed of 0.2 pixels per timestep by the time it has traveled d.
d = 64 //distance
V0 = 2 //initial velocity (in ppt)
Vf = 0.2 //final velocity (in ppt)
Also because this happens in a game loop, a variable delta is passed through to each action, which is the multiple of 1/60s that the last timestep took. In other words, if it took 1/60s, then delta is 1.0, if it took 1/30s, then delta is 0.5. Before acceleration is actually applied, it is multiplied by this delta value. Similarly, before the car moves again its velocity is multiplied by the delta value. This is pretty standard stuff, but it might be what is causing problems with my calculations.
Linear acceleration a for a distance d going from a starting speed Vi to a final speed Vf:
a = (Vf*Vf - Vi*Vi)/(2 * d)
EDIT:
After your edit, let me try and gauge what you need...
If you take this formula and insert your numbers, you get a constant acceleration of -0,0309375. Now, let's keep calling this result 'a'.
What you need between timestamps (frames?) is not actually the acceleration, but new location of the vehicle, right? So you use the following formula:
Sd = Vi * t + 0.5 * t * t * a
where Sd is the current distance from the start position at current frame/moment/sum_of_deltas, Vi is the starting speed, and t is the time since the start.
With this, your decceleration is constant, but even if it is linear, your speed will accomodate to your constraints.
If you want a non-linear decceleration, you could find some non-linear interpolation method, and interpolate not acceleration, but simply position between two points.
location = non_linear_function(time);
The four constraints you give are one too many for a linear system (one with constant acceleration), where any three of the variables would suffice to compute the acceleration and thereby determine the fourth variables. However, the system is way under-specified for a completely general nonlinear system -- there may be uncountably infinite ways to change acceleration over time while satisfying all the constraints as given. Can you perhaps specify better along what kind of curve acceleration should change over time?
Using 0 index to mean "at the start", 1 to mean "at the end", and D for Delta to mean "variation", given a linearly changing acceleration
a(t) = a0 + t * (a1-a0)/Dt
where a0 and a1 are the two parameters we want to compute to satisfy all the various constraints, I compute (if there's been no misstep, as I did it all by hand):
DV = Dt * (a0+a1)/2
Ds = Dt * (V0 + ((a1-a0)/6 + a0/2) * Dt)
Given DV, Dt and Ds are all given, this leaves 2 linear equations in the unknowns a0 and a1 so you can solve for these (but I'm leaving things in this form to make it easier to double check on my derivations!!!).
If you're applying the proper formulas at every step to compute changes in space and velocity, it should make no difference whether you compute a0 and a1 once and for all or recompute them at every step based on the remaining Dt, Ds and DV.
If you're trying to simulate a time-dependent acceleration in your equations, it just means that you should assume that. You have to integrate F = ma along with the acceleration equations, that's all. If acceleration isn't constant, you just have to solve a system of equations instead of just one.
So now it's really three vector equations that you have to integrate simultaneously: one for each component of displacement, velocity, and acceleration, or nine equations in total. The force as a function of time will be an input for your problem.
If you're assuming 1D motion you're down to three simultaneous equations. The ones for velocity and displacement are both pretty easy.
In real life, a car's stopping ability depends on the pressure on the brake pedal, any engine braking that's going on, surface conditions, and such: also, there's that "grab" at the end when the car really stops. Modeling that is complicated, and you're unlikely to find good answers on a programming website. Find some automotive engineers.
Aside from that, I don't know what you're asking for. Are you trying to determine a braking schedule? As in there's a certain amount of deceleration while coasting, and then applying the brake? In real driving, the time is not usually considered in these maneuvers, but rather the distance.
As far as I can tell, your problem is that you aren't asking for anything specific, which suggests that you really haven't figured out what you actually want. If you'd provide a sample use for this, we could probably help you. As it is, you've provided the bare bones of a problem that is either overdetermined or way underconstrained, and there's really nothing we can do with that.
if you need to go from 10m/s to 0m/s in 1m with linear acceleration you need 2 equations.
first find the time (t) it takes to stop.
v0 = initial velocity
vf = final velocity
x0 = initial displacement
xf = final displacement
a = constant linear acceleration
(xf-x0)=.5*(v0-vf)*t
t=2*(xf-x0)/(v0-vf)
t=2*(1m-0m)/(10m/s-0m/s)
t=.2seconds
next to calculate the linear acceleration between x0 & xf
(xf-x0)=(v0-vf)*t+.5*a*t^2
(1m-0m)=(10m/s-0m/s)*(.2s)+.5*a*((.2s)^2)
1m=(10m/s)*(.2s)+.5*a*(.04s^2)
1m=2m+a*(.02s^2)
-1m=a*(.02s^2)
a=-1m/(.02s^2)
a=-50m/s^2
in terms of gravity (g's)
a=(-50m/s^2)/(9.8m/s^2)
a=5.1g over the .2 seconds from 0m to 10m
Problem is either overconstrained or underconstrained (a is not constant? is there a maximum a?) or ambiguous.
Simplest formula would be a=(Vf-V0)/t
Edit: if time is not constrained, and distance s is constrained, and acceleration is constant, then the relevant formulae are s = (Vf+V0)/2 * t, t=(Vf-V0)/a which simplifies to a = (Vf2 - V02) / (2s).