Trying to calculate TDOA (Time Difference Of Arrival) but I can’t get my head around it. Can someone please help me with an clear and simple example.
I have 3 microphone located at:
X0 = 0 cm
Y0 = 0 cm
-
X1 = 0 cm
Y1 = 15 cm
-
X2 = 0 cm
Y2 = 30 cm
Time different of sound arrive to the 3 microphone:
A0 = 0 sec
A1 = 0.002 sec
A2 = 0.004 sec
Speed of sound:
S = 340 m/sec
Updated after response from wessel
I am trying to make a script calc TDOA
let ? = (Y1 - Y0) / (S); // = 0.00044
let ? = (Y2 - Y0) / (S); // = 0.00088
let VX = (X1 - X0) / A0; // = NaN
let VY = (Y1 - Y0) / A0; // = Infinity
let V = Math.sqrt(VX^2 + VY^2) // = 1.4142
let alpha = atan(VY / VX) // = NaN
console.log(alpha+' deg with the x-axis.');
If you have a distance and a speed (distance / time), you get a time by doing distance / speed = distance / (distance / time ) = distance / distance * time = time.
What you omit in your question, is the direction and the shape of the sound wave. If the sound is traveling along the x-axis, the shape does not matter, and the time difference would be:
(A1 - A0) = (X1 - X0) / (340 m/s) = 0.15 / 340 s = 0.00044 s
(A2 - A0) = (X2 - X0) / (340 m/s) = 0.3 / 340 s = 0.00088 s
If the shape is a straight line, e.g. from an infinitely far point source or from a particularly shaped non-point source, the different of arrival time is given by the x-component of the direction of the sound wave:
VX = (X1 - X0) / (A1 - A0) = 37.5 m/s.
The total sound speed, which you give as 340 m/s, should equal
V = Sqrt(VX^2 + VY^2)
such that you can work out that
VY = Sqrt(V^2 - VX^2) = 338 m/s
or
VY = -Sqrt(V^2 - VX^2) = -338 m/s
such that your sound wave must in incoming under an angle alpha:
alpha = atan(VY / VX) = 83 deg
with the x-axis.
I don't see why javascript is relevant here, though. Just in case: use Math.sqrt, Math.pow or V*V, and Math.atan or Math.atan2 (beware of the order of the arguments there!).
Related
Referring to the first diagram, I am trying to copy the three objects, looking at them from an arbitrary angle(A1). The distance between where I'm and the first object does not matter just the relative location of the object to one another.
In the second diagram, I select a point to copy these objects, facing another arbitrary angle(B1).
Angle (C1) shows the approximate position of -90 degrees.
I can get this to work if A1 = 0,90,180,270 and even 45,135 etc but the equations I come up with only work for 0 and 180 or 90 and 270. I have to modify them to work in those directions by changing a hardcoded offset angle and putting/removing a negative sign before the offset.
I'm doing this is javascript (and its Minecraft) usually I can figure out this but I have been working on it for weeks.
Here is some pseudo-code that works some of the time in certain right-angle directions. I have updated this to be more accurate, the 1x and 2x are the blocks x coordinate, etc. - everything is relative from the (1) block.
Minecraft's coordinate system is a little different from normal - 0 is south, +90 is west, 180 is north, 270 is east.
the only difference is that I am making negative az, ax.
// works for north/south looking - A1 is either 180/0 , B1 can be anything
var x = 1x - 2x;
var z = 1z - 2z;
var direction = Math.atan2(z1, x1);
var L1 = Math.sqrt(Math.pow(x1, 2) + Math.pow(z1, 2));
var az = Math.round(L1 * Math.sin((B1 + A1 + (direction * 180 / Math.PI)) * Math.PI / 180));
var ax = Math.round(L1 * Math.cos((B1 + A1 + (direction * 180 / Math.PI)) * Math.PI / 180));
// works for east/west looking - A1 is either 90/270 , B1 can be anything
var x = 1x - 2x;
var z = 1z - 2z;
var direction = Math.atan2(z1, x1);
var L1 = Math.sqrt(Math.pow(x1, 2) + Math.pow(z1, 2));
var az = -Math.round(L1 * Math.sin((B1 + A1 + (direction * 180 / Math.PI)) * Math.PI / 180));
var ax = -Math.round(L1 * Math.cos((B1 + A1 + (direction * 180 / Math.PI)) * Math.PI / 180));
First diagram
Second diagram
I started a project using the raycasting technique GitHub Project
To find the length of the ray (distance from players pos to wall) I just increment by one. But there are several problems with that, its time consuming, inaccurate & will be difficult for texturing.
I tried to implement the daa algorithm, which doesnt just increments by 1 -> he goes through the grids and returns exact positions.
http://www.geeksforgeeks.org/dda-line-generation-algorithm-computer-graphics/
Has anyone experience with that or any tips?
No algorithm way:
for(let resolution = 0; resolution < display.width / 2; resolution++){ //every 2nd px gets scanned
let ray = this.pov + (-this.fov / 2 + this.fov / (display.width / 2) * resolution);
let distance = 0, hit = false;
/*ugly way of raycasting!*/
do{
let x = this.x + distance * Math.cos(ray * (Math.PI / 180));
let y = this.y + distance * Math.sin(ray * (Math.PI / 180));
if(map[Math.floor(x / block)][Math.floor(y / block)]){
distance = Math.sqrt(Math.pow(this.x - x, 2) + Math.pow(this.y - y, 2));
hit = true
}
distance += 1;
}while(!hit);
distance = convert / distance;
canvas.fillStyle = "#fff";
canvas.fillRect(resolution * 2, display.height / 2 - distance / 2, 2, distance);
}
You don't need DDA or Bresenham algorithm to find intersections of the ray with walls.
If you need one intersection with given border (or box edges) - just calculate it with ray equation and border position.
If you want to get intersections with grid cells - use voxelization algorithm like Amanatides-Woo
I have a function which gets the mouse position in world space, then checks to see if the mouse is over or near to the circle's line.
The added complication how ever is the circle is transformed at an angle so it's more of an ellipse. I can't see to get the code to detect that the mouse is near the border of circle and am unsure where I am going wrong.
This is my code:
function check(evt){
var x = (evt.offsetX - element.width/2) + camera.x; // world space
var y = (evt.offsetY - element.height/2) + camera.y; // world space
var threshold = 20/scale; //margin to edge of circle
for(var i = 0; i < obj.length;i++){
// var mainAngle is related to the transform
var x1 = Math.pow((x - obj[i].originX), 2) / Math.pow((obj[i].radius + threshold) * 1,2);
var y1 = Math.pow((y - obj[i].originY),2) / Math.pow((obj[i].radius + threshold) * mainAngle,2);
var x0 = Math.pow((x - obj[i].originX),2) / Math.pow((obj[i].radius - threshold) * 1, 2);
var y0 = Math.pow((y - obj[i].originY),2) / Math.pow((obj[i].radius - threshold) * mainAngle, 2);
if(x1 + y1 <= 1 && x0 + y0 >= 1){
output.innerHTML += '<br/>Over';
return false;
}
}
output.innerHTML += '<br/>out';
}
To understand it better, I have a fiddle here: http://jsfiddle.net/nczbmbxm/ you can move the mouse over the circle, it should say "Over" when you are within the threshold of being near the circle's perimeter. Currently it does not seem to work. And I can't work out what the maths needs to be check for this.
There is a typo on line 34 with orignX
var x1 = Math.pow((x - obj[i].orignX), 2) / Math.pow((obj[i].radius + threshold) * 1,2);
should be
var x1 = Math.pow((x - obj[i].originX), 2) / Math.pow((obj[i].radius + threshold) * 1,2);
now you're good to go!
EDIT: In regards to the scaling of the image and further rotation of the circle, I would set up variables for rotation about the x-axis and y-axis, such as
var xAngle;
var yAngle;
then as an ellipse can be written in the form
x^2 / a^2 + y^2 / b^2 = 1
such as in Euclidean Geometry,
then the semi-major and semi-minor axes would be determined by the rotation angles. If radius is the circles actual radius. then
var semiMajor = radius * cos( xAngle );
var semiMinor = radius;
or
var semiMajor = radius;
var semiMinor = radius * cos( yAngle );
you would still need to do some more transformations if you wanted an x and y angle.
so if (xMouseC, yMouseC) are the mouse coordinates relative to the circles centre, all you must do is check if that point satisfies the equation of the ellipse to within a certain tolerance, i.e. plug in
a = semiMajor;
b = semiMinor;
x = xMouseC;
y = yMouseC;
and see if it is sufficiently close to 1.
Hope that helps!
Yes theres a few threads on this, but not many using angles and I'm really trying to figure it out this way,
I'm now stuck on setting the new velocity angles for the circles. I have been looking at:
http://www.hoomanr.com/Demos/Elastic2/
as a reference to it, but I'm stuck now.
Can anybody shed some light?
cx/cy/cx2/cy2 = center x/y for balls 1 and 2.
vx/vy/vx2/vy2 = velocities for x/y for balls 1 and 2
function checkCollision() {
var dx = cx2 - cx; //distance between x
var dy = cy2 - cy; // distance between y
var distance = Math.sqrt(dx * dx + dy * dy);
var ang = Math.atan2(cy - cy2, cx - cx2);
// was displaying these in a div to check
var d1 = Math.atan2(vx, vy); //ball 1 direction
var d2 = Math.atan2(vx2, vy2); //ball 2 direction
// this is where I am stuck, and i've worked out this is completely wrong now
// how do i set up the new velocities for
var newvx = vx * Math.cos(d1 - ang);
var newvy = vy * Math.sin(d1 - ang);
var newvx2 = vx2 * Math.cos(d2 - ang);
var newvy2 = vy2 * Math.sin(d2 - ang);
if (distance <= (radius1 + radius2)) {
//Set new velocity angles here at collision..
}
Heres a codepen link:
http://codepen.io/anon/pen/MwbMxX
A few directions :
• As mentioned in the comments, use only radians (no more *180/PI).
• atan2 takes y as first param, x as second param.
var d1 = Math.atan2(vy, vx); //ball 1 direction in angles
var d2 = Math.atan2(vy2, vx2); //ball 2 direction in angles
• to rotate a vector, compute first its norm, then only project it with the new angle :
var v1 = Math.sqrt(vx*vx+vy*vy);
var v2 = Math.sqrt(vx2*vx2+vy2*vy2);
var newvx = v1 * Math.cos(d1 - ang);
var newvy = v1 * Math.sin(d1 - ang);
var newvx2 = v2 * Math.cos(d2 - ang);
var newvy2 = v2 * Math.sin(d2 - ang);
• You are detecting the collision when it already happened, so both circles overlap, but you do NOT solve the collision, meaning the circles might still overlap on next iteration, leading to a new collision and a new direction taken, ... not solved, etc..
-->> You need to ensure both circles are not colliding any more after you solved the collision.
• Last issue, but not a small one, is how you compute the angle. No more time for you sorry, but it would be helpful both for you and us to build one (several) scheme showing how you compute the angles.
Updated (but not working) codepen here :
http://codepen.io/anon/pen/eNgmaY
Good luck.
Edit :
Your code at codepen.io/anon/pen/oXZvoe simplify to this :
var angle = Math.atan2(dy, dx),
spread = minDistance - distance,
ax = spread * Math.cos(angle),
ay = spread * Math.sin(angle);
vx -= ax;
vy -= ay;
vx2 += ax;
vy2 += ay;
You are substracting the gap between both circles from the speed. Since later you add the speed to the position, that will do the spatial separation (=> no more collision).
I think to understand what vx-=ax means, we have to remember newton : v = a*t, where a is the acceleration, so basically doing vx=-ax means applying a force having the direction between both centers as direction, and the amount by which both circle collided (spread) as intensity. That amount is obviously quite random, hence the numerical instability that you see : sometimes a small effect, sometimes a big one.
look here for a constant punch version :
http://codepen.io/anon/pen/WvpjeK
var angle = Math.atan2(dy, dx),
spread = minDistance - distance,
ax = spread * Math.cos(angle),
ay = spread * Math.sin(angle);
// solve collision (separation)
cx -= ax;
cy -= ay;
// give a punch to the speed
var punch = 2;
vx -= punch*Math.cos(angle);
vy -= punch*Math.sin(angle);
vx2 += punch*Math.cos(angle);
vy2 += punch*Math.sin(angle);
I am trying to approximate the position of the sun in XYZ for a threejs project.
I am following the maths found here: http://en.wikipedia.org/wiki/Position_of_the_Sun
Following the above, I have written the following Javascript code:
var n = ((2440587.5 + (this.datemillis / 8.64E7)) - 2451545);
var L = 280.460 + 0.9856474 * n;
var g = 357.528 + 0.9856003 * n;
L = (L + 360) % 360;
g = (g + 360) % 60;
var lambda = L + 1.915 * Math.sin(g) + 0.0020 * Math.sin(2 * g);
var r = 1.00014 - 0.01671 * Math.cos(g) - 0.00014 * Math.cos(2 * g);
var e = 23.439 - 0.0000004 * n;
var x = (r * this.constants.EARTH_RADIUS * 2) * Math.cos(lambda);
var y = (r * this.constants.EARTH_RADIUS * 2) * Math.cos(e) * Math.sin(lambda);
var z = (r * this.constants.EARTH_RADIUS * 2) * Math.sin(e) * Math.sin(lambda);
this.datemillis is returned by the getMillisecond function of the Javascript date object. It is updated each frame so that time advances at about 1 hour every 2 seconds.
However something must not be correct as this does not produce the expected result. When I apply the computed x y z coordinates to my sun in my threejs project, I can see the sun rotate around the earth (sitting in 0,0,0) but at a very slow rate (rotating the earth in a few days instead of 24 hours).
I'm thinking it might have something to do with the angle calculations that I'm not doing correctly (degrees/radians?) but I'm not very good at maths so I don't really know what I'm doing so maybe I just misinterpreted the Wiki calculations.
If somebody could spot something obvious I'm doing wrong and help me fix this, would be greatly appreciated!
Thanks
EDIT: so my sun currently is not rotating around the earth in a continous way - it rotates clockwise/counterclockwise alternatively and sometimes jumps positions...
I suggest this to get the Julian Date, from Calculating Jday(Julian Day) in javascript
var today = Date();
var JD = Math.floor((today / 86400000) - (today.getTimezoneOffset()/1440) + 2440587.5);
Add to JD the desired amount of days and increment that value at the desired speed. Note that if you add 1 day each millisecond you'll get 1000 days per second, not 1 hour every 2 seconds.
JD += offset;
Then go on with the wikipedia recipe:
var n = JD - 2451545;
//...
To put L and g in the range 0-360 (you have an error here) use
L = L % 360 + ( L < 0 ? 360 : 0 );
g = g % 360 + ( g < 0 ? 360 : 0 );
The wikipedia formulas express angles in degrees. However JavaScript trigonometric functions cos and sin expect radians.
Just write a "degrees" version of them:
function cosD( deg ) {
return Math.cos( deg * Math.PI / 180.0 );
}
function sinD( deg ) {
return Math.sin( deg * Math.PI / 180.0 );
}
Then use sinD() and cosD() in subsequent calculations.
var r = 1.00014 - 0.01671 * cosD(g) - 0.00014 * cosD(2 * g);
var e = 23.439 - 0.0000004 * n;
var x = (r * this.constants.EARTH_RADIUS * 2) * cosD(lambda);
var y = (r * this.constants.EARTH_RADIUS * 2) * cosD(e) * sinD(lambda);
var z = (r * this.constants.EARTH_RADIUS * 2) * sinD(e) * sinD(lambda);
I cannot answer your question but I do know this is a solved problem in threejs. There is an example running in an architecture/engineering workflow on Github on this topic. The sun position code is here https://github.com/radio412/viewer/blob/gh-pages/sun-position.js
You can see it being tapped for a directional light in threejs at line 108 here: https://github.com/radio412/viewer/blob/gh-pages/va3c-viewer.js