Rollercoaster simulation in matlab/javascript - javascript

I'm having problem with a project that I'm working on in matlab which i'm then going to implement using javascript. The purpose is to use matlab to get a better understanding of the physics before moving over to javascript. The goal is to create some sort of a Rollercoaster simulation in matlab using differential equations and euler aproximation. Then to animate a block(cart) following the path.
The problem is that I can't get the approximation working on a arbitary path (equation), and I don't understand what I'm doing wrong.
So this is what i'm trying to do:
for t=1:h:tf
%acceleration
ax(i) = (g*cos((-pi/4)))*sin(-pi/4)-((C*ro*A*vx(i)^2*sign(vx(i)))/(2*m))*sin(-pi/4);
ay(i) = (g*cos((-pi/4)))*cos(-pi/4)+((C*ro*A*vy(i)^2*sign(vy(i)))/(2*m))*cos(-pi/4);
%speed
vx(i+1) = vx(i)+h*ax(i);
vy(i+1) = vy(i)+h*ay(i);
%position
x(i+1) = x(i)+h*vx(i);
y(i+1) = y(i)+h*vy(i);
i = i+1;
speed = sqrt(vx(i)^2+vy(i)^2);
plot(x(i),y(i),'or')
pause(1/speed)
end
Where i'm following Newtons second law (F=ma => a = F/m) the only negative force component i'm using now is air resistance.
This is when i'm using a hardcoded path -> y=1-x, and it's working just fine!
But when i try to use an arbitary path, eg. 1/x, the angle is changed all the time, and i've tried things like putting each angle into an angle vector:
%% initial values
vx(1) = 0;
vy(1) = 0;
x(1) = 0;
y(1) = 6.7056;
%Track Geometry Constants
h_start = 6.7056;
l_end = 32;
b = .055;
w = .7;
p = .3;
%% Creating path
path_x = linspace(0, 23, 1000);
path_y = (exp(-b*path_x).*(cos(w*path_x - p)) + 2.2*(exp(-(b)*path_x)));
path_y = path_y*(h_start/max(path_y));
path_x = path_x*(l_end/max(path_x));
%%
alpha = zeros(size(path_y));
for k=1:1:size(path_y)-1
alpha(j) = atan(path_y(k+1)-path_y(k))/(path_x(k+1)-path_x(k));
j= j+1;
end
But this doesn't appear to work.
How can I make this work for an arbitrary path?
Thank you in advance!

There is a pretty simple error in your loop. Two errors, actually.
You are indexing alpha with a variable, j, that doesn't exist and increment it in the loop, instead of just using k, which increments automatically in the loop.
The reason this isn't giving an error is that your loop never runs. Because the size of path_y is not a single number, (the size is 1 x 1000), k=1:1:size(path_y)-1 tries to create a loop that goes from 1 to 0 in steps of positive 1. Since this isn't possible, the loop is skipped. One option is to use length, not size here.
But the most important error: you didn't check your code line by line when it stopped working to confirm that every part of your code was doing what you thought it was when you wrote it. If you'd checked what k=1:1:size(path_y)-1 was outputting, you should have been able to identify this problem very quickly.
Incidentally I think you can avoid the loop entirely (append a zero at the end if you really need this to have the same size as the path variables):
alpha = atan(diff(path_y)./diff(path_x));

Related

Optimize animation with javascript assigning value

I am building an animation with lots of effects and animation in a website. I am trying to optimize the efficiency of those animations since some of them are a little complex to low CPU/RAM devices. The animations are not smooth as I want as you can see here https://www.empresasite.com.br
So I realize in many parts of my code I do this:
var x = 38; //this value changes every 50ms
document.getElementById("a").style.left = document.getElementById("b").style.left = document.getElementById("c").style.left = document.getElementById("d").style.left = document.getElementById("e").style.left = x + "px";
Actually it's a simplification above, I run the code above with at least 13 elements a = b = c = d .... m = x; and at least with 4 properties (left, height, box-shadow and background-color).
So I was wondering if there is any better alternative to assign the same value to multiple elements/objects at once?
Maybe the code below would be faster? I used it but I didnt see a significant improvement in animation, maybe I should have seen it?
var x = 38;
x = x + "px";
document.getElementById("a").style.left = x;
document.getElementById("b").style.left = x;
document.getElementById("c").style.left = x;
document.getElementById("d").style.left = x;
document.getElementById("e").style.left = x;
I think the code above should be faster right? I say this cause every element updates its own property (left) retrieving the value from "x". In the first example I gave MAYBE javascript is assigning the value of the previous element in the chain of "=" sign so it has to assign "x" to the first element then assign the value of the first element to the second... go on.
Do you know exactly what jquery does when I use this:
$(".elements").css({left:x});
Does it use some optimization?
You could increase performance no-end by using translate instead of modifying position.
Using the jQuery variation you asked will not make any difference, as you are still modifying position left.
After playing around with most of the javascript benchmarking tools online I came up to this conclusion:
1) Jquery is the faster method of all native js solutions I used. Maybe Jquery uses some sort of optimization when you apply the same property to lots of elements at once! So you should rely on $(".class").css("left",x) to apply the x value to left property for hundreds of elements and it will be the faster solution;
2) The second solution is apply x individually TO EACH element. Example:
var x = 38;
document.getElementById("a").style.left = x;
document.getElementById("b").style.left = x;
3) The worst solution was actually the one I was using in the website that I was facing not smooth animations. So avoid this:
document.getElementById("a").style.left = document.getElementById("b").style.left = ... = ... = x;
The difference from the 1st solution to the 3rd is really noticeable. You can check it in the links below (pay special attention to the animation at the top):
1) https://www.empresasite.com.br/?q=principal&before -> this is using the 3rd solution
2) https://www.empresasite.com.br/?q=principal -> this is using the 1st solution
In a computer with lots of resources you may not see a difference but if you run this in a computer with 4GB of RAM or less you will see a big impact!
Hope this helps anyone that does not have smooth animations!

Is it possible to convert A string that is an equation with a variable into a equation?

I need to convert a string returned from prompt into an equation, however the parseFloat returns as only the first number, and symbols in an equation, and stops at the variable. The variable will always = x. The program is designed to convert an algebraic expression say 15*x(5^4-56)*17/x=15 into an expression, and calculate the value of x. If someone could show me how to do this, it would help dramatically. I am currently using multiple prompts, having the user put in the equation before x, then the equation after x, then it inserts a variable in between the two, and calculates it's value.
Edit:
I have no variables predefined, and it must work in equations where x > 1000, or x != //an integer.
Thanks in advance!
Seems to be a complex problem...
This is a solution for a simple relaxed version of your problem. Hope you can use some components of this.
Constraints:
answer for x should be integers between 0 and 1000
the left hand side of the expression should be proper javascript syntax
var input = prompt("enter the equation"); //eg: x*x+x+1=241
var parts = input.split('=');
//solving equation starts
var x = 0;
var temp = eval(parts[0]);
while (temp != parts[1] && x<1000){
x++;
temp = eval(parts[0]);
}
var ans = (x<1000)?"answer is "+x:"this program cannot solve this";
//solving equation finishes
alert(ans);
You can replace the "solving equation" part with some numerical methods used in computer science to solve equations (more details here) . You will have to parse the left side of equation and map them to proper javascript expressions (as a string to execute with eval()) if you want to allow users to use your syntax.
Javascript can evaluate strings using the eval function, but the variable as to be defined before hand, and the equation has to be formatted in way that javascript can understand:
var x = 15
var string = "15*x*17/x"
eval(string)
Your example: "15*x(5^4-56)*17/x=15" would not run however, because it would evaluate x(5^4-56) as a javascript expression, which is invalid.
Using all the info, and other mehtods I found about this, I have put together a communinty answer. Anyone is invited to change and/or add their methods to this.
In order to do this with the least work possible for the user and coder, you would implement the following code.
var input = prompt("enter the equation"); //eg: x*x+x+1=241
var parts = input.split('=');
//solving equation starts
var x = 0; //Or the lowest possible value of "x"
var temp = eval(parts[0]);
while (temp != parts[1] && x<1000){ // && x < The highest number to evaluate
x++; //Add the increment (determines the maximum amount of digits) eg x+0.1 for tenths max, x+2 for only even integers etc.
temp = eval(parts[0]);
}
var ans = (x<1000)?"answer is "+x:"this program cannot solve this"; //make sure x< is the same as line 7.
//solving equation finishes
alert(ans);
But, this runs very slowly if you allow tenths, or a range larger than 2000.`
A faster way of running this would be to define arrays allowing any variable (instead of just x) and a different eveulation process such as here. (do the right click view html and click on the first js source to see code) but, this is 2k lines. Both are usable, but the second is more efficient, and can solve multivariate equations.

Better random function in JavaScript

I'm currently making a Conway's Game of Life reproduction in JavaScript and I've noticed that the function Math.random() is always returning a certain pattern. Here's a sample of a randomized result in a 100x100 grid:
Does anyone knows how to get better randomized numbers?
ApplyRandom: function() {
var $this = Evolution;
var total = $this.Settings.grid_x * $this.Settings.grid_y;
var range = parseInt(total * ($this.Settings.randomPercentage / 100));
for(var i = 0; i < total; i++) {
$this.Infos.grid[i] = false;
}
for(var i = 0; i < range; i++) {
var random = Math.floor((Math.random() * total) + 1);
$this.Infos.grid[random] = true;
}
$this.PrintGrid();
},
[UPDATE]
I've created a jsFiddle here: http://jsfiddle.net/5Xrs7/1/
[UPDATE]
It seems that Math.random() was OK after all (thanks raina77ow). Sorry folks! :(. If you are interested by the result, here's an updated version of the game: http://jsfiddle.net/sAKFQ/
(But I think there's some bugs left...)
This line in your code...
var position = (y * 10) + x;
... is what's causing this 'non-randomness'. It really should be...
var position = (y * $this.Settings.grid_x) + x;
I suppose 10 was the original size of this grid, that's why it's here. But that's clearly wrong: you should choose your position based on the current size of the grid.
As a sidenote, no offence, but I still consider the algorithm given in #JayC answer to be superior to yours. And it's quite easy to implement, just change two loops in ApplyRandom function to a single one:
var bias = $this.Settings.randomPercentage / 100;
for (var i = 0; i < total; i++) {
$this.Infos.grid[i] = Math.random() < bias;
}
With this change, you will no longer suffer from the side effect of reusing the same numbers in var random = Math.floor((Math.random() * total) + 1); line, which lowered the actual cell fillrate in your original code.
Math.random is a pseudo random method, that's why you're getting those results. A by pass i often use is to catch the mouse cursor position in order to add some salt to the Math.random results :
Math.random=(function(rand) {
var salt=0;
document.addEventListener('mousemove',function(event) {
salt=event.pageX*event.pageY;
});
return function() { return (rand()+(1/(1+salt)))%1; };
})(Math.random);
It's not completly random, but a bit more ;)
A better solution is probably not to randomly pick points and paint them black, but to go through each and every point, decide what the odds are that it should be filled, and then fill accordingly. (That is, if you want it on average %20 percent chance of it being filled, generate your random number r and fill when r < 0.2 I've seen a Life simulator in WebGL and that's kinda what it does to initialize...IIRC.
Edit: Here's another reason to consider alternate methods of painting. While randomly selecting pixels might end up in less work and less invocation of your random number generator, which might be a good thing, depending upon what you want. As it is, you seem to have selected a way that, at most some percentage of your pixels will be filled. IF you had kept track of the pixels being filled, and chose to fill another pixel if one was already filled, essentially all your doing is shuffling an exact percentage of black pixels among your white pixels. Do it my way, and the percentage of pixels selected will follow a binomial distribution. Sometimes the percentage filled will be a little more, sometimes a little less. The set of all shufflings is a strict subset of the possibilities generated this kind of picking (which, also strictly speaking, contains all possibilities for painting the board, just with astronomically low odds of getting most of them). Simply put, randomly choosing for every pixel would allow more variance.
Then again, I could modify the shuffle algorithm to pick a percentage of pixels based upon numbers generated from a binomial probability distribution function with a defined expected/mean value instead of the expected/mean value itself, and I honestly don't know that it'd be any different--at least theoretically--than running the odds for every pixel with the expected/mean value itself. There's a lot that could be done.
console.log(window.crypto.getRandomValues(new Uint8Array(32))); //return 32 random bytes
This return a random bytes with crypto-strength: https://developer.mozilla.org/en/docs/Web/API/Crypto/getRandomValues
You can try
JavaScript Crypto Library (BSD license). It is supposed to have a good random number generator. See here an example of usage.
Stanford JavaScript Crypto Library (BSD or GPL license). See documentation for random numbers.
For a discussion of strength of Math.random(), see this question.
The implementation of Math.random probably is based on a linear congruential generator, one weakness of which is that a random number depends on the earlier value, producing predictable patterns like this, depending on the choice of the constants in the algorithm. A famous example of the effect of poor choice of constants can be seen in RANDU.
The Mersenne Twister random number generator does not have this weakness. You can find an implementation of MT in JavaScript for example here: https://gist.github.com/banksean/300494
Update: Seeing your code, you have a problem in the code that renders the grid. This line:
var position = (y * 10) + x;
Should be:
var position = (y * grid_x) + x;
With this fix there is no discernible pattern.
You can using the part of sha256 hash from timestamp including nanoseconds:
console.log(window.performance.now()); //return nanoseconds inside
This can be encoded as string,
then you can get hash, using this: http://geraintluff.github.io/sha256/
salt = parseInt(sha256(previous_salt_string).substring(0, 12), 16);
//48 bits number < 2^53-1
then, using function from #nfroidure,
write gen_salt function before, use sha256 hash there,
and write gen_salt call to eventListener.
You can use sha256(previous_salt) + mouse coordinate, as string to get randomized hash.

Web Audio: Karplus Strong String Synthesis

Edit: Cleaned up the code and the player (on Github) a little so it's easier to set the frequency
I'm trying to synthesize strings using the Karplus Strong string synthesis algorithm, but I can't get the string to tune properly. Does anyone have any idea?
As linked above, the code is on Github: https://github.com/achalddave/Audio-API-Frequency-Generator (the relevant bits are in strings.js).
Wiki has the following diagram:
So essentially, I generate the noise, which then gets output and sent to a delay filter simultaneously. The delay filter is connected to a low-pass filter, which is then mixed with the output. According to Wikipedia, the delay should be of N samples, where N is the sampling frequency divided by the fundamental frequency (N = f_s/f_0).
Excerpts from my code:
Generating the noise (bufferSize is 2048, but that shouldn't matter too much)
var buffer = context.createBuffer(1, bufferSize, context.sampleRate);
var bufferSource = context.createBufferSource();
bufferSource.buffer = buffer;
var bufferData = buffer.getChannelData(0);
for (var i = 0; i < delaySamples+1; i++) {
bufferData[i] = 2*(Math.random()-0.5); // random noise from -1 to 1
}
Create a delay node
var delayNode = context.createDelayNode();
We need to delay by f_s/f_0 samples. However, the delay node takes the delay in seconds, so we need to divide that by the samples per second, and we get (f_s/f_0) / f_s, which is just 1/f_0.
var delaySeconds = 1/(frequency);
delayNode.delayTime.value = delaySeconds;
Create the lowpass filter (the frequency cutoff, as far as I can tell, shouldn't affect the frequency, and is more a matter of whether the string "sounds" natural):
var lowpassFilter = context.createBiquadFilter();
lowpassFilter.type = lowpassFilter.LOWPASS; // explicitly set type
lowpassFilter.frequency.value = 20000; // make things sound better
Connect the noise to the output and the delay node (destination = context.destination and was defined earlier):
bufferSource.connect(destination);
bufferSource.connect(delayNode);
Connect the delay to the lowpass filter:
delayNode.connect(lowpassFilter);
Connect the lowpass to the output and back to the delay*:
lowpassFilter.connect(destination);
lowpassFilter.connect(delayNode);
Does anyone have any ideas? I can't figure out whether the issue is my code, my interpretation of the algorithm, my understanding of the API, or (though this is least likely) an issue with the API itself.
*Note that on Github, there's actually a Gain Node between the lowpass and the output, but this doesn't really make a big difference in the output.
Here's what I think is the problem. I don't think the DelayNode implementation is designed to handle such tight feedback loops. For a 441 Hz tone, for example, that's only 100 samples of delay, and the DelayNode implementation probably processes its input in blocks of 128 or more. (The delayTime attribute is "k-rate", meaning changes to it are only processed in blocks of 128 samples. That doesn't prove my point, but it hints at it.) So the feedback comes in too late, or only partially, or something.
EDIT/UPDATE: As I state in a comment below, the actual problem is that a DelayNode in a cycle adds 128 sample frames between output and input, so that the observed delay is 128 / sampleRate seconds longer than specified.
My advice (and what I've begun to do) is to implement the whole Karplus-Strong including your own delay line in a JavaScriptNode (now known as a ScriptProcessorNode). It's not hard and I'll post my code once I get rid of an annoying bug that can't possibly exist but somehow does.
Incidentally, the tone you (and I) get with a delayTime of 1/440 (which is supposed to be an A) seems to be a G, two semitones below where it should be. Doubling the frequency raises it to a B, four semitones higher. (I could be off by an octave or two - kind of hard to tell.) Probably one could figure out what's going on (mathematically) from a couple more data points like this, but I won't bother.
EDIT: Here's my code, certified bug-free.
var context = new webkitAudioContext();
var frequency = 440;
var impulse = 0.001 * context.sampleRate;
var node = context.createJavaScriptNode(4096, 0, 1);
var N = Math.round(context.sampleRate / frequency);
var y = new Float32Array(N);
var n = 0;
node.onaudioprocess = function (e) {
var output = e.outputBuffer.getChannelData(0);
for (var i = 0; i < e.outputBuffer.length; ++i) {
var xn = (--impulse >= 0) ? Math.random()-0.5 : 0;
output[i] = y[n] = xn + (y[n] + y[(n + 1) % N]) / 2;
if (++n >= N) n = 0;
}
}
node.connect(context.destination);

Why does my my gravity work in this?

http://davzy.com/gameA/
I can't figure out a smart way to get gravity. Now with this it detects which block the character is over but it does't drop to that block!
Is there a better way to do gravity? I'd like to do this without a game library.
I don't know what you mean by "get gravity"; your question is unclear. I assume that if you can detect when the block is over, you can use the following formula:
s(t) = ut + 1/2at2
Where s is the distance at time t, u is the initial velocity (which in your case would be zero), and a is the acceleration (on Earth this is 9.8m/s2). Essentially you would be adjusting the top position of your object based on the value you get at time t (so original top position of object + s(t)). I would imagine you would use some sort of animation loop. Perhaps a setInterval. Maybe others with more experience in Javascript animation can chime in about the best way to implement this. However, this would be the formula that you would be using to figure out where the object is at time t, if it falls.
Basically gravity in a platformer goes like this:
var currentGrav = 0.0;
var gravAdd = 0.5; // add this every iteration of the game loop to currentGrav
var maxGrav = 4.0; // this caps currentGrav
var charPosY = getCharPosY(); // vertical position of the character, in this case the lower end
var colPosY = getColDow(); // some way to get the vertical position of the next "collision"
for(var i = 0; i < Math.abs(Math.ceil(currentGrav)); i++) { // make sure we have "full pixel" values
if (charPosY == colPosY) {
onGround = true;
break; // we hit the ground
}
onGround = false;
charPosY++;
}
Now to jump one could simply do this:
if (jumpKeyPressed && onGround) {
currentGrav = -5.0; //
}
You can, if you want(and understand C), check out my game for a basic platformer(with moving platforms) here:
http://github.com/BonsaiDen/Norum/blob/master/sources/character.c

Categories

Resources