I have a few ordered points (less than 10) in 2D coordinates system.
I have an agent moving in the system and I want to find the shortest path between those points following their order.
For background the agent can be given a position to go to with a thrust, and my objective is to plot the fastest course given the fact that the agent has a maximum thrust and maximum angular velocity.
After some research I realized that I may be looking for a curve fitting algorithm, but I don't know the underlying function since the points are randomly distributed in the coordinates system.
Please, help me find a solution to this problem.
I am open to any suggestion, my prefered programming language being C++.
I'm sure there is a pure mathematical solution such as spacecraft trajectory optimization for example, but here is how I would consider approaching it from a programming/annealing perspective.
Even though you need a continuous path, you might start the path search with discreet steps and a tolerance for getting close enough to each point as a start.
Assign a certain amount of time to each step and vary applied angular force and thrust at each step.
Calculate resulting angular momentum and position for the start of the next step.
Select the parameters for the next step either with a random search, or iterate through each to find the closest to the next target point (quantize the selection of angles and thrust to begin with). Repeat steps until you are close enough to the next target point. Then repeat to get to the next point.
Once you have a rough path you can start refining it (perhaps use the rough point from the previous run as target points in the new one) by reducing the time/size of the steps and tolerance to target points.
When evaluating the parameters' fitness at each step you might want to consider that once you reach a target point you also want to perhaps have momentum in the direction of the next point. This should be an emergent property if multiple paths are considered and the fitness function considers shortest total time.
c++ could help here if you use the std::priority_queue and std::map for example to keep track of the potential paths.
Related
I read through the forum and as I am sure this question has been asked before, but I couldn't really find what I was looking for.
My problem is the following:
I have an AI-Character moving along a spline. Should that path be blocked, the character should move in an arc around it and then continue on it's path.
For arguments sake lets assume that the spline has a length of 7000 units.
Therefore, I have two 3D (x,y,z) vectors. The first vector is the current position of the AI-bot and the second vector the position past the obstacle. For the time being lets just say: current spline position + 400 units; later on I could do a line trace to get the dimension of the obstacle etc. but for now I don't care about it.
Now I would like to compute an alternative path to avoid aforementioned obstacle - hence compute the arc between these two points - How do I do this?
I am really terrible at maths but looked at projectile trajectory because I thought that it would be sort of the same, just was unable to really understand it :<
It doesn't have to be an arc. You can solve this problem recursively in a very simple way.
Consider you're at position A, and the obstacle is at position B. You can do the following moves:
From current position to A+V(B[x]+height(B),0,0)
From current position to A+V(0,B[y]+width(B),0)
From current position to A+V(B[x]-height(B),0,0)
where V is a vector with components V(x,y,z), width(B) is the width of the obstacle and B[x] is the x component of the position of B. This way you moved around it along a rectangle. You can now smoothen the path by subdividing that rectangle in halves. 3 subdivisions are enough to make this smooth enough. To subdivide, take the middle point the first path, and draw a line to the middle of the second path. The same you do from the second path to the third one, and now your rectangle becomes an octagon. If that's not smooth enough, do a few more steps. This will create a new spline that you can use.
I would look at a combination of splines and the EQS system. The spline defines the ideal path to follow. The EQS system finds locations near or on the path, while still doing obstacle avoidance. EQS can return all valid destinations so you can manually order them by custom critera.
Actors set on a spline do work, but there's a whole bunch o' mess when making them stop following a spline, creating a new one at the correct point, attaching the actor the new spline, and so on.
I arrived at this conclusion yesterday after exactly going the messy way of adding spline points etc. The only problem i see is that I find the EQS system very difficult to understand. Not following the examples as such, but modifying it in the way I need it. Lets see, i keep you posted.
Im building a DIY laser target.
So far on the software side I managed to find when is a laser shot at the target by calculating differences and threshold, and then find where did it hit in relation to the whole image.
Now the next problem I am facing is finding where it hit in relation to the target center.
I have a proper box assembled for the target, but while testing this is what I have (the inner circle should have been filled with black):
Its not pretty and has lots of unrelated noise but it should be enough to test. This is a best possible scenario, from within the box:
To find where it hit in relation to the target center I suppose I'll have to make a binary image out of those two black rings and calculate the average point. (how?)
Then (supposing the target is perfectly parallel, not even a little bit in perspective), with the center known, I would need to know how far the outer ring is from it.
With that known it should be a matter of trigonometry to tell the punctuation (11 to 0, being 0 the outside of the outer ring)
Resuming the question:
Need to detect a known figure(ring), tell where its center is, and determine its radius.
I am not worried about performance since this will only be done once at each program run to calibrate.
Some sample C++ code (besides pointing to the functions I can use) would be great since I'm new to both C++ and OpenCV.
I have a wireless mesh network of nodes, each of which is capable of reporting its 'distance' to its neighbors, measured in (simplified) signal strength to them. The nodes are geographically in 3d space but because of radio interference, the distance between nodes need not be trigonometrically (trigonomically?) consistent. I.e., given nodes A, B and C, the distance between A and B might be 10, between A and C also 10, yet between B and C 100.
What I want to do is visualize the logical network layout in terms of connectness of nodes, i.e. include the logical distance between nodes in the visual.
So far my research has shown the multidimensional scaling (MDS) is designed for exactly this sort of thing. Given that my data can be directly expressed as a 2d distance matrix, it's even a simpler form of the more general MDS.
Now, there seem to be many MDS algorithms, see e.g. http://homepage.tudelft.nl/19j49/Matlab_Toolbox_for_Dimensionality_Reduction.html and http://tapkee.lisitsyn.me/ . I need to do this in C++ and I'm hoping I can use a ready-made component, i.e. not have to re-implement an algo from a paper. So, I thought this: https://sites.google.com/site/simpmatrix/ would be the ticket. And it works, but:
The layout is not stable, i.e. every time the algorithm is re-run, the position of the nodes changes (see differences between image 1 and 2 below - this is from having been run twice, without any further changes). This is due to the initialization matrix (which contains the initial location of each node, which the algorithm then iteratively corrects) that is passed to this algorithm - I pass an empty one and then the implementation derives a random one. In general, the layout does approach the layout I expected from the given input data. Furthermore, between different runs, the direction of nodes (clockwise or counterclockwise) can change. See image 3 below.
The 'solution' I thought was obvious, was to pass a stable default initialization matrix. But when I put all nodes initially in the same place, they're not moved at all; when I put them on one axis (node 0 at 0,0 ; node 1 at 1,0 ; node 2 at 2,0 etc.), they are moved along that axis only. (see image 4 below). The relative distances between them are OK, though.
So it seems like this algorithm only changes distance between nodes, but doesn't change their location.
Thanks for reading this far - my questions are (I'd be happy to get just one or a few of them answered as each of them might give me a clue as to what direction to continue in):
Where can I find more information on the properties of each of the many MDS algorithms?
Is there an algorithm that derives the complete location of each node in a network, without having to pass an initial position for each node?
Is there a solid way to estimate the location of each point so that the algorithm can then correctly scale the distance between them? I have no geographic location of each of these nodes, that is the whole point of this exercise.
Are there any algorithms to keep the 'angle' at which the network is derived constant between runs?
If all else fails, my next option is going to be to use the algorithm I mentioned above, increase the number of iterations to keep the variability between runs at around a few pixels (I'd have to experiment with how many iterations that would take), then 'rotate' each node around node 0 to, for example, align nodes 0 and 1 on a horizontal line from left to right; that way, I would 'correct' the location of the points after their relative distances have been determined by the MDS algorithm. I would have to correct for the order of connected nodes (clockwise or counterclockwise) around each node as well. This might become hairy quite quickly.
Obviously I'd prefer a stable algorithmic solution - increasing iterations to smooth out the randomness is not very reliable.
Thanks.
EDIT: I was referred to cs.stackexchange.com and some comments have been made there; for algorithmic suggestions, please see https://cs.stackexchange.com/questions/18439/stable-multi-dimensional-scaling-algorithm .
Image 1 - with random initialization matrix:
Image 2 - after running with same input data, rotated when compared to 1:
Image 3 - same as previous 2, but nodes 1-3 are in another direction:
Image 4 - with the initial layout of the nodes on one line, their position on the y axis isn't changed:
Most scaling algorithms effectively set "springs" between nodes, where the resting length of the spring is the desired length of the edge. They then attempt to minimize the energy of the system of springs. When you initialize all the nodes on top of each other though, the amount of energy released when any one node is moved is the same in every direction. So the gradient of energy with respect to each node's position is zero, so the algorithm leaves the node where it is. Similarly if you start them all in a straight line, the gradient is always along that line, so the nodes are only ever moved along it.
(That's a flawed explanation in many respects, but it works for an intuition)
Try initializing the nodes to lie on the unit circle, on a grid or in any other fashion such that they aren't all co-linear. Assuming the library algorithm's update scheme is deterministic, that should give you reproducible visualizations and avoid degeneracy conditions.
If the library is non-deterministic, either find another library which is deterministic, or open up the source code and replace the randomness generator with a PRNG initialized with a fixed seed. I'd recommend the former option though, as other, more advanced libraries should allow you to set edges you want to "ignore" too.
I have read the codes of the "SimpleMatrix" MDS library and found that it use a random permutation matrix to decide the order of points. After fix the permutation order (just use srand(12345) instead of srand(time(0))), the result of the same data is unchanged.
Obviously there's no exact solution in general to this problem; with just 4 nodes ABCD and distances AB=BC=AC=AD=BD=1 CD=10 you cannot clearly draw a suitable 2D diagram (and not even a 3D one).
What those algorithms do is just placing springs between the nodes and then simulate a repulsion/attraction (depending on if the spring is shorter or longer than prescribed distance) probably also adding spatial friction to avoid resonance and explosion.
To keep a "stable" diagram just build a solution and then only update the distances, re-using the current position from previous solution as starting point. Picking two fixed nodes and aligning them seems a good idea to prevent a slow drift but I'd say that spring forces never end up creating a rotational momentum and thus I'd expect that just scaling and centering the solution should be enough anyway.
I am currently working on a project that has a vector containing X and Y coordinates for approximately 800 points. These points represent an electric network of lines.
My goal is to compute the shortest distance Path between a Point A and Point B that can be or can not be located along the path given by the vectors containing the X-Y coordinates of the electric lines.
I have read about the Dijkstra Algorithm but since i am not that much familiar with it, I am not sure if I should go in that direction. I will be very thankful if I can get any feedback or comments from you that can direct me to solve this matter.
Any pathfinding algorithm depends on paths, points are just meaningless. What you have now is a list of "waypoints". However you have not explained how those points connect. For example if any and every point is connected to each other point the shortest distance would simply be the pythagoral distance between A & B. - I'm also unsure what you mean by X-Y coordinates of electric lines, such a "line" would always have a start & end position?
So the first step is to add to each point not only the x,y coordinates, but also a list of connectable points.
Once you did this you can start using a pathfinding algorithm (In this case A* would seem better than Dijkstra's though). It would simply be a standard implementation with each "cost" the actual distance between a point. (And for A* the heuristic would be the pythagoral distance to the end point).
For a good tutorial about A* (and other algorithms) you should check Amit's pages
EDIT, in reply to the comments.
It seems the first step is to convert a set of line segments to "points". The way I would go through this is:
collection AllPoints {containing Location & LinksToOtherPoints}
for each Segment
get start/end Point of Segment
if Point.Location is not in allPoints
add Point to AllPoints
add the other Point of Segment to LinksToOtherPoints
You then have simply a list with all points & the connections between them. As you have to constantly search the allPoints collection I suggest storing that in a binary tree structure (sets?).
For computing the shortest path Dijakstra would be fine.
You may get faster results from using A*, which uses a best guess of the distance in order to focus its search in the right direction, thereby getting there quicker.
If you are repeatedly querying the same data set, then memoization is fine.
Those people who recommend a brute-force algorithm are fools - it's worth taking a little time to learn how to program an efficient solution. But you could calculate the shortest path between all points using the Floyd-Warshall algorithm. Unfortunately, this won't tell you what the shortest path is just how long it is.
Just calculate the distance for all possible paths and pick the shortest one.
800 paths is nothing for modern PC. You will not even notice it.
I am doing alphabet tracing application for kids. I have given the dotten points. how to identify that am moving over that points. using Touches moved, i want to write.If moved incorrectly, i dont like to draw lines. plz share ur ideas
The simple version is:
Record the initial touch-point on touchesBegan.
On each touchesMoved call, do:
Interpolate a reasonable number of points (a dozen or so should be sufficient) between the initial touch-point and the current touch-point.
For each interpolated point, perform a hit-test against your "dot" locations. This can be done by computing the linear distance between the point and the "dot" location, and counting any distances closer than some threshold as a "hit".
Set the initial touch-point to the current touch-point.
On touchesEnded, perform one final round of interpolation and hit-test, and then clear your initial touch-point.
Of course you may want to add some extensions of your own to the basic algorithm, such as keeping an array of all the contacted points to check at the end of the event to help discriminate coordinated interactions from random nonsense, and so on.