I am writing some code to participate in an AI challenge. The main objective for the AI challenge is to take a simulated robot and navigate it through a maze to a destination zone. The secondary objective which is optional is to find a recharger placed in the maze at an unknown location. This is all done in a 2D grid.
My program can call a method to get a distance measurement from the recharger. So using trilateration I should be able to locate the recharger by calling this method, recording my ai's current position and the distance the recharger is away from that point 3 times over.
I found this example of trilateration on wikipedia http://en.wikipedia.org/wiki/Trilateration but this applies to a 3d space. I'm only dealing with a 2D space. Also I don't understand how to use the formula shown in Wikipedia, searching the web for a working example with numbers plugged in and boiling down to the final coordinates is scarce with Google searches.
I'm not a math major; I am just an enthusiast exploring AI problems.
An explanation and step by step example of how to calculate the problem is what I need as mathematics are not my strong point. Below is some sample data:
Point 1: x=39, y=28, distance=8
Point 2: x=13, y=39, distance=11
Point 3: x=16, y=40, distance=8
Any example using my sample data would be greatly appreciated. The programming to this will be very straight forward once I can wrap my head around the mathematics.
As the Wikipedia trilateriation article describes, you compute (x,y) coordinates by successively calculating: ex, i, ey, d, j, x, y. You have to be familiar with vector notation, so, for example, ex = (P2 - P1) / ‖P2 - P1‖ means:
ex,x = (P2x - P1x) / sqrt((P2x - P1x)2 + (P2y - P1y)2)
ex,y = (P2y - P1y) / sqrt((P2x - P1x)2 + (P2y - P1y)2)
Your data is:
P1 = (39, 28); r1 = 8
P2 = (13, 39); r2 = 11
P3 = (16, 40); r3 = 8
The calculation steps are:
ex = (P2 - P1) / ‖P2 - P1‖
i = ex(P3 - P1)
ey = (P3 - P1 - i · ex) / ‖P3 - P1 - i · ex‖
d = ‖P2 - P1‖
j = ey(P3 - P1)
x = (r12 - r22 + d2) / 2d
y = (r12 - r32 + i2 + j2) / 2j - ix / j
Related
it is my first time posting but I'll start by apologizing in advance if this question has been asked before.
I have been struggling on how to implement a 3rd order polynomial formula in C because of either extremely small values or larger than 32bit results (on a 16bit MCU).
I use diffrent values but as an example I would like to compute for "Y" in formula:
Y = ax^3 + bx^2 + cx + d = 0.00000012*(1024^3) + 0.000034*(1024^2) + 0.056*(1024) + 789.10
I need to use a base32 to get a meaningful value for "a" = 515
If I multiply 1024^3 (10bit ADC) then I get a very large amount of 1,073,741,824
I tried splitting them up into "terms A, B, C, and D" but I am not sure how to merge them together because of different resolution of each term and limitation of my 16bit MCU:
u16_TermA = fnBase32(0.00000012) * AdcMax * AdcMax * AdcMax;
u16_TermB = fnBase24(0.000034) * AdcMax * AdcMax;
u16_TermC = fnBase16(0.056) * AdcMax;
u16_TermD = fnBase04(789.10);
u16_Y = u16_TermA + u16_TermB + u16_TermC + u16_TermD;
/* AdcMax is a variable 0-1024; u16_Y needs to be 16bit */
I'd appreciate any help on the matter and on how best to implement this style of computations in C.
Cheers and thanks in advance!
One step toward improvement:
ax^3 + bx^2 + cx + d --> ((a*x + b)*x + c)*x + d
It is numerically more stable and tends to provide more accurate answers near the zeros of the function and less likely to overflow intermediate calculations.
2nd idea; consider scaling the co-efficents if they maintain their approximate relative values as given on the question.
N = 1024; // Some power of 2
aa = a*N*N*N
bb = b*N*N
cc = c*N
y = ((aa*x/N + bb)*x/N + cc)*x/N + d
where /N is done quickly with a shift.
With a judicious selection of N (maybe 2**14 for high precision avoid 32-bit overflow), then entire code might be satisfactorily done using only integer math.
As aa*x/N is just a*x*N*N, I think a scale of 2**16 works well.
Third idea:
In addition to scaling, often such cubic equations can be re-written as
// alpha is a power of 2
y = (x-root1)*(x-root2)*(x-root3)*scale/alpha
Rather than a,b,c, use the roots of the equation. This is very satisfactory if the genesis of the equation was some sort of curve fitting.
Unfortunately, OP's equation roots has a complex root pair.
x1 = -1885.50539
x2 = 801.08603 + i * 1686.95936
x3 = 801.08603 - i * 1686.95936
... in which case code could use
B = -(x1 + x2);
C = x1 * x2;
y = (x-x1)*(x*x + B*x + C)*scale/alpha
I would like to draw rounded area and points over a photo.
I decided to do it with a svg which is simplier to make it resizable and movable.
But, from a list of points I do not have an area which go through all points.
I used the Quadratic Bezier CurveTo, but I am not able to find the mathematic formula to give the the "Q parameter" the values to calculate the control point to go from A to C passing by B.
For the moment, when the angle is too high, the line "turn" before the point, but i would like to go touch the point.
There is infinite number of curves through point B.
Let define that B lies on the curve at parameter t=1/2
Quadratic curve with unknown control point Q has equation
P(t) = A*(1-t)^2 + 2*Q*t*(1-t) + C*t^2
Substiting point B and t=1/2, we have
B = A/4 + Q/2 + C/4
Q = 2*B - A/2 - C/2
or in coordinates
Q.x = 2*B.x - A.x/2 - C.x/2
Q.y = 2*B.y - A.y/2 - C.y/2
This very simple method should work well when B is near symmetrical relative to A and C
Q.x = 2*7 - 0 - 20/2 = 4
Q.y = 2*10 - 0 - 0 = 20
I have two points on a map -
val point1 : LatLng(13.3016139,77.4219107)
val point2 : LatLng(14.1788932,77.7613413)
I want to calculate and find 100 equidistant points along a straight line between these two coordinates. How do I do that?
ps. I'm sure this has been asked before, I just can't find it.
Equidistant, and more importantly, straight by which projection?
usually, to find a distance in cartesian space one would use something like the
Haversine formula to find a value, as previously answered in stack answer: How to convert latitude or longitude to meters?
As for the equidistant part, once you have the distance decided as per your taste of the shape and radius of Earth at given points, a simple division will do. .
python 3.7
>>> dist = 5427 #just some number
>>> nbr_o_points = 101
>>> points = [(dist/nbr_o_points)*(i+1) for i in range(nbr_o_points)]
>>> [f'{p:.2f}' for p in points]
['53.73', '107.47', '161.20',..., '5319.53', '5373.27', '5427.00']
Now to transfer these distances from point a to b back onto the desired projection... This is not part of your question... Stack - how-to-determine-vector-between-two-lat-lon-points might help.
take the vector and multiply by the dists in points in order to get your coordinates.
This is how I solved it -
fun findEquidistantPoints(latLng1: LatLng, latLng2: LatLng, pointCount: Int): ArrayList<LatLng> {
if (pointCount < 0)
throw IllegalArgumentException("PointCount cannot be less than 0")
val points = ArrayList<LatLng>()
val displacement = latLng1.displacementFromInMeters(latLng2)
val distanceBetweenPoints = displacement / (pointCount + 1)
for (i in 1..pointCount) {
val t = (distanceBetweenPoints * i) / displacement
points.add(LatLng(
(1 - t) * latLng1.latitude + t * latLng2.latitude,
(1 - t) * latLng1.longitude + t * latLng2.longitude
))
}
return points
}
I want to plot the temporal evolution of the factor of safety (FS, a quantification for the risk of landslides in a certain area).
This is calculated as follows:
effcohesion=0;
rootcohesion=0;
gammat=12.9E3;
gammaw=9810;
c=0;
deltac=0;
m=0.5;
z=2.5;
phi=16;
slope=rand(20,20)*30 % slope of a gridpoint in area
Strength = c + deltac + (gammat - gammaw.*m).*z.*(cosd(slope).^2);
Stress = gammat.*z.*(sind(slope)).*(cosd(slope));
Part = tand(phi);
FS2 = (Strength./Stress).*(Part)
Now. The value of m (= the height of the water table, which determines the FS) varies throughout the year and is thus not constant. I have a file with precipitation, evaporation, etc. data but to make it not too complicated, I here assume that m is just a function of the day of the year:
mnew=zeros(365,1);
for t=1:365
mnew(t)=(m+t)/150;
end
I now have a dataset with FS for 20x20 points where m =0.5 (=FS2) and a file with the evolution of m during the year (= mnew).
How can I now create a 3D matrix where (1) the spatial variation of FS is stored (so the values of FS over the 20x20 matrix) and (2) the temporal evolution of FS in function of m throughout the year. Eventually, I want a matrix that has both the spatial and temporal evolution of FS in it.
Layer 1 = FS at all 20x20 points on day 1
Layer 2 = FS at all 20x20 points on day 2
etc.
Can someone help me?
Thanks in advance!
A "3D matrix" would more properly be called a rank 3 array. To do this, just paste your FS2 calculation inside the time loop. Instead of m, use the appropriate mnew to calculate FS2. Then set that layer of FS3 (the rank 3 array) to FS2.
Then, layer 1 (day 1) is given by FS3(:,:,1), layer 2 by FS3(:,:,2), etc.
m0=0.5;
% Sizes of array
n1 = 20;
n2 = 20;
n3 = 365;
FS3 = zeros(n1, n2, n3);
mnew=zeros(n3,1);
for t=1:n3
mnew(t)=(m0+t)/150;
effcohesion=0;
rootcohesion=0;
gammat=12.9E3;
gammaw=9810;
c=0;
deltac=0;
m = mnew(t);
z=2.5;
phi=16;
slope=rand(n1,n2)*30; % slope of a gridpoint in area
Strength = c + deltac + (gammat - gammaw.*m).*z.*(cosd(slope).^2);
Stress = gammat.*z.*(sind(slope)).*(cosd(slope));
Part = tand(phi);
FS2 = (Strength./Stress).*(Part);
FS3(:,:,t) = FS2;
end
I need help with solving this problem. I have randomly generated points (example on Picture #1) and I want to connect them with lines (example on Picture #2). Lines can't be intersected and after connection, the connected points should look like an irregular area.
%Generating random points
xn = randi([3 7],1,10);
yn = randi([3 6],1,10);
%Generated points
xn = [6,3,7,7,6,6,6,4,6,3];
yn = [5,3,4,3,3,6,5,4,6,3];
Picture #1:
Result should be like this:
Picture #2:
Any idea how to solve this?
I suppose for the general case it can be very difficult to come up with a solution. But, assuming your points are scattered "nicely" there is quite a simple solution.
If you sort your points according to the angle above the x axis of the vector connecting the point and the center of the point cloud then:
P = [xn;yn]; %// group the points as columns in a matrix
c = mean(P,2); %// center point relative to which you compute the angles
d = bsxfun(#minus, P, c ); %// vectors connecting the central point and the dots
th = atan2(d(2,:),d(1,:)); %// angle above x axis
[st si] = sort(th);
sP = P(:,si); %// sorting the points
And that's about it. To plot the result:
sP = [sP sP(:,1)]; %// add the first point again to close the polygon
figure;plot( sP(1,:), sP(2,:), 'x-');axis([0 10 0 10]);
This algorithm will fail if several points has the same angle w.r.t the center of the point cloud.
An example with 20 random points:
P = rand(2,50);
You could adapt the code from another answer I gave for generating random simple polygons of an arbitrary number of sides. The difference here is you already have your set of points chosen and thus implicitly the number of sides you want (i.e. the same as the number of unique points). Here's what the code would look like:
xn = [6,3,7,7,6,6,6,4,6,3]; % Sample x points
yn = [5,3,4,3,3,6,5,4,6,3]; % Sample y points
[~, index] = unique([xn.' yn.'], 'rows', 'stable'); % Get the unique pairs of points
x = xn(index).';
y = yn(index).';
numSides = numel(index);
dt = DelaunayTri(x, y);
boundaryEdges = freeBoundary(dt);
numEdges = size(boundaryEdges, 1);
while numEdges ~= numSides
if numEdges > numSides
triIndex = vertexAttachments(dt, boundaryEdges(:,1));
triIndex = triIndex(randperm(numel(triIndex)));
keep = (cellfun('size', triIndex, 2) ~= 1);
end
if (numEdges < numSides) || all(keep)
triIndex = edgeAttachments(dt, boundaryEdges);
triIndex = triIndex(randperm(numel(triIndex)));
triPoints = dt([triIndex{:}], :);
keep = all(ismember(triPoints, boundaryEdges(:,1)), 2);
end
if all(keep)
warning('Couldn''t achieve desired number of sides!');
break
end
triPoints = dt.Triangulation;
triPoints(triIndex{find(~keep, 1)}, :) = [];
dt = TriRep(triPoints, x, y);
boundaryEdges = freeBoundary(dt);
numEdges = size(boundaryEdges, 1);
end
boundaryEdges = [boundaryEdges(:,1); boundaryEdges(1,1)];
x = dt.X(boundaryEdges, 1);
y = dt.X(boundaryEdges, 2);
And here's the resulting polygon:
patch(x,y,'w');
hold on;
plot(x,y,'r*');
axis([0 10 0 10]);
Two things to note:
Some sets of points (like the ones you chose here) will not have a unique solution. Notice how my code connected the top 4 points in a slightly different way than you did.
I made use of the TriRep and DelaunayTri classes, both of which may be removed in future MATLAB releases in favor of the delaunayTriangulation class.