MATLAB loop-index issue [closed] - arrays

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 6 years ago.
Improve this question
Context: I must create a program that describes the motion of a car being tested for a quarter-mile time as part of a performance analysis. This involves time, distance, velocity, acceleration, forces, torque, and rotational speed.
In the last for loop I get the following error with whatever line of code is at the top (in this example the engine torque):
"Attempted to access RPM(2); index out of bounds because numel(RPM)=1."
clear all
close all
clc
time(1) = 0; %[seconds]
dist(1) = 0;
vel(1) = 0;
accel(1) = 0;
RPMmin = 1200;
RPM(1) = RPMmin;
r = 19; %[inches]
wt = 3760; %[pounds]
Ng = [3.253, 2.233, 1.611, 1.243, 1, 0.629]; %{Gear Ratio}
Nd = [3.73]; %differential ratio
dt = 0.1; %time increment
for k = 1:1:6
xntt(k) = Ng(k) * Nd;
xmf(k) = 1 + (0.04 * xntt(k)) + (0.0025 * xntt(k)^2);
gst = 0.25; %gear shift time
end
for i = 1:1:1000
Te(i) = 18.154 + (.1571 * RPM(i)) - (0.0000147 * (RPM(i))^2);
fx(i) = Te(i) * xntt(k)/(r/12);
dV(i + 1) = (32.2/(wt * xmf(k)))*fx(i);
accel(i + 1) = dV(i)/dt;
vel(i + 1) = vel(i) + (dV(i) * dt);
dist(i + 1) = dist(i) + vel(i + 1)*dt;
time(i + 1) = time(i) + dt;
RPM(i) = (vel(i + 1)*60*xntt(k))/((2*pi*r)/12);
end

This happens when i=2 inside the for-loop (second iteration). Depending on RPM, you basically have two choices:
let Te(i) depend on RPM(i-1), so Te(2) will depend on RPM(1) and so on. This will, however, throw an error when i=1 due to the fact that if i=1, then i-1=0 and Matlab allows only positive indices so you need to place an if check inside the loop.
let RPM grow just like Te, so if at iteration i you're writing on Te(i+1), write as well on RPM(i+1).
Both of these approaches lead to a code with no errors (i.e. syntactically correct) but then you must choose the correct approach depending on what your problem is and how such vectors are sort of "linked" together (i.e. your code must be semantically correct as well).

Related

How to optimize valve simulation logic? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
This is an simple logic-programming and optimisation etude, that I've created for myself, and somewhat stumbled upon it.
I have a numerical simulation of simple scheme. Consider some reservoir (or a capacitor) Cm, which is constantly pumping up with pressure. Lets call its current state Vm:
At its output it has a valve, or a gate, G, that could be open or closed, according to following logic:
Gate opens, when pressure(or voltage) Vm exceeds some threshold, call it Vopen: Vm > Vopen
Gate remains open, while current outrush Ia is greater than some Ihold: Ia > IHold
Gate conducts power only out of reservoir (like a diode)
I am doing numerical ODE solving of this, i.e. determining Vm and Ia at each (equal, small) timestep dt. Have three variants of this:
Variable types:
float Vm=0.0, Ia=0.0, Vopen, Ihold, Ra, dt;
int G=0;
Loop body v1 (serial):
Vm = Vm + (-Ia*G)*dt;
G |= (Vm > Vopen);
Ia = Ia + (Vm*Ra*G)*dt;
G &= (Ia > Ihold);
Loop body v2 (serial, with temp var, ternary conditionals):
int Gv; // temporary var
Vm = Vm + (-Ia*G)*dt;
Gv = (Vm > Vopen) ? 1 : G;
Ia = Ia + (Vm*Ra*Gv)*dt;
G = (Ia > Ihold) ? Gv : 0;
Loop body v3 (parallel, with cache):
// cache new state first
float Vm1 = Vm + (-Ia*G)*dt;
float Ia1 = Ia + (Vm*Ra*G)*dt;
// update memory
G = ( Vm1 > Vopen ) || (( Ia1 > Ihold ) && G);
Vm = Vm1;
Ia = Ia1; // not nesesary to cache, done for readibility
the G was taken from building up the following truth table, plus imagination:
Q:
Which is correct? Are they?
How third variant(parallel logic) differs from first two(serial logic)?
Are there more effective ways of doing this logic?
PS. I am trying to optimize it for SSE, and then (separately) for OpenCL (if that gives optimisation hints)
PPS. For those who is curious, here is my working simulator, involving this gate (html/js)
By the overall description they are the same and should all fulfil your needs.
Your serial code will produce half-steps. That means if you break it down to the discrete description V(t) can be described as being 1/2 dt in front of I(t). The fist one will keep G changing in every half-step and the second one will synchronise it to I. But since you are not evaluating G in between in doesn't really matter. There is also no real problem with V and I being a half step apart but you should keep it in mind but maybe you should use for plotting/evaluation the vector {V(t),(I(t-1)+I(t))/2,G(t)}.
The parallel code will keep them all in the same time step.
For your pure linear problem the direct integration is a good solution. Higher order ode solver won't buy you anything. State-space representation for pure linear systems only write the same direct integration in a different way.
For SIMD optimisation there isn't munch to do. You need to evaluate step-wise since you are updating I by V and V by I. That means you can't run the steps in parallel which makes many interesting optimisation not possible.

My if and else if are running at the same time [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
I've got a program measuring distance from a rocket to the moon, so when the distance is >250, only the if runs. However when the else runs and the distance <=250, the if continues to run while the else runs. If anyone can help me fix it I would be very thankful.
do
{
if (distance >250)
{
time += 1;
y_pos = initial_y_pos - (vel_y * time)/2;
x_pos = initial_x_pos + (vel_x * time)/2;
//Sets the new x and y position when time is flowing so the rocket can move
GFX_DrawLineTo(x_pos, y_pos, 3);
GFX_UpdateDisplay();
distance = sqrt(pow((y_pos-(y+312)),2)+(pow((x_pos-(x+440)),2)));
mars_dist = sqrt(pow((y_pos-150),2)+pow((x_pos-1150),2));
//distance calculation from the rocket to the moon. Needed for sphere of influence
printf("%f\n",distance);
}
else if (distance <=250)
{
y_pos = initial_y_pos - ((vel_y * time) - ((gravity * time)/2));
x_pos = initial_x_pos + ((vel_x * time) - ((gravity * time)/2));
GFX_DrawLineTo(x_pos, y_pos, 3);
GFX_UpdateDisplay();
distance = sqrt(pow((y_pos-(y+312)),2)+(pow((x_pos-(x+440)),2)));
mars_dist = sqrt(pow((y_pos-150),2)+pow((x_pos-1150),2));
//printf("%f\n",distance);
printf("%f\n", x_pos);
}
if (distance <= 50)
//If the rocket either hits moon or mars, this is responsible for recognising that
{
printf("Unlucky! Your rocket crashed into the moon!");
return 0;
}
}
//while (distance > 250);
while ((0 <= x_pos && x_pos <= 1280) || (0 <= y_pos && y_pos <= 1024));
when the else runs and the distance <=250, the if continues to run while the else runs
ok, you mean distance <=250 then the next while turn distance>250
This happens when the computed speed/covered distance is too high and the rocket crosses Mars to be on the other side far than 250 (or the rocket enter inside Mars ?) after the delay time, that means you have to change
y_pos = initial_y_pos - ((vel_y * time) - ((gravity * time)/2));
x_pos = initial_x_pos + ((vel_x * time) - ((gravity * time)/2));
...
distance = sqrt(pow((y_pos-(y+312)),2)+(pow((x_pos-(x+440)),2)));
mars_dist = sqrt(pow((y_pos-150),2)+pow((x_pos-1150),2));
to decrease the speed/covered distance in that case if it is too high. Or may be the speed/covered distance is correct but the rocket reaches the surface or Mars in less than time, so the new position is incorrect and impossible because that supposes the rocket can cross the surface of Mars, you have to detect that case.

Meltdown PoC Detailed Code Review [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
I read all the week-end about Meltdown and Spectre
I also have already read the .pdfs for Spectre and Meltdown
which are Must Read for anyone seeking more knowledge about these exploits but unfortunately don't provide detailed explanations on the code.
I found various PoC on github, which were very interesting but I lack the knowledge to fully understand it. I would be thanksful about more explanation on specific parts:
From this link https://github.com/dendisuhubdy/meltdown/blob/master/src/poc.c , and other git repositories as well, there are many interesting parts in the conception of this exploit.
Time reads
/* Time reads. Order is lightly mixed up to prevent stride prediction */
for (i = 0; i < 256; i++) {
mix_i = ((i * 167) + 13) & 255;
addr = &array2[mix_i * 512];
time1 = __rdtscp(&junk); /* READ TIMER */
junk = *addr; /* MEMORY ACCESS TO TIME */
time2 = __rdtscp(&junk) - time1; /* READ TIMER & COMPUTE ELAPSED TIME */
if (time2 <= CACHE_HIT_THRESHOLD && mix_i != array1[tries % array1_size])
results[mix_i]++; /* cache hit - add +1 to score for this value */
}
why do we use prime numbers 167 and 13 ?
/* Locate highest & second-highest results results tallies in j/k */
Why do we care about getting the max value ?
Other parts explanations are very welcome as well !!

Configuring and limiting output of PI controller

I have implemented simple PI controller, code is as follows:
PI_controller() {
// handling input value and errors
previous_error = current_error;
current_error = 0 - input_value;
// PI regulation
P = current_error //P is proportional value
I += previous_error; //I is integral value
output = Kp*P + Ki*I; //Kp and Ki are coeficients
}
Input value is always between -π and +π.
Output value must be between -4000 and +4000.
My question is - how to configure and (most importantly) limit the PI controller properly.
Too much to comment but not a definitive answer. What is "a simple PI controller"? And "how long is a piece of string"? I don't see why you (effectively) code
P = (current_error = 0 - input_value);
which simply negates the error of -π to π. You then aggregate the error with
I += previous_error;
but haven't stated the cumulative error bounds, and then calculate
output = Kp*P + Ki*I;
which must be -4000 <= output <= 4000. So you are looking for values of Kp and Ki that keep you within bounds, or perhaps don't keep you within bounds except in average conditions.
I suggest an empirical solution. Try a series of runs, filing the results, stepping the values of Kp and Ki by 5 steps each, first from extreme neg to pos values. Limit the output as you stated, counting the number of results that break the limit.
Next, halve the range of one of Kp and Ki and make a further informed choice as to which one to limit. And so on. "Divide and conquer".
As to your requirement "how to limit the PI controller properly", are you sure that 4000 is the limit and not 4096 or even 4095?
if (output < -4000) output = -4000;
if (output > 4000) output = 4000;
To configure your Kp and Ki you really should analyze the frequency response of your system and design your PI to give the desired response. To simply limit the output decide if you need to freeze the integrator, or just limit the immediate output. I'd recommend freezing the integrator.
I_tmp = previous_error + I;
output_tmp = Kp*P + Ki*I_tmp;
if( output_tmp < -4000 )
{
output = -4000;
}
else if( output_tmp > 4000 )
{
output = 4000;
}
else
{
I = I_tmp;
output = output_tmp;
}
That's not a super elegant, vetted algorithm, but it gives you an idea.
If I understand your question correctly you are asking about anti windup for your integrator.
There are more clever ways to to it, but a simple
if ( abs (I) < x)
{
I += previous_error;
}
will prevent windup of the integrator.
Then you need to figure out x, Kp and Ki so that abs(x*Ki) + abs(3.14*Kp) < 4000
[edit] Off cause as macduff states, you first need to analyse your system and choose the korrect Ki and Kp, x is the only really free variable in the above equation.

Noise cancellation setup - combining the microphone's signals intelligently [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I built a noise cancellation setup with two microphones and two different microphone preamplifiers that go to two different channels of a stereo recording.
Here is a sample
http://filestore.to/?d=U5FN2IH96K
I tried
char ergebnis[80];
sprintf(ergebnis, "%s.neu.raw", Datei);
FILE* ausgabe = fopen(ergebnis, "wb");
FILE* f = fopen(Datei, "rb");
if (f == NULL)
{
return;
}
int i = -1;
int r1 = 0;
int r2 = 0;
int l1 = 0;
int l2 = 0;
int l = 0;
int r = 0;
int wo = 0;
int dif = 0;
while (wo != EOF)
{
wo = getc(f);
i++;
if (i == 0)
{
r1 = (unsigned)wo;
}
if (i == 1)
{
r2 = (unsigned)wo;
r = (r2 << 8) + r1; //r1 | r2 << 8;
}
if (i == 2)
{
l1 = (unsigned)wo;
}
if (i == 3)
{
l2 = (unsigned)wo;
l = (l2 << 8) + l1; //l1 | l2 << 8;
dif = r - (l * 2);
putc((char)( (unsigned)dif & 0xff), ausgabe);
putc((char)(((unsigned)dif >> 8) & 0xff), ausgabe);
i = -1;
}
}
when the magic happens in
dif = r - (l * 2);
But this does not eliminate the noise surrounding it, all it does is create crackling sounds.
How could I approach this task with my setup instead? I prefer practical solutions over "read this paper only the author of the paper understands".
While we are at it, how do I normalize the final mono output to make it as loud as possible without clipping?
I don't know why you would expect this
dif = r - (l * 2);
to cancel noise, but I can tell you why it "create[s] crackling sounds". The value in dif is often going to be out of range of 16-bit audio. When this happens, your simple conversion function:
putc((char)( (unsigned)dif & 0xff), ausgabe);
putc((char)(((unsigned)dif >> 8) & 0xff), ausgabe);
will fail. Instead of a smooth curve, your audio will jump from large positive to large negative values. If that confuses you, maybe this post will help.
Even if you solve that problem, a few things aren't clear, not the least of which is that for active noise canceling to work you usually assume that one mike provides a source of noise and the other provides signal + noise. Which is which in this case? Did you just place two mikes next to each other and hope to hear some sound source with less ambient noise after some simple arithmetic? That won't work, since they are both hearing different combinations of signal and noise (not just in amplitude, but time as well). So you need to answer 1. which mike is the source of signal and which is the source of noise? 2. what kind of noise are you trying to cancel? 3. what distinguishes the mikes in their ability to hear signal and noise? 4. etc.
Update: I'm still not clear on your setup, but here's something that might help:
You might have a setup where your signal is strong in one mike and weak in the other, and a noise is applied to both mikes. In all likelyhood, there will be signal leak into both mikes. Nevertheless, we will assume
l = noise1
r = signal + noise2
Note that I have not assumed the same noise values for l and r, this reflects the reality that the two mikes will be picking up different noise values due to time delays and other factors. However, it is often the case (and may or may not be the case in your setup) that noise1 and noise2 are correlated at low frequencies. Thus, if we have a low pass filter, lp, we can achieve some noise reduction in the low frequencies as follows:
out = r - lp(l) = signal + noise2 - lp(noise1)
This, of course, assumes that the noise level at l and r is the same, which it may or may not be, depending on your setup. You may want to leave a manual parameter for this purpose for manual tuning at the end:
out = r - g*lp(l)
where g is your tuning parameter and close to 1. I believe in some high-end noise reduction systems, g is constantly tuned automatically.
Selecting a cutoff frequency for your lp filter is all that remains. An approximation you could use is that the highest frequency you can cancel has a wavelength equal to 1/4 the distance between the mikes. Of course, I'm REALLY waving my arms with that, because it depends a lot on where the sound is coming from, how directional your mikes are and so on, but it's a starting point.
Sample calculation for mikes that are 3 inches apart:
Speed of sound = 13 397 inches / sec
desired wavelength = 4*3 inches = 12 inches
frequency = 13,397 / 12 = 1116 Hz
So your filter should have a cutoff frequency of 1116 Hz if the mikes are 3 inches apart.
Expect this setup to cancel a significant amount of your signal below the cutoff frequency as well, if there is bleed.

Resources