I have a space with obstacles I wish to find a path through. What I can do is discretize the space into a grid and use A* (or D* or whatever) to find a path through it. I wish to now add orientation to the algorithm. So the node location now becomes a 3d vector (x, y, phi). You can go from one node to another one only if they belong to an arc (both positions are on a circle and are oriented along the tangent lines). How do I discretize the space so that angles don't explode in a sense that by traversing the graph, the set of possible angles becomes finite?
Thanks.
As I understand it, your challenge is not to discretize coordinate, but to discretize the headings. I had to do the same thing in a grid world that allowed movement in eight directions, i.e. horizontal, vertical and diagonal. Your discretized space should match the problem domain. For your consideration:
4-directions: use a square grid with movement across edges
8-directions use a square grid with movement across edges and vertices
6-directions use a hexagonal grid with movement across edges
12-directions use a hexagonal grid with movement across edges and points
... and so on.
To actually get the discretized headings, I declared an enum called Direction:
public enum Direction {
North,
NorthEast,
East,
SouthEast,
South,
SouthWest,
West,
NorthWest;
//additional code below...
}
You can lookup the correct heading by first computing the XY-offset between the current position and goal position:
int dx = currentPosition.x - goalPosition.x;
int dy = currentPosition.y - goalPosition.y;
These were passed to the getInstance(int,int) method (below) to obtain the correct Direction:
public static Direction getInstance(int dx, int dy) {
int count = Direction.values().length;
double rad = Math.atan2(dy, dx); // In radians
double degree = rad * (180 / Math.PI) + 450;
return getInstance(((int) Math.round(((degree % 360) / (360 / count)))) % count);
}
public static Direction getInstance(int i) {
return Direction.values()[i % Direction.count];
}
In effect, these methods compute the heading in degrees and rounds to the nearest Direction. You can then implement a method that moves/turns the agent in the the Direction heading, e.g. agent.turnToward(Direction d) or agent.move(Direction d).
Additional Resources:
Hexagon grids: http://www.redblobgames.com/grids/hexagons/#distances
Representing grids with graphs: http://www.redblobgames.com/pathfinding/grids/algorithms.html
Pathfinding with A*: http://theory.stanford.edu/~amitp/GameProgramming/
Angles can be prevented from blowing up by ensuring that phi is considered to be modulo 2pi, that is, phi = phi + 2pi*k for any integer value of k.
In C like syntax, you might end up updating phi with fmod.
phi = fmod(phi + deltaphi, 2*pi)
Where deltaphi is the change in angle you're introducing (in radians).
The most common way to do this is to constrain the values of the angle phi to take on one of n discrete angles which also has the advantage of avoiding precision/rounding issues. Given that you know phi can only take on one of n values, you can treat it like an integer, and map the value to a real when necessary.
i = (i + deltai) % n
phi = (2*i*pi)/n)
Where your change in angle deltai is (2*deltai*pi)/n radians.
However, finding a good discretization is only part of the solution - it defines a representation of your configuration space, but as you've pointed out, you also need to consider what a valid transition is.
The simplest approach to integrate angles into planning is to require rotations and translations to be distinct (at any time you can do one or the other, but not both), or to be composable (always translate, and then on arriving instantaneously rotate).
Moving forward and or backward at the same time while you're turning introduces is more complex, and tends to not work particularly well with discrete lattices - it tends to require some model of the vehicle you're working with. The most common are the simple nonholonomic models - the forward only car (the Dubins' car) or the car with forward / reverse (the Reeds Shepp car) - your reference to tangents to circles, I'm guessing this is what you're after. Dubins-Curves, or similar libraries can be used to build libraries of possible paths that could be combined with an A* (or D*) planner.
Differentially Constrained Mobile Robot Motion Planning in State Lattices by Mihail Pivtoraiko, Ross A. Knepper and Alonzo Kelly has some striking images of what's possible.
Related
How can I draw filled elliptical sector using Bresenham's algorithm and bitmap object with DrawPixel method?
I have written method for drawing ellipse, but this method uses symmetry and passes only first quadrant. This algorithm is not situable for sectors. Of course, I can write 8 cycles, but I think it's not the most elegant solution of the task.
On integer math the usual parametrization is by using limiting lines (in CW or CCW direction) instead of your angles. So if you can convert those angles to such (you need sin,cos for that but just once) then you can use integer math based rendering for this. As I mentioned in the comment bresenham is not a good approach for a sector of ellipse as you would need to compute the internal iterators and counters state for the start point of interpolation and also it will give you just the circumference points instead of filled shape.
There are many approaches out there for this here a simple one:
convert ellipse to circle
simply by rescaling the smaller radius axis
loop through bbox of such circle
simple 2 nested for loops covering the outscribed square to our circle
check if point inside circle
simply check if x^2 + y^2 <= r^2 while the circle is centered by (0,0)
check if point lies between edge lines
so it should be CW with one edge and CCW with the other. You can exploit the cross product for this (its z coordinate polarity will tell you if point is CW or CCW against the tested edge line)
but this will work only up to 180 deg slices so you need also add some checking for the quadrants to avoid false negatives. But those are just few ifs on top of this.
if all conditions are met conver the point back to ellipse and render
Here small C++ example of this:
void elliptic_arc(int x0,int y0,int rx,int ry,int a0,int a1,DWORD c)
{
// variables
int x, y, r,
xx,yy,rr,
xa,ya,xb,yb, // a0,a1 edge points with radius r
mx,my,cx,cy,sx,sy,i,a;
// my Pixel access (you can ignore it and use your style of gfx access)
int **Pixels=Main->pyx; // Pixels[y][x]
int xs=Main->xs; // resolution
int ys=Main->ys;
// init variables
r=rx; if (r<ry) r=ry; rr=r*r; // r=max(rx,ry)
mx=(rx<<10)/r; // scale from circle to ellipse (fixed point)
my=(ry<<10)/r;
xa=+double(r)*cos(double(a0)*M_PI/180.0);
ya=+double(r)*sin(double(a0)*M_PI/180.0);
xb=+double(r)*cos(double(a1)*M_PI/180.0);
yb=+double(r)*sin(double(a1)*M_PI/180.0);
// render
for (y=-r,yy=y*y,cy=(y*my)>>10,sy=y0+cy;y<=+r;y++,yy=y*y,cy=(y*my)>>10,sy=y0+cy) if ((sy>=0)&&(sy<ys))
for (x=-r,xx=x*x,cx=(x*mx)>>10,sx=x0+cx;x<=+r;x++,xx=x*x,cx=(x*mx)>>10,sx=x0+cx) if ((sx>=0)&&(sx<xs))
if (xx+yy<=rr) // inside circle
{
if ((cx>=0)&&(cy>=0)) a= 0;// actual quadrant
if ((cx< 0)&&(cy>=0)) a= 90;
if ((cx>=0)&&(cy< 0)) a=270;
if ((cx< 0)&&(cy< 0)) a=180;
if ((a >=a0)||((cx*ya)-(cy*xa)<=0)) // x,y is above a0 in clockwise direction
if ((a+90<=a1)||((cx*yb)-(cy*xb)>=0))
Pixels[sy][sx]=c;
}
}
beware both angles must be in <0,360> range. My screen has y pointing down so if a0<a1 it will be CW direction which matches the routione. If you use a1<a0 then the range will be skipped and the rest of ellipse will be rendered instead.
This approach uses a0,a1 as real angles !!!
To avoid divides inside loop I used 10 bit fixed point scales instead.
You can simply divide this to 4 quadrants to avoid 4 if inside loops to improve performance.
x,y is point in circular scale centered by (0,0)
cx,cy is point in elliptic scale centered by (0,0)
sx,sy is point in elliptic scale translated to ellipse center position
Beware my pixel access is Pixels[y][x] but most apis use Pixels[x][y] so do not forget to change it to your api to avoid access violations or 90deg rotation of the result ...
I want to simulate particles driven by wind on a three.js globe. The data I have is a Vector3 for the position of a particle and a Vector2 indicating wind speed and direction, think North/East. How do I get the new Vector3?
I've consulted numerous examples and read the documentation and believe the solution involves quaternions, but the axis of rotation is not given. Also, there are thousands of particles, it should be fast, however real-time is not required.
The radius of the sphere is 1.
I would recommend you have a look at the Spherical class provided by three.js. Instead of cartesian coordinates (x,y,z), a point is represented in terms of a spherical coordinate-system (θ (theta), φ (phi), r).
The value of theta is the longitude and phi is the latitude for your globe (r - sphereRadius would be the height above the surface). Your wind-vectors can then be interpreted as changes to these two values. So what I would try is basically this:
// a) convert particle-location to spherical
const sphericalPosition = new THREE.Spherical()
.setFromVector3(particle.position);
// b) update theta/phi (note that windSpeed is assumed to
// be given in radians/time, but for a sphere of size 1 that
// shouldn't make a difference)
sphericalPosition.theta += windSpeed.x; // east-direction
sphericalPosition.phi += windSpeed.y; // north-direction
// c) write back to particle-position
particle.position.setFromSpherical(sphericalPosition);
Performance wise this shouldn't be a problem at all (maybe don't create a new Spherical-instance for every particle like I did above). The conversions involve a bit of trigonometry, but we're talking just thousands of points, not millions.
Hope that helps!
If you just want to rotate a vector based on an angle, just perform a simple rotation of values on the specified plane yourself using trig as per this page eg for a rotation on the xz plane:
var x = cos(theta)*vec_to_rotate.x - sin(theta)*vec_to_rotate.z;
var z = sin(theta)*vec_to_rotate.x + cos(theta)*vec_to_rotate.z;
rotated_vector = new THREE.Vector3(x,vec_to_rotate.y,z);
But to move particles with wind, you're not really rotating a vector, you should be adding a velocity vector, and it 'rotates' its own heading based on a combination of initial velocity, inertia, air friction, and additional competing forces a la:
init(){
position = new THREE.Vector(0,0,0);
velocity = new THREE.Vector3(1,0,0);
wind_vector = new THREE.Vector3(0,0,1);
}
update(){
velocity.add(wind_vector);
position.add(velocity);
velocity.multiplyScalar(.95);
}
This model is truer to how wind will influence a particle. This particle will start off heading along the x axis, and then 'turn' eventually to go in the direction of the wind, without any rotation of vectors. It has a mass, and a velocity in a direction, a force is acting on it, it turns.
You can see that because the whole velocity is subject to friction (the multscalar), our initial velocity diminishes as the wind vector accumulates, which causes a turn without performing any rotations. Thought i'd throw this out just in case you're unfamiliar with working with particle systems and maybe were just thinking about it wrong.
So I am making a program, where you can have two objects (circles). I want them to orbit like planets around each other, but only in 2D.
I know that using Newtons Universal Law of Gravitation I can get the force between the two objects. I also know A = F / M. My question is how would I take the A from the previous equation and change it into a vector?
You need to use vector equations:
// init values (per object)
double ax=0.0,ay=0.0,az=0.0; // acceleration [m/s^2]
double vx=0.0,vy=0.0,vz=0.0; // velocity [m/s]
double x=0.0, y=0.0, z=0.0; // position [m]
double m=1.0; // mass [kg]
// iteration inside some timer (dt [seconds] period) ...
int i; double a,dx,dy,dz; // first compute acceleration
for (ax=0.0,ay=0.0,az=0.0,i=0;i<obj.num;i++)
if (obj[i]!=this) // ignore gravity from itself
{
dx=obj[i].x-x;
dy=obj[i].y-y;
dz=obj[i].z-z;
a=sqrt((dx*dx)+(dy*dy)+(dz*dz)); // a=distance to obj[i]
a=6.67384e-11*(obj[i].m*m)/(a*a*a); // a=acceleration/distance to make dx,dy,dz unit vector
ax+=a*dx; // ax,ay,az = actual acceleration vector (integration)
ay+=a*dy;
az+=a*dz;
}
vx+=ax*dt; // update speed via integration of acceleration
vy+=ay*dt;
vz+=az*dt;
x+=vx*dt; // update position via integration of velocity
y+=vy*dt;
z+=vz*dt;
Code is taken from here
obj[] is list of all your objects
obj.num is the count of them
I recommend to create object class with all the variables inside (ax,ay,az,...m), init them once and then continuously update (iteration) in some timer. If you want more accuracy then you should compute ax,ay,az for all objects first and only after update speed and position (to avoid change of position of objects during gravity computation). If you want to drive an object (like with truster) then just add its acceleration to ax,ay,az vector)
Now to setup an orbit just:
place planet object
must be massive enough and also set its position / velocity to what you want
place satellite
Initial position should be somewhere near planet. It should not be too massive. Init also speed vector with tangent direction to orbiting trajectory. If speed is too low it will collapse into planet and if speed is too high it will escape from planet otherwise will be orbiting (circle or ellipse)
timer
lower the interval better the simulation usually 10ms is OK but for massive and far objects is also 100ms and more OK. If you want particles or something then use 1ms (very dynamic sceene).
I strongly recommend to read this related QA:
Is it possible to make realistic n-body solar system simulation in matter of size and mass?
especially [edit3] about the integration precision and creating orbital data.
With two objects you are probably best using an ellipse which is the path the objects will follow about their common center of mass. Read Kepler's laws of planetary motion which gives the background.
If one object is a much greater mass than the other, i.e. a sun and a planet you can have one stationary and the other taking an elliptical path. The equation of the ellipse is given by
r = K e / ( 1 + e cos(theta))
K is a constant giving the size and e is the eccentricity. If you want an elliptical orbit have 0 < e < 1 the smaller it is the more circular the orbit. To get x, y coordinates from this use, x = r cos(theta), y = r sin(theta). The missing bit is time and how the angle is dependant on time. This is where the second and third laws come in. If a and b are the semi-major and semi-minor lengths of the ellipse, and P is the period then
0.5 * P * r^2 theta'= pi a b
theta' is the rate of change of angle with respect to time (d theta/d t). You can use this to get how much theta will change given a increase in time. First work out the current radius r0 given the current angle th0 if the time increment is δt then the angle increment δtheta is
δtheta = 2 pi * a * b / r^2 * δt
and the next angle is th0 + δtheta.
If the masses are of similar magnitude then see two body problem. Both objects will have elliptical orbits, there are two patterns which you can see in animations on that page. The ellipses will follow the same formula as above with the focus at the common center of mass.
If you have three object things get considerably harder and there are not generally neat solutions. See three body problem for this.
I was wondering if the following algorithm to check if a point is inside a rectangle is valid.
I've developed it using my own intuition (no strong trig/math basis to support it), so I'd love to hear from someone with more experience in the matter.
Context:
The rectangle is defined with 4 points. It could be rotated.
Coordinates are always positive.
By definition, the point is considered inside the rectangle if intersects it.
Hypothesis:
Use the distance between the point and the rectangle vertices (first diagram below).
The maximum possible total distance is when the point is in one vertex (second diagram).
If the point is just outside the rectangle, the distance will be greater (third diagram).
Diagram link: http://i45.tinypic.com/id6o35.png
Algorithm (Java):
static boolean pointInsideRectangle(Point[] rect, Point point) {
double maxDistance = distance(rect[0], rect[1]);
maxDistance += distance(rect[0], rect[2]);
maxDistance += distance(rect[0], rect[3]);
double distance = 0;
for (Point rectPoint : rect) {
distance += distance(rectPoint, point);
if (distance > maxDistance) return false;
}
return true;
}
Questions: is this correct?
Short answer: NO :P (don´t fell bad about it)
Long Answer: Intersecction the areas from the four circles that you mention (max distance between opposite vertex) does not produce a rectangle.
Since I´m a bit rusty in geometry I can´t give full mathematical explanation (time constrain for my part), but give you some pseudocode of the procedure with the constrains that you ask (no fancy formulae), valid for any rectangle the wikipeida or a geometry book can fill the gaps.
Find the N,E,S,W vertex (the uppermost, rightmost, lowest and leftmost vertex) this is trivially easy for any rectangle but the axis aligned who can produce oddly assignation of the vertex (see images with examples)
Find the NE, SE, SW and NW border, this is the line equation in wikipedia or another link, again should be easy, but the axis aligned border should be analized carefully because those generate another type of ecuation/restriction.
Check if your point is on the "right side" of the border see inequality as mathematical term, only a point inside your rectangle satisfy the four restrictions as you can see in the image attached.
my apologies if I have overlook some command of java.geom that can accomplish this task
I hope this help with your endevour
You can try this.Lets name the point we have as A.Draw a line between A and every point of the rectangle.After that you get 4 different triangles.Calculate the area the triangles are taking(using Heron's formula) and compare it to the area of the rectangle.If the areas are the same then your point is inside the rectangle.
Cheers
Okay I'm working on a Space sim and as most space sims I need to work out where the opponents ship will be (the 3d position) when my bullet reaches it. How do I calculate this from the velocity that bullets travel at and the velocity of the opponents ship?
Calculate the relative velocity vector between him and yourself: this could be considered his movement if you were standing still. Calculate his relative distance vector. Now you know that he is already D away and is moving V each time unit. You have V' to calculate, and you know it's length but not it's direction.
Now you are constructing a triangle with these two constraints, his V and your bullet's V'. In two dimensions it'd look like:
Dx+Vx*t = V'x*t
Dy+Vy*t = V'y*t
V'x^2 + V'y^2 = C^2
Which simplifies to:
(Dx/t+Vx)^2 + (Dy/t+Vx)^2 = C^2
And you can use the quadratic formula to solve that. You can apply this technique in three dimensions similarly. There are other ways to solve this, but this is just simple algebra instead of vector calculus.
Collision Detection by Kurt Miller
http://www.gamespp.com/algorithms/collisionDetection.html
Add the negative velocity of the ship to the bullet, so that only the bullet moves. Then calculate the intersection of the ship's shape and the line along which the bullet travels (*pos --> pos + vel * dt*).
The question probably shouldn't be "where the ship will be when the bullet hits it," but IF the bullet hits it. Assuming linear trajectory and constant velocity, calculate the intersection of the two vectors, one representing the projectile path and another representing that of the ship. You can then determine the time that each object (ship and bullet) reach that point by dividing the distance from the original position to the intersection position by the velocity of each. If the times match, you have a collision and the location at which it occurs.
If you need more precise collision detection, you can use something like a simple BSP tree which will give you not only a fast way to determine collisions, but what surface the collision occurred on and, if handled correctly, the exact 3d location of the collision. However, it can be challenging to maintain such a tree in a dynamic environment.