in src/simulator/task_validation.cpp [344:400]
bool isTaskInSolvedState(const ::task::Task& task,
const b2WorldWithData& world) {
checkTaskValidity(task);
const b2Body* body1 = nullptr;
const b2Body* body2 = nullptr;
for (const b2Body* box2dBody = world.GetBodyList(); box2dBody != nullptr;
box2dBody = box2dBody->GetNext()) {
if (box2dBody->GetUserData() == nullptr) {
throw std::runtime_error("Found a Box2d body without userdata");
}
Box2dData* box2d_data = static_cast<Box2dData*>(box2dBody->GetUserData());
if (box2d_data == nullptr) {
throw std::runtime_error(
"Found a Box2d body with userdata that is not Box2dData");
}
if (box2d_data->object_type == Box2dData::GENERAL) {
if (box2d_data->object_id == task.bodyId1) {
body1 = box2dBody;
} else if (box2d_data->object_id == task.bodyId2) {
body2 = box2dBody;
}
}
// Found both bodies, quit loop
if (body1 != nullptr && body2 != nullptr) {
break;
}
}
if (body1 == nullptr || body2 == nullptr) {
throw std::runtime_error("Task body IDs not present in the scene");
}
const auto& thriftBody1 = task.scene.bodies[task.bodyId1];
const auto& thriftBody2 = task.scene.bodies[task.bodyId2];
// A custom check for a pair of touching balls to improve stability.
if (isTwoBallTouchingCase(thriftBody1, thriftBody2, task.relationships)) {
const auto r1 = body1->GetFixtureList()->GetShape()->m_radius;
const auto r2 = body2->GetFixtureList()->GetShape()->m_radius;
const float distance = sqrt(
geometry::squareDistance(body1->GetPosition(), body2->GetPosition()));
return distance < r1 + r2 + kBallTouchingThreshold;
}
::scene::Shape scaledPhantomShape;
if (task.__isset.phantomShape && task.phantomShape.__isset.polygon) {
scaledPhantomShape = p2mShape(task.phantomShape);
}
for (auto r = task.relationships.begin(); r != task.relationships.end();
++r) {
if (isValidRelationship(*body1, *body2, *r, scaledPhantomShape) == false) {
return false;
}
}
return true;
}