Skip to content

Commit

Permalink
Make simulator achieve 120hz instead of dropping frames to be more de…
Browse files Browse the repository at this point in the history
…terministic, switch to dantzig solver
  • Loading branch information
qhdwight committed Apr 19, 2024
1 parent 5eb699e commit 65c9dc9
Showing 1 changed file with 24 additions and 20 deletions.
44 changes: 24 additions & 20 deletions src/simulator/simulator.physics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@

namespace mrover {

// Determines the timestep for the physics update.
// Need a relatively high frequency to achive a stable simulation.
constexpr unsigned int PHYSICS_UPDATE_HZ = 120;
// Set to a very high value, so that if the computer can not keep up the above in realtime, it slows down instead of dropping frames.
// In a video game we do not want this behavior but this is robotics so we have to be deterministic.
// See: https://stackoverflow.com/questions/12778229/what-does-step-mean-in-stepsimulation-and-what-do-its-parameters-mean-in-bulle
// Important formula that needs to hold true to avoid dropping: timeStep < maxSubSteps * fixedTimeStep
constexpr int MAX_SUB_STEPS = 1024;

auto btTransformToSe3(btTransform const& transform) -> SE3d {
btVector3 const& p = transform.getOrigin();
btQuaternion const& q = transform.getRotation();
Expand All @@ -21,8 +30,8 @@ namespace mrover {

mBroadphase = std::make_unique<btDbvtBroadphase>(mOverlappingPairCache.get());

// mSolver = std::make_unique<btMultiBodyMLCPConstraintSolver>(new btDantzigSolver{});
mSolver = std::make_unique<btMultiBodyConstraintSolver>();
mSolver = std::make_unique<btMultiBodyMLCPConstraintSolver>(new btDantzigSolver{});
// mSolver = std::make_unique<btMultiBodyConstraintSolver>();

mDynamicsWorld = std::make_unique<btMultiBodyDynamicsWorld>(mDispatcher.get(), mBroadphase.get(), mSolver.get(), mCollisionConfig.get());
// mDynamicsWorld->getSolverInfo().m_minimumSolverBatchSize = 1;
Expand All @@ -43,25 +52,20 @@ namespace mrover {
}
}

// TODO(quintin): clean this up
int maxSubSteps = 0;
float updateDuration = std::clamp(std::chrono::duration_cast<std::chrono::duration<float>>(dt).count(), 0.0f, 0.1f);
[[maybe_unused]] int simStepCount = mDynamicsWorld->stepSimulation(updateDuration, maxSubSteps, 1 / 120.0f);

// // TODO(quintin): Figure out why this fails
// if (auto* mlcpSolver = dynamic_cast<btMLCPSolver*>(mDynamicsWorld->getConstraintSolver())) {
// // if (int fallbackCount = mlcpSolver->getNumFallbacks()) {
// // NODELET_WARN_STREAM_THROTTLE(1, std::format("MLCP solver failed {} times", fallbackCount));
// // }
// mlcpSolver->setNumFallbacks(0);
// }

// if (simStepCount) {
// if (simStepCount > maxSubSteps) {
// int droppedSteps = simStepCount - maxSubSteps;
// NODELET_WARN_STREAM(std::format("Dropped {} simulation steps out of {}", droppedSteps, simStepCount));
// }
// }
int simStepCount = mDynamicsWorld->stepSimulation(updateDuration, MAX_SUB_STEPS, 1.f / PHYSICS_UPDATE_HZ);

if (auto* mlcpSolver = dynamic_cast<btMLCPSolver*>(mDynamicsWorld->getConstraintSolver())) {
if (int fallbackCount = mlcpSolver->getNumFallbacks()) {
NODELET_WARN_STREAM_THROTTLE(1, std::format("MLCP solver failed {} times", fallbackCount));
}
mlcpSolver->setNumFallbacks(0);
}

if (!mHeadless && simStepCount && simStepCount > MAX_SUB_STEPS) {
int droppedSteps = simStepCount - MAX_SUB_STEPS;
NODELET_ERROR_STREAM(std::format("Dropped {} simulation steps out of {}! This should never happen unless you have a literal potatoe of a computer", droppedSteps, simStepCount));
}

linksToTfUpdate();

Expand Down

0 comments on commit 65c9dc9

Please sign in to comment.