This question already has an answer here:
How do I work out the future position of a moving object? [closed]
(1 answer)
Closed 10 years ago.
I have asked this question previously and it was closed due to it not being a programming question, this is entirely as I worded it wrong. I would like this to implemented into java. I am creating a little game and I have a photon torpedo which is being fired from a ship towards a target. Now as the speed of the torpedo is slow the ship will never hit any targets if they're moving and I want to fix this. I have drew up multiple theories and mapped out lots of mathematical stuff to find out the best way to accomplish this and in the end I deduced the following:
I find the time it takes for the photon torpedo to get to the target.
I find how far the target will have traveled in the time it takes for the torpedo to arrive.
I then find the distance between the new position of the target and the original ship.
this then gives me the opportunity to use the Cosine rule (SSS) to find out the trajectory at which the bullet needs to be fired to have a much higher chance of hitting.
Here is a digram:
Now the only problem that I need to rotate line a to the correct orientation as by default it's parallel to line c which messes up the entire equation. Can anyone help with this? And also if you can think of a better way to find the new position suggestions are very welcome. My java game entity mechanic works as follows:
Each entity has two Vectors which control movement. Position and Velocity. However, velocity is not tracked entirely properly as instead of it being a speed and a direction, to make things easier it's an xSpeed and a ySpeed.
The entities are all updates once per tick and the ship which shoots the torpedo must calculate the future position in this one tick and not over multiple ticks.
I ask this question not to be closed again, because this time I really need the answer to be implemented into Java.
This is the math i've tried so far:
double dis = level.distanceBetween(photonTargetTop, this);
double speed = 5;
double time = dis / speed;
double d1 = photonTargetTop.velocity.x * time;
double d2 = photonTargetTop.velocity.y * time;
double dis2 = level.distanceBetween(this, photonTargetTop.pos.x + d1, photonTargetTop.pos.y + d2);
double dis3 = level.distanceBetween(photonTargetTop, photonTargetTop.pos.x + d1, photonTargetTop.pos.y + d2);
double cosAngle = Math.pow(dis2, 2) + Math.pow(dis, 2) - Math.pow(dis3, 2) / 2 * dis2 * dis;
double angle = Math.acos(cosAngle);
EntityPhoton p = new EntityPhoton(this, level);
p.rotation = angle;
level.addEntity(p, pos);
Let's assume the target ship has no acceleration, meaning that it's speed and direction is not changing.
Let's also assume that once fired, your torpedo has no acceleration. And it always goes at constant speed.
Let's also call (0,0) the point where your torpedo is fired.
The ship describes a straight line. Choose a point on this line (if the ship is following a course that does not go through (0,0) you can find the closest point to the central position with some geometry that you can look up on wikipedia).
Once you have chosen the position where you want to hit the enemy ship, you know the distance between (0,0) and that position, and given that the speed of the torpedo is always the same, you can also know when to fire the torpedo.
Then you must also find the direction, meaning the values of speed to give on x and y, but that's not so difficult.
In general the problem is a system with multiple solutions, so presuming that the torpedo is faster than the target, there are infinite points where you can hit it, so you must use some heuristic to choose a point that's convenient to you.
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I want to calculate actual distance traveled by mobile (iOS and Android). I know through google map API, we can find optimum route distance between 2 coordinates. But I want to calculate distance, actual path mobile(in vehicle) has covered.
One Algo I came to know is saving coordinates after x seconds, lets say after 5 or 10 seconds, and then calculate distance between consecutive coordinates, and there sum will give total distance.
I want to discuss better approach of its solution , Is there any better solution?
Edit : How Apps like Nike running app and Uber works?
------------------UPDATE----------------------
There is two major point in your question.
1) get the phone coordinates (which has been treated in the first part of this response)
2) Calculate the real distance between this two coordinates
IMHO, calculus could be done by a web service: calculation based only
on the distance between two coordinates can lead to really wrong result.
Here is an exemple of such a web service
https://graphhopper.com/#directions-api
The demo app: https://graphhopper.com/api/1/examples/
It's based on traffic flow (as many of this tools)
So you have to be careful with the order of the coordinates
because it can bring wrong result.
For exemple with two point in the right order:
This gives a good result
But if you give wrong order (with the same coordinates)
For the same coordinates, it can lead to an extremely different result.
So for coordinates ABCD (in chrnological order)
you need to do:
A->B B->C C->D
Graphhopper seems able to do offline distance calculus
Here are the lib on iOS and Android
https://github.com/graphhopper/graphhopper-ios/
https://github.com/graphhopper/graphhopper/tree/master/android
---------------------------------------------------
You have to define how your app work. Foreground or background?
As said in other responses, you'll have to get the user position every X seconds. Then calculate the distance.
For iOS:
You can use information on this website: http://mobileoop.com/
It talks about tracking user location on iOS when the app is in background.
Here is the github: https://github.com/voyage11/Location
Then you have to convert the point thanks to
CLLocationDistance distance = [aCLLocationA distanceFromLocation:aCLLocationB];
You can also check this (from apple doc) https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/LocationAwarenessPG/CoreLocation/CoreLocation.html:
Make sure the location manager’s pausesLocationUpdatesAutomatically property is set to YES. When this property is set to YES, Core Location pauses location updates (and powers down the location hardware) whenever it makes sense to do so, such as when the user is unlikely to be moving anyway. (Core Location also pauses updates when it can’t obtain a location fix.)
Assign an appropriate value to the location manager’s activityType property. The value in this property helps the location manager determine when it is safe to pause location updates. For an app that provides turn-by-turn automobile navigation, setting the property to CLActivityTypeAutomotiveNavigation causes the location manager to pause events only when the user does not move a significant distance over a period of time.
CLActivityTypeAutomotiveNavigation insure you to get a position which is on a road.
For Android:
You can use this project:
https://github.com/quentin7b/android-location-tracker
That can easily helps you to get the user's position thru time
Thanks to the TrackerSettings object
TrackerSettings settings =
new TrackerSettings()
.setUseGPS(true)
.setUseNetwork(true)
.setUsePassive(true)
.setTimeBetweenUpdates(30 * 60 * 1000)
.setMetersBetweenUpdates(100);
To find the distance between two point on Android, you can check this:
Get the distance between two geo points
Both OS
Based on a position picked up every X second you have to reduce time between picking location data to improve accuracy.
As you want to calculate distance on a road context, setup the Location manager in navigation mode, this mode gives you coordinates that are on road.
Finally
If you want to improve the accuracy of your distance calculus,
you can use a google API:
https://developers.google.com/maps/documentation/distance-matrix/intro
By setting the right mode parameter:
Optional parameters
mode (defaults to driving) — Specifies the mode of transport to use when calculating distance. Valid values and other request details are specified in the Travel Modes section of this document.
I'm working on something similar on Andoriod, but the principals are the same for iOS either:
For each GPS sample, check its accuracy. If it's over some threshold (say 20 meters) - ignore it.
Remember that even if the mobile device is static, different GPS samples will give you different locations, depending on the accuracy. A car standing still for a long time in a traffic light, will show that you've advanced few dozens of meters, so add a method that detects if the mobile is static or not. I've implemented this by reading the accelerometer - if the delta between two readings if bigger than some threshold - the device is moving. If it's too small - ignore the GPS.
If you intend to use it in a car, you can read the GPS whenever it has a new reading (in Android use the onLocationChanged method). If you use it for running/walking, take into account that your speed is slow - two consecutive readings will be relativly close, but due to the GPS's accuracy, you can get quite a large distance betwwen them. It can be fixed by increasing the time between two consecutive readings, or by ignoring some of them (i.e. take into account only each 10th reading).
Use the Haversine formula to calculate the distance between two consecutive readings. In Android it can be done with the Location.distanceTo() method.
You'll have to test it against the odometer in your car and adjust the thresholds for the accelerometer.
4 years ago, I just made an app called Landsurvayor that calculates the actual distance of two geo-graphical points drawn on Google Map. I don't know that might help you or not but there is a formula called Haversine formula that calculates the actual distance between two geo-graphical points. You might give it a try and see whether it is useful for you or not. Below is the sample code of Haversine formula:
public double CalculationByDistance(double initialLat, double initialLong,
double finalLat, double finalLong){
int R = 6371; // km
double dLat = toRadians(finalLat-initialLat);
double dLon = toRadians(finalLong-initialLong);
lat1 = toRadians(lat1);
lat2 = toRadians(lat2);
double a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(lat1) * Math.cos(lat2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
return R * c;
}
public double toRadians(deg) {
return deg * (Math.PI/180)
}
More about Haversine formula:
https://en.wikipedia.org/wiki/Haversine_formula
There is another simple Android SDK built-in approach to calculate distance between two lat, lng:
Location locationA = new Location("point A");
locationA.setLatitude(latA);
locationA.setLongitude(lngA);
Location locationB = new Location("point B");
locationB.setLatitude(latB);
LocationB.setLongitude(lngB);
distance = locationA.distanceTo(locationB) ;
I hope it might help you.
You can achieve more accuracy with a combination of the following strategies.
As mentioned in other Answers, you can store the position of the mobile
every X seconds(say 10 seconds) using GPS and measure the
consecutive time between the points.
Also when the user makes quick turns, make sure to read that by
using Magnetic Sensor values too, so in such event, decrease the
"timing between position storing" to say 1-2 seconds(Will be needed for accuracy)
As a final step, use Map data(such as Google Maps etc.) to make sure
you are being tracked properly(if on road).
And then sum up all the values to get the accurate distance.
P.S. I gave information about the strategies alone since I'm not sure about its implementation in Android(or iOS).
Hope this helps :)
One problem with using GPS coordinates is that they (obviously) are not accurate. If you are travelling in a straight line, the GPS coordinates might show you travelling on a zig-zag path, hence returning a greater distance travelled than the true distance. Even with good GPS accuracy this error can be significant. Using less coordinates could result in a more accurate calculation, or not.
What you need is a way to smooth the GPS path plotted, with due consideration to your required accuracy (again a trade-off).
My first thought is to break the points into groups, and fit line segments to each group (look up "linear regression"). Then find where each consecutive line-pair overlap to define each line segment. Then simply sum the line segment lengths.
You could curve-fit segments, but that's much more intense mathematically, and might not yield a better result (and which curve formula to use?). There may be better mathematical ways I'm not aware of.
Hope this helps.
If you are looking for exact (or nearly exact) distance information, you need to track the path followed, which means checking coordinates every few seconds (depending upon expected speed traveled). You can save space by discarding the old coordinates after calculating each segment and just storing current distance traveled.
Android :: how to calculate distance while walking in android?
There are different ways to do this:
1.GPS: Keep adding GPS distance between 2 points every X seconds (say 10 sec). Check Android Location.distanceTo or distanceBetween. Check
My Tracks app, it is open source. GPS is not available indoors and
would have error if user is changing direction very frequently (read
every 1-2 second)
2.Accelerometer: Look for code/library for step detection using accelerometer. Distance comes from double integration of acceleration,
errors can add up very quickly here.
3.Step detector: Built-in in Nexus 5. Google must have taken care of accelerometer errors to extent possible. This is hardware-based
computation, consumes less battery but not available in most of
handsets as of date.
The 2nd option seem very similar to what you suggested and I do think its the best way to achieve it since iOS and Android defer in code and in functionality therefor the best method to achieve it is saving currentLocation and previousLocation in a while loop that will .sleep() and just sum the entire loop as the distance traveled.
the bigger question is this supposedly app is a distance summerizing app? does it just a small function inside of it? how do you decide when to stop calculating the distance?
If accuracy is critical, you can use data from accelerometer and gyroscope. You can find very simple formula for solving simple cinematic task so you get acc in global axis. Than you just have to use integral twice (first to get velocity, than to get position).
Just to show another perspective.
Use GPS to get lat lon of both places and after getting both pass it below method.Its will return distance in km
public static double getDistanceFromLatLonInKm(double lat1, double lon1,
double lat2, double lon2) {
double R = 6371; // Radius of the earth in km
double dLat = deg2rad(lat2 - lat1); // deg2rad below
double dLon = deg2rad(lon2 - lon1);
double a = Math.sin(dLat / 2) * Math.sin(dLat / 2)
+ Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2))
* Math.sin(dLon / 2) * Math.sin(dLon / 2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
double d = R * c; // Distance in km
return d;
}
public static double deg2rad(double deg) {
return deg * (Math.PI / 180);
}
}
Log points every x seconds (maybe 2-3?) and use distance formula below for every point logged.
Distance = sqrt((x2−x1)^2+(y2−y1)^2)
Sum them all up and you get distance
I'm making a simple 2d Java game similar to goemetry wars. I'm currently programming the player's shooting.
I have a target point specified by the mouse location. Now I want to add a bit of randomization, so that the shooting angle has a random offset. I am currently converting the point to a vector directly. My idea was to convert the vector to an angle, apply the randomization to that angle, and then, convert the angle back to a vector (given the length of the vector).
I can't figure out how to convert the angle back to a vector. I don't need code, it's basically just a question about the maths.
If there's a better way to randomize the shooting, I would love to hear that too! I can!t apply the randomization to the point because there are other things then the mouse that can set it.
Polar coordinate system
As everybody seems to have just answered in the comments, here goes the answer to your question as it is formulated : you need to use the polar coordinate system.
Let's call your angle a, the angle you want to add to it b, so the modified angle is a+b.
In the polar coordinate system, your point is represented by an angle a = Math.atan2(y, x) and a radius r = sqrt(x*x + y*y). If you just use the angle, you loose some information, which is at which distance the mouse is from your (0,0) point.
Converting back from your polar representation (after the angle has been modified) is now possible : x = r * Math.cos(a+b), y = r * Math.sin(a+b)
Without computing the angle
By using some cool trigonometry formulas, we can do better. We don't need to go to an angle and come back to a vector, we can modify the x and y values of the vector directly, still changing the angle like you want.
Remember that we want to find x'=r cos(a+b) and y'=r sin(a+b). We will obviously the following formulas :
Now let us multiply by r on both sides to get what whe want.
We now recognize x=r cos(a) and y=r sin(a), so we have the final expression :
If you come to think of it, for small values of b (which is what you want), sin(b) is close to 0, and cos(b) is close to 1, so the perturbation is small.
Not only do you reduce the number of trigonometry operations from 3 to 2, but you also have a cos and a sin of small values, which is nice if they are computed from Taylor series, makes convergence very fast. But that's implementation dependent.
NB: An alternative (and more elegant?) way to find the same result (and exact same formulas) is to use a rotation matrix.
I can haz cod
Whoopsie, you said you didn't want code. Well let's do it like this : I don't post it here, but if you want to compare with how I'd do it once you're done coding your implementation, you can see mine in action here : http://ideone.com/zRV4lL
I'm aware of Quaternion methods of doing this. But ultimately these methods require us to transform all objects in question into the rotation 'space' of the Camera.
However, looking at the math, I'm certain there must be a simple way to get the XY, YZ and XZ equations for a line based on only the YAW (heading) and PITCH of a camera.
For instance, given the normals of the view frustrum such as (sqrt(2), sqrt(2), 0) you can easily construct the line (x+y=0) for the XY plane. But once the Z (in this case, Z is being used for depth, not GL's Y coordinate scrambling) changes, the calculations become more complex.
Additionally, given the order of applying rotations: yaw, pitch, roll; roll does not affect the normals of the view frustrum at all.
So my question is very simple. How do I go from a 3-coordinate view normal (that is normalized, i.e the vector length is 1) or a yaw (in radians), pitch (in radians) pair to a set of three line equations that map the direction of the 'eye' through space?
NOTE:
Quaternions I have had success with in this, but the math is too complex for every entity in a simulation to do for visual checks, along with having to check against all visible objects, even with various checks to reduce the number of viewable objects.
Use any of the popular methods out there for constructing a matrix from yaw and pitch to represent the camera rotation. The matrix elements now contain all kinds of useful information. For example (when using the usual representation) the first three elements of the third column will point along the view vector (either into or out of the camera, depending on the convention you're using). The first three elements of the second column will point 'up' relative to the camera. And so on.
However it's hard to answer your question with confidence as lots of things you say don't make sense to me. For example I've no idea what "a set of three line equations that map the direction of the 'eye' through space" means. The eye direction is simply given by a vector as I described above.
nx = (float)(-Math.cos(yawpos)*Math.cos(pitchpos));
ny = (float)(Math.sin(yawpos)*Math.cos(pitchpos));
nz = (float)(-Math.sin(pitchpos)));
That gets the normals of the camera. This assumes yaw and pitch are in radians.
If you have the position of the camera (px,py,pz) you can get the parametric equation thusly:
x = px + nx*t
y = py + ny*t
z = pz + nz*t
You can also construct the 2d projections of this line:
0 = ny(x-px) + nx(y-py)
0 = nz(y-px) + ny(z-pz)
0 = nx(z-pz) + nz(x-px)
I think this is correct. If someone notes an incorrect plus/minus let me know.
I currently have an array of points (x,y) from the result of an A* pathfinding function. This array is set up so that the first index is the point closest to the character and the next one is the next point that needs to be traveled in the path.
These points are on a grid (currently 8 pixels between each point on the grid, this is changable.)
My current strategy is to move the character to the first point, when he has arrived at that point, then move to the next one, simple as that.
I move to the first point by creating a vector from the character to that point and find how far it is. Then I find the angle and move in that direction.
// How the character is moved
double xMove = Math.cos(charAngle * (Math.PI / 180)) * 0.1 * delta;
double yMove = Math.sin(charAngle * (Math.PI / 180)) * 0.1 * delta;
x += xMove;
y += yMove;
absVx -= Math.abs(xMove);
absVy -= Math.abs(yMove);
absVX and absVy store the absolute distance left to go and it is decremented after each movement. If they are both below or equal to zero, then we have reached our destination, we remove it from the array and recalculate everything again with the next point.
I have two issues.
Sometimes the character skips over a point and then he just travels forever. This is most likely due to the delta the game engine adds to the movement (slick) and the character moves too far, I'm not sure on this one though.
This works fine when I single click the destination but what I need is to be able to hold down the mouse button. Currently the character just "stands still" on the first point if I hold the mouse down.
I had an idea for a solution to the 2nd problem but I'm not sure it's a good one. It is to store the location you want to go from the last mouse click but not actually calculate it untill you have passed the point you were moving to.
So, I hope someone really smart and fun can have a little conversation with me about this :D
About 1, the most probably cause is a rounding issue; adding these xMove / yMove introduce an small error and the x and y never really get the value of the destination, so the algorithm keeps running.
Ways to solve:
1 Define "reaching destination" so it allows a degree of error
2 Find out how many "ticks" will take to the character to arrive to destination, when it "arrives", force the character position to its destination (this allows to correct accumulated error).
Also, I would go back to graphics theory. IIRC, your path moving between points should be equal to Bresenham's line drawing algorithm. For later stages, your character could follow a B-Spline along his path.
Alright, this is probably gonna be a pretty simple question to answer. I haven't had a math class dealing with logarithms in a few years, so I apologize. So I have a USB Controller that I'm using to control the mouse on the screen with the left joystick. Now how this works right now is the controller returns a double between 0.00 and 1.00 depending on how far the push the joystick in the direction (0.00 center, 1.00 pushed all the way over). I'm using this to adjust the speed of the mouse movement by multiplying the returned value by a given speed (returned double * speed). This gives me a linear speed. But for the purpose of accuracy of the mouse and clicking things on screen, I'd like it to be more logarithmic, so as it's really slow when barely pushing, and then the speed increases logarithmically as you move the joystick farther. That way you can get good speed for moving across the screen, while also having good sensitivity when moving it slowly. So I just need help with the formula, as I'm sure it's pretty simple. Also, I'm working in Java.
Right now my formula is:
double value (value given by controller)
int speed = 25;
value += value * speed;
I then use this to move the mouse.
Thanks,
Brayden
I presume you meant exponential. An exponential function looks like http://hotmath.com/images/gt/lessons/genericalg1/exponential_graph.gif: the more value is, the larger the derivative (the more speed will increase for the same change in value).
double value = ...;
int base = 25;
value = java.lang.Math.pow(base, value);
Not sure if java.lang.Math is necessary in its full form or whether you need to import java.lang.Math first. I'm not a Java programmer.
I agree with MvanGeest, I think you want an exponential formula. That way its small with little distance, and very big with larger distances.
I'm not sure what mouse speed values are fast or slow, but you could do something like
double value (value given by controller);
int speed (maximum speed value);
value = Math.pow(speed, value);
You could also make the value something like 2*(whatever the controller gives you) to make a wider range of speeds.
Something like:
f(value) = value * MAXSPEED * Math.Pow (base, 1 - value)
f(0) = 0 // no movement
f(1) = MAXSPEED // maximum movement when joystick is full throttle
All values should be covered in the range. Base in this case can be any value greater than 1.