Calculate correct impluse or force to move a Box2D body to a specific position - Box2D

被刻印的时光 ゝ 提交于 2019-12-09 01:51:04

问题


i have a question about moving a Box2D body to a specific position without using this for example.

body->SetTransform(targetVector,body->GetAngle())

I have some code which works for applyForce (here):

const float destinationControl = 0.3f;
b2Vec2 missilePosition = _physicalBody->GetPosition();
b2Vec2 diff = targetPosition - missilePosition;
float dist = diff.Length();

if (dist > 0)
{

// compute the aiming direction
b2Vec2 direction = b2Vec2(diff.x / dist, diff.y / dist);

// get the current missile velocity because we will apply a force to compensate this.
b2Vec2 currentVelocity = _physicalBody->GetLinearVelocity();

// the missile ideal velocity is the direction to the target multiplied by the max speed
b2Vec2 desireVelocity = b2Vec2(direction.x * maxSpeed, direction.y * maxSpeed);

// compensate the current missile velocity by the desired velocity, based on the control factor

b2Vec2 finalVelocity = control * (desireVelocity - currentVelocity);

// transform our velocity into an impulse (get rid of the time and mass factor)
float temp = (_physicalBody->GetMass() / normalDelta);

b2Vec2 finalForce = b2Vec2(finalVelocity.x * temp, finalVelocity.y * temp);

_physicalBody->ApplyForce(finalForce, _physicalBody->GetWorldCenter());

}

But the when the maxSpeed is to high the body move over the point to fast.

So does anyone know how to calculate a force (ApplyForce) or an impluse (ApplyLinearImpulse) to move the body to a target position (very exactly) in a specific time.

Or a solution with the code above. I mean calculate the maxSpeed to move the body in a specific time to the target position.

In my google search i found the interesting article from iforce about projected trajectory (here). Maybe this could be help too?

Thank you in advance


回答1:


I think you have it mostly correct, but you are not checking to see if the body will overshoot the target in the next time step. Here is what works for me:

b2Vec2 targetPosition = ...;
float targetSpeed = ...;

b2Vec2 direction = targetPosition - body->GetPosition();
float distanceToTravel = direction.Normalize();

// For most of the movement, the target speed is ok
float speedToUse = targetSpeed;

// Check if this speed will cause overshoot in the next time step.
// If so, we need to scale the speed down to just enough to reach
// the target point. (Assuming here a step length based on 60 fps)
float distancePerTimestep = speedToUse / 60.0f;
if ( distancePerTimestep > distanceToTravel )
    speedToUse *= ( distanceToTravel / distancePerTimestep );

// The rest is pretty much what you had already:
b2Vec2 desiredVelocity = speedToUse * direction;
b2Vec2 changeInVelocity = desiredVelocity - body->GetLinearVelocity();

b2Vec2 force = body->GetMass() * 60.0f * changeInVelocity;
body->ApplyForce( force, body->GetWorldCenter(), true );



回答2:


There is a way for single-time applied force to move by given distance (previous answer suggests that you can correct error in calculation by additional force in future frames):

public static void applyForceToMoveBy(float byX, float byY, Body body) {
    force.set(byX, byY);
    force.sub(body.getLinearVelocity());
    float mass = body.getMass();
    force.scl(mass * 30.45f);
    body.applyForceToCenter(force, true);
}

Known limitations:

1) LinearVelocity effect was not tested;
2) calculation was tested with body linear damping = 0.5f. Appreciate, if somebody know how to add it into formula;
3) magic number 30.45f - maybe this could be fixed by point 2 or by world frame delta.


来源:https://stackoverflow.com/questions/24516945/calculate-correct-impluse-or-force-to-move-a-box2d-body-to-a-specific-position

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!