I'm developing a very simple physical engine.
I have to calculate the final speed of a circle in an elastic collision against another circle. Each circle has a specific mass, radius and speed.
In order to calculate x and y speed I solve a system with conservation on momentum and conservation of kinetic energy equations.
By the way these equations don't consider the "shape" of circles.
So I calculate the rebound angle by finding the tangent where 2 circles intersect.
Now I have 2 different final speeds directions: the one calculated with momentum law and the one calculated with rebound.
I don't know how to combine the 2 speeds to get the final one
You'll need to calculate the speed in both the X and the Y direction.
Basically, what you do is calculate the results of the x component of the collision, the results of the collision in the y direction, and then combine them to find the resultant angles and speeds.
This is a common AP physics question, so you'll find lots of writeups on the internet about how to do it. This one looks like it should work for you:
http://spiff.rit.edu/classes/phys311.old/lectures/coll2d/coll2d.html
The solution I found is to consider normal and tangential components of my 2 circles velocities, and not their X and Y components.
This way I can apply law of conservation of momentum related to tangent and normal, and at the same time it considers the geometry of circles too.
The last part of this tutorial is very helpful, even if I used a different algorithm, with some different logics: https://www.youtube.com/watch?v=LPzyNOHY3A4
Related
I am trying to bounce a projectile off of a wall in Slick. When the wall is vertical or horizontal, I can just invert the x or y velocity of the projectile, but when this is not the case I am struggling. I found another answer to a similar question in C# and have tried to implement it, but the result is just that the ball goes off at 180 degrees every time. What I have is:
Vector2f norm = wall.getNormal();
float comp = (vect.dot(norm)/norm.dot(norm));
Vector2f u = new Vector2f(norm.getX()*comp,norm.getY()*comp);
Vector2f w = new Vector2f(vect.getX()-u.getX(),u.getX());
vect.set(w.getX()-u.getX(),w.getY()-u.getY());
Where wall is a Vector2f that I am trying to bounce off of (converted from a line to a vector, but not sure if this was necessary) and vect is the trajectory of my projectile.
Any advice would be really helpful. I would love if someone could explain an answer to me rather than just giving me the code, because I think I may need to implement something slightly different later.
Thanks.
The answer here is going to wind up being mostly a question of math. I briefly go over the math/physics involved and trust that you should be able to implement the math/physics in code yourself.
How projectiles are supposed to bounce off of walls
In classical physics, or at least in a reasonably representative model of classical physics, when a projectile collides with a wall, the magnitude of the angle at which it leaves the wall relative to the 'normal' vector of the wall is equal to the magnitude at which it approaches the wall relative to the 'normal' vector. In other words, draw a line perpendicular to the wall the object is colliding with. The angle between this line and the vector of your projectile moving towards the wall will be the same as the angle of the vector of your projectile moving away from the wall.
This is most commonly discussed for light rays, but it works the same way for simple projectiles.
http://hyperphysics.phy-astr.gsu.edu/hbase/phyopt/fermat.html
How to calculate these angles
So let's say you have a vector for the normal of the wall, and a vector for the projectile. For 2-dimensional vectors, this is actually quite easy. You should have a couple of decent options here. One way might be to get the angles of the two vectors and subtract them to find the difference.
Now we know the magnitude of the angle, but we now need to create a vector with the same angle but on the other side of the normal vector. Your vector library conveniently allows you to adjust your vector by a given angle. You should be able to take the projectile's current velocity vector and adjust in the correct direction it by twice the angle between it and the normal-to-wall vector and get the desired velocity vector post-reflection. The trick I will leave you to figure out is a good way to determine if you need to adjust your vector in the clockwise or counter-clockwise direction.
Some things to keep in mind about Vector2f
The getNormal() method returns a unit vector in the same direction as the vector
If you want a vector normal to a certain vector, you must use the getPerpendicular() method
A vector may be rotated/adjusted by a certain angle using the sub(double theta) method
If you would like to retrieve the angle of a vector, you may do so using the getTheta() method
I need to make a wheel fall on 1 of five angles and I want it to teeter when it gets to the angle. After the user spins the wheel, I have it slow down by multiplying the rotation velocity by .98 per tick. I sort of have it working by finding the closest of the angles and adding a small value in its direction to the velocity. However this looks unrealistic and can be glitchy.
I was thinking of implementing a damped sine wave but i'm not sure how I would do this.
Current Pseudocode:
var rotation, rotationVelocity, stoppingPoints[5];
update(deltaT) {
velocity -= rotationVelocity * 0.5 * dt;
closestAngle = findClosestAngle().angle;
rotationVelocity += (closestAngle - rotation) / 36 * dt;
rotation += rotationVelocity;
}
Edit:
Teeter: move or balance unsteadily; sway back and forth:
subtract a constant amount from it's velocity every iteration until it reaches zero
not only does this actually represent how friction works in real life, but it's easier too.
If you want it to move as though it were connected to a spring:
Hooke's law for springs is F = -kx where k is a constant and x is the distance from the origin if you want it to sway back and forth as though it were on a spring. keep track of it's rotation from an origin, and add -kx where x is it's rotational distance(or angle) from the origin.
Now, if you apply both friction and hooke's law to the spring, it should look realistic.
I think the closest angle that you want is the cloest to where it will stop. You can simulate where it will end, how long it takes to end, and use that to determine how much extra(or less) velocity you'll need.
Not sure what you mean by teetering exactly.
It sounds like you want to model a wheel with weights attached at the stoppingPoints. I mean, from a physics viewpoint. There is the existing rotational velocity, then deceleration from friction, and an unknown acceleration/deceleration caused by the effects of gravity on those points (as translated to a rotational velocity based on the position of the weights). Anyway, that's my interpretation and would probably be my approach (to model the gravity).
I think the teetering you speak of will be achieved when the acceleration caused by the weights exceeds the existing rotational velocity.
I will probably have to implement a center-of-gravity class but I will ask help in seeking such a Java class before I do. I suspect this has been implemented by others as part of a math library.
In a space of n-dimensions, suppose each dimension is discrete. So for example in 3 dimensions, you can have an X dimension with a range of [0..a]. You also have a Y dimension with a range of [0..b] and a Z dimension with a range of [0..c]. The implementation should be general so that the number of dimensions can be greater than 3 and also generally a not equal to b where a and b are the maximum coordinates of their respective dimensions.
Each point in the space is a double precision float (non-negative).
Find the coordinate of the center-of-gravity.
If you use a physics engine, you can easily get the centre of gravity -- try JBullet :) The centre of mass which you can get with the API is essentially the same thing, but with a slight difference:
The term center of mass is often used interchangeably with center of
gravity, but they are physically different concepts. They happen to
coincide in a uniform gravitational field, but where gravity is not
uniform, center of gravity refers to the mean location of the
gravitational force acting on a body. This results in small but
measurable gravitational torque that must be accounted for in the
operation of artificial satellites.
http://www.continuousphysics.com/Bullet/BulletFull/classbtRigidBody.html
I'm calculating shortest path of a robot on a plane with polygonal obstacles. Everything works well and fast, no problems there. But, how to smoothen the path so it becomes curvy ?
Below is a picture of a path connecting vertices with a straight line.
P.S
Robot is just a circle.
This paper might be useful. It looks like it's a non-trivial problem. Abstract:
Automatic graph drawers need to compute paths among ver- tices of a simple polygon which besides remaining in the interior need to exhibit certain aesthetic properties. Some of these require the incorpo- ration of some information about the polygonal shape without being too far from the actual shortest path. We present an algorithm to compute a locally convex region that “contains” the shortest Euclidean path among two vertices of a simple polygon. The region has a boundary shape that “follows” the shortest path shape. A cubic Bezier spline in the region in- terior provides a “short and smooth” collision free curve between the two given vertices. The obtained results appear to be aesthetically pleasant and the methods used may be of independent interest. They are elemen- tary and implementable. Figure 7 is a sample output produced by our current implementation.
I used to play with path calculation techniques a lot when trying to make realistic flying sequences to be rendered in Teragen. I initially tried using Bézier Curves.
But discovered that (for flying at least) they aren't that useful. The reason is that the curvature between curves is discontinuous, and so cannot be used to calculate a continuous correct banking angle for a fly-by. Also, it's hard to be sure that the curve doesn't intersect an mountain.
I digress. The way I eventually settled on was a simple mass-spring based path, and relax it into submission.
Subdivide the path into lots of little segments, the more the merrier. For each point, move it a little bit in a direction so as to reduce the angle between it and its neighbours, and way from the obstacles. Repeat many times until the path has settled down.
k = 0.01 // Adjust the values of k and j to your liking.
j = 0.01 // Small values take longer to settle. Larger values are unstable.
For each point P
normal_vector = vector_to_previous_point + vector_to_next_point
obstacle_vector = vector_to_nearest_obstacle
obstacle_distance = magnitude(obstacle_vector)
obstacle_vector *= obstacle_distance^2
P += (normal_vector * k) - (obstacle_vector * j)
The benefit of these kind of finite element relaxation techniques is that you can program all kinds of constraints into it, and the path will settle on some compromise between them, depending on the weights (j and k in this case).
If you're into robotics, why not come and join the Robotics Proposal?
Can't you just make the path curvy in the actual execution of the path following algorithm? If you leave the path as is (i.e. connected straight lines), implementing a look ahead distance of ~1 meter (this value will depend on the speed of your robot and the amount you've padded the configuration space to avoid obstacles) in the control algorithm that calculates the velocity of each wheel will automatically smooth out the path without any need for preprocessing.
Here's a quick images of what I mean...the red dotted-line is the path that is actually executed by the robot when you control to a point based on a lookahead distance. A lookahead distance just computes a point further down the path by some arbitrary distance.
Again, the only thing you have to worry about is how much you're padding obstacles to make sure you avoid hitting them. Normally I believe the area of an obstacle is padded by half the robot's radius, but if you're controlling to a lookahead distance you may have to make this slightly larger.
In the case of a robot we can't know the future. We have to draw each point knowing only the location of the robot and the obstacles. The usual method for making curved paths of minimum length is to model the robot with a circle and move the circle so it remains in contact with the obstacles. Just keep one radius away and the turns will be curves.
If you want curves and NOT minimum distance try making the above radius proportional to the distance you are from a polygon vertex.
The Bezier curves idea only works to make the path curved in retrospect. It changes where the robot ha been. Usually with robots changing the past is called "cheating". One way to avoid having to change the path you've already walked is to look ahead. But can the robot see around corners? You have to specify the rules better.
I am doing a mashup using Google Maps under Grails where users can create geofences by selecting a point on the map and a radius. This get stored on my database and the application receives constantly a set of coordinates from a GPS device.
I would like to compare the received coordinates with the area stored in the circles. If the point is inside (or outside) the circle the program will fire an action. However, I would like to know how I can find out if the coordinates are located inside/outside the circle. There is a Javascript library which allows doing this but I need to do this on the server.
Is there a Java (or even Groovy) library for this?
How would you implement it?
if distance from point to center of circle is <= radius of circle then it is inside the circle.
if the area is made of more than one circle than compare to all the circles... it won't take that long.
java.awt.geom.Point2D.Double is perfect for this.
Well, if it doesn't need to be "perfect", you don't need to worry about plotting circles or anything like that. You can just take the two locations (the location you want to test, and the center of the circle) and use Pythagorus to find the distance. If that distance is less than the radius of the circle, it's inside.
There is a caveat to take into consideration, however: the reason this wouldn't be perfect is that that for your points, you're probably going to get a latitude and longitude...and the Earth is a sphere. So near the poles of the Earth this will kind of fall apart. But it may well be good enough for what you're doing.
Sadly, most of the responses here won't work for you conveniently, because GPS coordinates are in units of degrees. You will need something to convert from two points in Degrees of latitude and longitude to a great circle distance, which simple Pythagorean theorem falls short of.
If you're using Google maps API, you can probably do everything you need using GLatLng. As other posters have noted, You can determine the distance between two points is less than the radius of the specified circle. Specifically GLatLng.distance(other:GLatLng) returns the meters distance between too GPS locations.
To actually display the circles requires a bit more finesse. You will need to create a GPolygon to draw the circumference of the circle. You can find a number of free JavaScript functions that can do this for you.
Victor and Beska have the correct answer. That is, if the distance between the point and the center is less than the radius, then it's in the circle.
For the great circle distance between two points, you can use GeoTools' GeodeticCalculator. In particular you set the point and radius using setStartingGeographicPoint and setDestinationGeographicPoint followed by calling getOrthodromicDistance which will return the distance.
You want to find the vector that is the distance between the selected coordinate and the center of the circle, then compute the square distance between the selected coordinate and the center of the circle by squaring the components of the vector and adding them together; if that scalar (the squared distance) is less than the square of the radius, the point is within the circle.
This method avoids having to take a square root, and is just as accurate as normal distance comparison.
One possibility is to calculate the distance from the centerpoint and compare it to the radius.
Depending on you application you may be have to take into account that the world is a sphere and not 2Dimensional. To calcualte a distance on earth you can use this formula.
Since you are using Google Maps and for geographical distances spherical geometry holds rather than euclidean geometry. However if it is relativley smaller distance like a parking lot etc. then you can use euclidean distance formula (http://en.wikipedia.org/wiki/Distance) to find out whether the point is inside or outside the circle.
I presume you know the coordinates of the circle's center C(xc, yc) and its radius, R. Then for a given point P(x1, y1) find the euclidean distance, D as
square-root((x1-xc)^2 + (y1-yc)^2)). If D > R, the point lies outside the circle. If D < R, the point lies inside the circle. If D = R, the point lies on the circumference of the circle.
In case you are doing your measurements over larger distances then you should rather look for Geodesics (please check this http://en.wikipedia.org/wiki/Great-circle_distance).
I hope it helps.
cheers