So this is a pretty simple problem, given a circle of diameter 60 units, find the largest rectangle that fits in it. Using some pretty simple maths we know it'll have an area of 1800 units.
So I created this AMPL model
param diameter := 60;
param radius := diameter / 2;
var tlX; # top left x of the rectangle
var tlY; # top left y of the rectangle
subject to tlInside: sqrt(tlX*tlX + tlY*tlY) < radius; # make sure its inside the circle
var brX; # bottom right x of the rect
var brY; # bottom right y of the rectangle
subject to brInside: sqrt(brX*brX + brY*brY) <= radius; # make sure its inside the circle
var xDiff = brX - tlX;
var yDiff = brY - tlY;
maximize Area: xDiff * yDiff;
First up:
option solver gurobi; solves it, but creates an area of 0. lol, wut?
Second up:
option solver HiGHS; solves it, but creates an area of 12.3873. Closer. But still not clearly near optimal
Third up:
option solver cbc; solves it, but create an area of 1820.51. This is close to the optimal (1800) but it generates the variables that violate the constraints!
All other solvers I tried couldn't even come up with a solution.
So what's going on. Seems like it's a pretty trivial problem?
You have to realize that as you model the problem you are creating a non-convex objective function over a convex set of feasible points. That is far from trivial to optimize, and any locally optimal solution may be returned as optimal. I guess this is what happens with gurobi and HiGHS.
Related
After some time searching, I have revised my question.
I have found numerous examples of ball to ball collisions, but the only ones that seem to work use Vector2d or Vector2D.
This is a problem, because I am only allowed to use the regular java library, so my main question is: How do I convert the examples (which I will post below) to use what I can use?
I have several variables, both balls have the same mass, the velocities are broken into different variables, x and y. Also I have access to their x and y pos.
This is the ONLY problem left in my application.
I am at a total loss on how to convert the below example.
// get the mtd
Vector2d delta = (position.subtract(ball.position));
float d = delta.getLength();
// minimum translation distance to push balls apart after intersecting
Vector2d mtd = delta.multiply(((getRadius() + ball.getRadius())-d)/d);
// resolve intersection --
// inverse mass quantities
float im1 = 1 / getMass();
float im2 = 1 / ball.getMass();
// push-pull them apart based off their mass
position = position.add(mtd.multiply(im1 / (im1 + im2)));
ball.position = ball.position.subtract(mtd.multiply(im2 / (im1 + im2)));
// impact speed
Vector2d v = (this.velocity.subtract(ball.velocity));
float vn = v.dot(mtd.normalize());
// sphere intersecting but moving away from each other already
if (vn > 0.0f) return;
// collision impulse
float i = (-(1.0f + Constants.restitution) * vn) / (im1 + im2);
Vector2d impulse = mtd.multiply(i);
// change in momentum
this.velocity = this.velocity.add(impulse.multiply(im1));
ball.velocity = ball.velocity.subtract(impulse.multiply(im2));
Here is the URL for the question:
http://stackoverflow.com/questions/345838/ball-to-ball-collision-detection-and-handling
And I have taken a look at his source code.
Thank you for taking the time to read this issue.
SUCCESS!
I have found how to use Vector2d, and it works PERFECTLY!
Will edit later with answer!
I'm implementing my own 3d engine in c# based on a really basic 3d open-source engine in JavaScript called a3. I don't know If I have 100% understand you but It sounds like you can only find examples with Vector2d but you are not allowed to use that class?
I that is the case, as you can imagine javascript does not have native Vector2d types so someone had to implement. Don't be afraid of giving it a try, is just a few high school maths functions, you should be able to implement your own Vector2d class in just a few minutes
The following link contain implementations if vector2d, vector3d, vector4d, matrix3, and matrix4 in javascript: https://github.com/paullewis/a3/tree/master/src/js/core/math hope it helps :)
I've used Nick Vellios' tutorial to create radial gravity with a Box2D object. I am aware of Make a Vortex here on SO, but I couldn't figure out how to implement it in my project.
I have made a vortex object, which is a Box2D circleShape sensor that rotates with a consistent angular velocity. When other Box2D objects contact this vortex object I want them to rotate around at the same angular velocity as the vortex, gradually getting closer to the vortex's centre. At the moment the object is attracted to the vortex's centre but it will head straight for the centre of the vortex, rather than spinning around it slowly like I want it to. It will also travel in the opposite direction than the vortex as well as with the vortex's rotation.
Given a vortex and a box2D body, how can I set the box2d body to rotate with the vortex as it gets 'sucked in'.
I set the rotation of the vortex when I create it like this:
b2BodyDef bodyDef;
bodyDef.type = b2_dynamicBody;
bodyDef.angle = 2.0f;
bodyDef.angularVelocity = 2.0f;
Here is how I'm applying the radial gravity, as per Nick Vellios' sample code.
-(void)applyVortexForcesOnSprite:(CCSpriteSubclass*)sprite spriteBody:(b2Body*)spriteBody withVortex:(Vortex*)vortex VortexBody:(b2Body*)vortexBody vortexCircleShape:(b2CircleShape*)vortexCircleShape{
//From RadialGravity.xcodeproj
b2Body* ground = vortexBody;
b2CircleShape* circle = vortexCircleShape;
// Get position of our "Planet" - Nick
b2Vec2 center = ground->GetWorldPoint(circle->m_p);
// Get position of our current body in the iteration - Nick
b2Vec2 position = spriteBody->GetPosition();
// Get the distance between the two objects. - Nick
b2Vec2 d = center - position;
// The further away the objects are, the weaker the gravitational force is - Nick
float force = 1 / d.LengthSquared(); // 150 can be changed to adjust the amount of force - Nick
d.Normalize();
b2Vec2 F = force * d;
// Finally apply a force on the body in the direction of the "Planet" - Nick
spriteBody->ApplyForce(F, position);
//end radialGravity.xcodeproj
}
Update I think iForce2d has given me enough info to get on my way, now it's just tweaking. This is what I'm doing at the moment, in addition to the above code. What is happening is the body gains enough velocity to exit the vortex's gravity well - somewhere I'll need to check that the velocity stays below this figure. I'm a little concerned I'm not taking into account the object's mass at the moment.
b2Vec2 vortexVelocity = vortexBody->GetLinearVelocityFromWorldPoint(spriteBody->GetPosition() );
b2Vec2 vortexVelNormal = vortexVelocity;
vortexVelNormal.Normalize();
b2Vec2 bodyVelocity = b2Dot( vortexVelNormal, spriteBody->GetLinearVelocity() ) * vortexVelNormal;
//Using a force
b2Vec2 vel = bodyVelocity;
float forceCircleX = .6 * bodyVelocity.x;
float forceCircleY = .6 * bodyVelocity.y;
spriteBody->ApplyForce( b2Vec2(forceCircleX,forceCircleY), spriteBody->GetWorldCenter() );
It sounds like you just need to apply another force according to the direction of the vortex at the current point of the body. You can use b2Body::GetLinearVelocityFromWorldPoint to find the velocity of the vortex at any point in the world. From Box2D source:
/// Get the world linear velocity of a world point attached to this body.
/// #param a point in world coordinates.
/// #return the world velocity of a point.
b2Vec2 GetLinearVelocityFromWorldPoint(const b2Vec2& worldPoint) const;
So that would be:
b2Vec2 vortexVelocity = vortexBody->GetLinearVelocityFromWorldPoint( suckedInBody->GetPosition() );
Once you know the velocity you're aiming for, you can calculate how much force is needed to go from the current velocity, to the desired velocity. This might be helpful: http://www.iforce2d.net/b2dtut/constant-speed
The topic in that link only discusses a 1-dimensional situation. For your case it is also essentially 1-dimensional, if you project the current velocity of the sucked-in body onto the vortexVelocity vector:
b2Vec2 vortexVelNormal = vortexVelocity;
vortexVelNormal.Normalize();
b2Vec2 bodyVelocity = b2Dot( vortexVelNormal, suckedInBody->GetLinearVelocity() ) * vortexVelNormal;
Now bodyVelocity and vortexVelocity will be in the same direction and you can calculate how much force to apply. However, if you simply apply enough force to match the vortex velocity exactly, the sucked in body will probably go into orbit around the vortex and never actually get sucked in. I think you would want to make the force quite a bit less than that, and I would scale it down according to the gravity strength as well, otherwise the sucked-in body will be flung away sideways as soon as it contacts the outer edge of the vortex. It could take a lot of tweaking to get the effect you want.
EDIT:
The force you apply should be based on the difference between the current velocity (bodyVelocity) and the desired velocity (vortexVelocity), ie. if the body is already moving with the vortex then you don't need to apply any force. Take a look at the last code block in the sub-section titled 'Using forces' in the link I gave above. The last three lines there do pretty much what you need if you replace 'vel' and 'desiredVel' with the sizes of your bodyVelocity and vortexVelocity vectors:
float desiredVel = vortexVelocity.Length();
float currentVel = bodyVelocity.Length();
float velChange = desiredVel - currentVel;
float force = body->GetMass() * velChange / (1/60.0); //for a 1/60 sec timestep
body->ApplyForce( b2Vec2(force,0), body->GetWorldCenter() );
But remember this would probably put the body into orbit, so somewhere along the way you would want to reduce the size of the force you apply, eg. reduce 'desiredVel' by some percentage, reduce 'force' by some percentage etc. It would probably look better if you could also scale the force down so that it was zero at the outer edge of the vortex.
I had a project where I had asteroids swirling around a central point (there are things jumping between them...which is a different point).
They are connected to the "center" body via b2DistanceJoints.
You can control the joint length to make them slowly spiral inward (or outward). This gives you find grain control instead of balancing force control, which may be difficult.
You also apply tangential force to make them circle the center.
By applying different (or randomly changing) tangential forces, you can make the
crash into each other, etc.
I posted a more complete answer to this question here.
I am trying to calculate the forces that will act on circular objects in the event of a collision. Unfortunately, my mechanics is slightly rusty so i'm having a bit of trouble.
I have an agent class with members
vector position // (x,y)
vector velocity // (x,y)
vector forward // (x,y)
float radius // radius of the agent (all circles)
float mass
So if we have A,B:Agent, and in the next time step the velocity is going to change the position. If a collision is going to occur I want to work out the force that will act on the objects.
I know Line1 = (B.position-A.position) is needed to work out the angle of the resultant force but how to calculate it is baffling me when I have to take into account current velocity of the vehicle along with the angle of collision.
arctan(L1.y,L1.x) is am angle for the force (direction can be determined)
sin/cos are height/width of the components
Also I know to calculate the rotated axis I need to use
x = cos(T)*vel.x + sin(T)*vel.y
y = cos(T)*vel.y + sin(T)*vel.x
This is where my brain can't cope anymore.. Any help would be appreciated.
As I say, the aim is to work out the vector force applied to the objects as I have already taken into account basic physics.
Added a little psudocode to show where I was starting to go with it..
A,B:Agent
Agent {
vector position, velocity, front;
float radius,mass;
}
vector dist = B.position - A.position;
float distMag = dist.magnitude();
if (distMag < A.radius + B.radius) { // collision
float theta = arctan(dist.y,dist.x);
flost sine = sin(theta);
float cosine = cos(theta);
vector newAxis = new vector;
newAxis.x = cosine * dist .x + sine * dist .y;
newAxis.y = cosine * dist .y - sine * dist .x;
// Converted velocities
vector[] vTemp = {
new vector(), new vector() };
vTemp[0].x = cosine * agent.velocity.x + sine * agent.velocity.y;
vTemp[0].y = cosine * agent.velocity.y - sine * agent.velocity.x;
vTemp[1].x = cosine * current.velocity.x + sine * current.velocity.y;
vTemp[1].y = cosine * current.velocity.y - sine * current.velocity.x;
Here's to hoping there's a curious maths geek on stack..
Let us assume, without loss of generality, that we are in the second object's reference frame before the collision.
Conservation of momentum:
m1*vx1 = m1*vx1' + m2*vx2'
m1*vy1 = m1*vy1' + m2*vy2'
Solving for vx1', vy1':
vx1' = vx1 - (m2/m1)*vx2'
vy1' = vy1 - (m2/m1)*vy2'
Secretly, I will remember the fact that vx1'*vx1' + vy1'*vy1' = v1'*v1'.
Conservation of energy (one of the things elastic collisions give us is that angle of incidence is angle of reflection):
m1*v1*v1 = m1*v1'*v1' + m2*v2'+v2'
Solving for v1' squared:
v1'*v1' = v1*v1 - (m2/m1)v2'*v2'
Combine to eliminate v1':
(1-m2/m1)*v2'*v2' = 2*(vx2'*vx1+vy2'*vy1)
Now, if you've ever seen a stationary poolball hit, you know that it flies off in the direction of the contact normal (this is the same as your theta).
v2x' = v2'cos(theta)
v2y' = v2'sin(theta)
Therefore:
v2' = 2/(1-m2/m1)*(vx1*sin(theta)+vy1*cos(theta))
Now you can solve for v1' (either use v1'=sqrt(v1*v1-(m2/m1)*v2'*v2') or solve the whole thing in terms of the input variables).
Let's call phi = arctan(vy1/vx1). The angle of incidence relative to the tangent line to the circle at the point of intersection is 90-phi-theta (pi/2-phi-theta if you prefer). Add that again for the reflection, then convert back to an angle relative to the horizontal. Let's call the angle of incidence psi = 180-phi-2*theta (pi-phi-2*theta). Or,
psi = (180 or pi) - (arctan(vy1/vx1))-2*(arctan(dy/dx))
So:
vx1' = v1'sin(psi)
vy1' = v1'cos(psi)
Consider: if these circles are supposed to be solid 3D spheres, then use a mass proportional to radius-cubed for each one (note that the proportionality constant cancels out). If they are supposed to be disklike, use mass proportional to radius-squared. If they are rings, just use radius.
Next point to consider: Since the computer updates at discrete time events, you actually have overlapping objects. You should back out the objects so that they don't overlap before computing the new location of each object. For extra credit, figure out the time that they should have intersected, then move them in the new direction for that amount of time. Note that this time is just the overlap / old velocity. The reason that this is important is that you might imagine a collision that is computed that causes the objects to still overlap (causing them to collide again).
Next point to consider: to translate the original problem into this problem, just subtract object 2's velocity from object 1 (component-wise). After the computation, remember to add it back.
Final point to consider: I probably made an algebra error somewhere along the line. You should seriously consider checking my work.
I want to simulate a free fall and a collision with the ground (for example a bouncing ball). The object will fall in a vacuum - an air resistance can be omitted. A collision with the ground should causes some energy loss so finally the object will stop moving. I use JOGL to render a point which is my falling object. A gravity is constant (-9.8 m/s^2).
I found an euler method to calculate a new position of the point:
deltaTime = currentTime - previousTime;
vel += acc * deltaTime;
pos += vel * deltaTime;
but I'm doing something wrong. The point bounces a few times and then it's moving down (very slow).
Here is a pseudocode (initial pos = (0.0f, 2.0f, 0.0f), initial vel(0.0f, 0.0f, 0.0f), gravity = -9.8f):
display()
{
calculateDeltaTime();
velocity.y += gravity * deltaTime;
pos.y += velocity.y * deltaTime;
if(pos.y < -2.0f) //a collision with the ground
{
velocity.y = velocity.y * energyLoss * -1.0f;
}
}
What is the best way to achieve a realistic effect ? How the euler method refer to the constant acceleration equations ?
Because floating points dont round-up nicely, you'll never get at a velocity that's actually 0. You'd probably get something like -0.00000000000001 or something.
you need to to make it 0.0 when it's close enough. (define some delta.)
To expand upon my comment above, and to answer Tobias, I'll add a complete answer here.
Upon initial inspection, I determined that you were bleeding off velocity to fast. Simply put, the relationship between kinetic energy and velocity is E = m v^2 /2, so after taking the derivative with respect to velocity you get
delta_E = m v delta_v
Then, depending on how energyloss is defined, you can establish the relationship between delta_E and energyloss. For instance, in most cases energyloss = delta_E/E_initial, then the above relationship can be simplified as
delta_v = energyloss*v_initial / 2
This is assuming that the time interval is small allowing you to replace v in the first equation with v_initial, so you should be able to get away with it for what your doing. To be clear, delta_v is subtracted from velocity.y inside your collision block instead of what you have.
As to the question of adding air-resistance or not, the answer is it depends. For small initial drop heights, it won't matter, but it can start to matter with smaller energy losses due to bounce and higher drop points. For a 1 gram, 1 inch (2.54 cm) diameter, smooth sphere, I plotted time difference between with and without air friction vs. drop height:
For low energy loss materials (80 - 90+ % energy retained), I'd consider adding it in for 10 meter, and higher, drop heights. But, if the drops are under 2 - 3 meters, I wouldn't bother.
If anyone wants the calculations, I'll share them.
I wanted to simulate the following through animation :
A ball starts with a certain velocity at the bottom most point of
a vertical circular loop and keeps rolling in it until its velocity permits.
For this, I wanted to find velocity/x/y vs. time equation.
For e.g. if the ball had mass : 5Kg, radius of the circular loop = 10m,
and initial velocity of the ball is 200 m/s, what will its velocity and (x,y) position
be after 5 seconds?
thanks.
Sliding, frictionless case with a point-particle ball
In this case we aren't worrying about rotational energy and are assuming that the ball is actually a point particle. Then, in order for the ball to stay on at the top, the centripetal force condition has to be satisfied:
m * v_top^2 / r = m * g
so
v_top = sqrt(r * g)
So the minimum initial velocity is determined by:
1 / 2 * m * v0^2 >= 1 / 2 * m * v_top^2 + m * g * 2 * r
v0 >= sqrt(5 * r * g)
This is similar to what Pete said, except that he forgot the centripetal force condition to stay on at the top.
Next, the acceleration tangential to the track is given by:
a = - g * sin(theta)
but a = r * alpha = r * d^2(theta)/dt^2 where alpha is the rotational acceleration. Thus, we get
r * d^2(theta)/dt^2 = g * sin(theta)
However, I don't know of an analytical solution to this differential equation and Mathematica was stumbling with finding one too. You can't just move the dts to the other side and integrate because theta is a function of t. I would recommend solving it by numerical means such as a Runga-Kutte or maybe the Verlet method. I solved it using Mathematica for the parameters you gave, but with the ball moving so quickly, it doesn't really slow down much in going around. When I lowered the initial velocity though, I was able to see the speeding up and slowing down by plotting theta as a function of time.
Adding in other things like a finite ball radius, rotational energy and friction are certainly doable, but I would worry about being able to solve this first case before moving on because it only gets more complicated from here. By the way, with the friction you will have to choose some kinetic coefficient of friction for your given materials which will of course be proportional to the normal force exerted on the ball by the track which can be solved for by summing the force components along the radius of the circle and don't forget to include the centripetal force condition.
If you haven't done this sort of physics before, I definitely recommend getting a introductory good book on physics (with calculus) and working through it. You only need to bother with the sections that apply to mechanics though that is a very large section of the book probably. There might be better routes to pursue though like some of the resources in this question.
If there are no acceleration (x,y) =(xstart+ vx*time ,ystart + vy*time) and speed remain the same, and it is not related to the radius
Since the velocity is constant you will have an angular velocity of omega = vel / radius. You will obtain how many radians you ball will move per second over its circular path.
To get the position at time t you just have to exploit polar coordinates:
x = x_center + sin( 3/2*PI + omega*t)*radius
y = y_center + cos( 3/2*PI + omega*t)*radius
This because you start from bottom point of the circle (so its 3/2*PI) plus how many radiants you move every second (we obtained it from tangential velocity). All multiplied for the radius, otherwise you will consider a unity circle.
EDIT: Since you wonder how to find a position of an object that is subject to many different forces I can tell you that usually a physical engine doesn't care about finding equations of moving objects. It just applies forces to objects considering their intended motions (like your circular one) or environmental factors (like gravity or friction) and calculates coordinates step by step by applying forces and using an integrator to see the results.
Ignoring friction, the forces on the ball are gravity and the track.
First, there are two main cases - is the velocity enough for the ball to loop-the-loop or not:
initial energy = 1/2 m v² = 0.5 * 5 * 200 * 200
potential energy = m g h = 5 * 9.8 * 20
so it will go round the whole loop.
Initially the ball is at the bottom of the loop, theta = 0
The acceleration on the ball is the component of g along the track
a = g⋅sin theta
The distance travelled is theta * radius. It is also the double integral of acceleration against time.
theta ⋅ radius = double integral of acceleration against time
Integrating acceleration once gives velocity, integrating velocity gives distance.
so solve this for t:
theta ⋅ r = ∫(∫ g⋅sin theta.dt).dt
then your x and y are trivial functions of theta.
Whether you solve it analytically or numerically is up to you.
With dynamic friction, friction is usually proportional to the normal force on the bodies. So this will equal the centripetal force - proportional to the square of the angular velocity, and the component of gravity normal to the track (g sin theta)
You didn't tell anything about how you want your velocity to change. Do you have any friction model? If there is no friction, then the formulas are simple:
length = velocity*t
x = sin(length)*radius
y = -cos(length)*radius
If the velocity is changing, then you have to change length to something like
length = integral over dt[0..t] (velocity dt)
The only thing I wanted to add is the if this is real ball (sphere) with mass 5kg then it must have a diameter dia=(6*m/(PI*rho))^(1/3) where rho is the density of the material. For steel (rho=7680) the diameter is dia=0.1075 meters. Therefore the pitch radius (radius at which the center of gravity of the ball rides on) is equal to R=10-(dia/2) or R=9.9466 meters.
The problem gets a little more complex when friction is included. For one you have to consider the direction of friction (assuming dry friction theory). That depends on the amount the ball rotates in its axis and that depends on moment of inertia of the ball.
When you do the simulation you might want to monitor the total kinetic energy + the total potential energy and make sure your are not adding energy to the system (or taking away). [Don't forget to include the rotational component for the kinetic energy]
Get a standard book on dynamics, and I am sure a similar problem is already described in the book.I would recommend "Vector Mechanic for Engineers - Dynamics".