ppovb5fc7/gazebo/test/integration/world_reset.cc

433 lines
14 KiB
C++

/*
* Copyright (C) 2014 Open Source Robotics Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#include <string.h>
#include "gazebo/physics/physics.hh"
#include "gazebo/test/ServerFixture.hh"
#include "gazebo/test/helper_physics_generator.hh"
using namespace gazebo;
typedef std::tr1::tuple<const char *, const char *, int> string2_int;
class WorldResetTest : public ServerFixture,
public ::testing::WithParamInterface<string2_int>
{
/// \brief Test to see if model pose is reset when the world is reset
/// \param[in] _physicsEngine Physics engine type.
/// \param[in] _world Name of world to load
/// \param[in] _resets Number of resets to perform in the test
public: void ModelPose(const std::string &_physicsEngine,
const std::string &_world, const int _resets);
/// \brief Test to see if nested model pose is reset when the world is reset
/// \param[in] _physicsEngine Physics engine type.
/// \param[in] _world Name of world to load
/// \param[in] _resets Number of resets to perform in the test
public: void NestedModelPose(const std::string &_physicsEngine,
const std::string &_world, const int _resets);
/// \brief Test resetting different worlds
/// \param[in] _physicsEngine Physics engine type.
/// \param[in] _world Name of world to load
/// \param[in] _resets Number of resets to perform in the test
public: void WorldName(const std::string &_physicsEngine,
const std::string &_world, const int _resets);
};
class WorldControlResetTest : public ServerFixture,
public ::testing::WithParamInterface<const char *>
{
/// \brief Test to see if model pose is reset when the world is reset through
/// world_control topic
/// \param[in] _physicsEngine Physics engine type.
public: void ModelOverlapReset(const std::string &_physicsEngine);
};
/////////////////////////////////////////////////
void WorldControlResetTest::ModelOverlapReset(const std::string &_physicsEngine)
{
if (_physicsEngine == "simbody")
{
gzerr << "Simbody fails this test due to issue #1957" << std::endl;
return;
}
Load("worlds/empty.world", true, _physicsEngine);
physics::WorldPtr world = physics::get_world("default");
ASSERT_TRUE(world != NULL);
physics::PhysicsEnginePtr physics = world->GetPhysicsEngine();
ASSERT_TRUE(physics != NULL);
EXPECT_EQ(physics->GetType(), _physicsEngine);
double dt = physics->GetMaxStepSize();
unsigned int steps = 250;
// Step forward, verify time increasing
world->Step(steps);
double simTime = world->GetSimTime().Double();
EXPECT_NEAR(simTime, dt*steps, dt);
// spawn a box with known initial pose
ignition::math::Pose3d initialPose(1, 2, 0.0, 0, 0, 1.57);
math::Vector3 size(1, 1, 1);
SpawnBox("box", size, initialPose.Pos(), initialPose.Rot().Euler(), false);
physics::ModelPtr model = world->GetModel("box");
ASSERT_TRUE(model != NULL);
// spawn another box that overlaps with the previous box
ignition::math::Pose3d initialPose2(1.2, 2, 0.5, 0, 0, 0);
SpawnBox("box2", size, initialPose2.Pos(), initialPose2.Rot().Euler(), false);
physics::ModelPtr model2 = world->GetModel("box2");
ASSERT_TRUE(model2 != NULL);
// physics engine has not stepped yet since the boxes were spawned so they
// should stay overlapped. Verify pose
EXPECT_EQ(model->GetWorldPose(), initialPose);
EXPECT_EQ(model2->GetWorldPose(), initialPose2);
// Step forward, verify time increasing
world->Step(steps);
double simTime2 = world->GetSimTime().Double();
EXPECT_NEAR(simTime2, simTime + dt*steps, dt);
// physics engine has stepped, verify the models are pushed apart
// Note: DART doesn't really mind overlapping models
if (_physicsEngine != "dart")
{
EXPECT_NE(model->GetWorldPose(), initialPose);
EXPECT_NE(model2->GetWorldPose(), initialPose2);
}
// Create a publisher to reset gzserver
gazebo::transport::PublisherPtr pub =
node->Advertise<gazebo::msgs::WorldControl>(
"/gazebo/default/world_control");
pub->WaitForConnection();
// Reset world, verify time == 0
gazebo::msgs::WorldControl msg;
msg.mutable_reset()->set_all(true);
pub->Publish(msg);
int sleep = 0;
int maxSleep = 20;
// Wait for sim time to be reset
while (sleep < maxSleep)
{
simTime = world->GetSimTime().Double();
if (ignition::math::equal(simTime, 0.0, dt))
break;
sleep++;
gazebo::common::Time::MSleep(100);
}
simTime = world->GetSimTime().Double();
EXPECT_NEAR(simTime, 0.0, dt);
// verify boxes have moved back to initial pose and they are not pushed
// apart
EXPECT_EQ(model->GetWorldPose(), initialPose);
EXPECT_EQ(model2->GetWorldPose(), initialPose2);
}
/////////////////////////////////////////////////
TEST_P(WorldControlResetTest, ModelOverlapReset)
{
ModelOverlapReset(GetParam());
}
/////////////////////////////////////////////////
void WorldResetTest::ModelPose(const std::string &_physicsEngine,
const std::string &_world, const int _resets)
{
if (_physicsEngine == "simbody" &&
_world.find("pr2") != std::string::npos)
{
gzerr << "Simbody fails this test with the PR2 due to issue #1672"
<< std::endl;
return;
}
if (_physicsEngine == "simbody" &&
_world.find("nested_model") != std::string::npos)
{
gzerr << "Simbody fails this test with nested models due to issue #1718"
<< std::endl;
return;
}
if (_physicsEngine == "dart" &&
_world.find("pr2") != std::string::npos)
{
gzerr << "Abort test since dart does not support ray sensor in PR2, "
<< "Please see issue #911.\n";
return;
}
Load(_world, true, _physicsEngine);
physics::WorldPtr world = physics::get_world("default");
ASSERT_TRUE(world != NULL);
physics::PhysicsEnginePtr physics = world->GetPhysicsEngine();
ASSERT_TRUE(physics != NULL);
EXPECT_EQ(physics->GetType(), _physicsEngine);
double dt = physics->GetMaxStepSize();
unsigned int steps = 250;
// Step forward, verify time increasing
world->Step(steps);
double simTime = world->GetSimTime().Double();
EXPECT_NEAR(simTime, dt*steps, dt);
ignition::math::Pose3d initialPose(1, 2, 0.5, 0, 0, 1.57);
// spawn a box with known initial pose
math::Vector3 size(1, 1, 1);
SpawnBox("box", size, initialPose.Pos(), initialPose.Rot().Euler(), false);
physics::ModelPtr model = world->GetModel("box");
ASSERT_TRUE(model != NULL);
// verify box pose
EXPECT_EQ(model->GetWorldPose(), initialPose);
// move box to new pose
ignition::math::Pose3d newPose(4, 5, 0.5, 0, 0, 0);
model->SetWorldPose(newPose);
EXPECT_EQ(model->GetWorldPose(), newPose);
// Reset world repeatedly
for (int i = 0; i < _resets; ++i)
{
// Reset world, verify time == 0
world->Reset();
simTime = world->GetSimTime().Double();
EXPECT_NEAR(simTime, 0.0, dt);
// Step forward, verify time increasing
world->Step(steps);
simTime = world->GetSimTime().Double();
EXPECT_NEAR(simTime, dt*steps, dt);
}
// verify box has moved back to initial pose
EXPECT_EQ(model->GetWorldPose(), initialPose);
}
/////////////////////////////////////////////////
TEST_P(WorldResetTest, ModelPose)
{
std::string physics = std::tr1::get<0>(GetParam());
std::string worldName = std::tr1::get<1>(GetParam());
int resets = std::tr1::get<2>(GetParam());
gzdbg << "Physics engine [" << physics << "] "
<< "world name [" << worldName << "] "
<< "reset count [" << resets << "]"
<< std::endl;
ModelPose(physics, worldName, resets);
}
/////////////////////////////////////////////////
void WorldResetTest::NestedModelPose(const std::string &_physicsEngine,
const std::string &_world,
const int _resets)
{
if (_physicsEngine == "simbody")
{
gzerr << "Nested models are not working in simbody yet, issue #1718"
<< std::endl;
return;
}
if (_physicsEngine == "dart")
{
gzerr << "Nested models are not working in dart yet, issue #1833"
<< std::endl;
return;
}
if (_world != "worlds/nested_model.world")
return;
Load(_world, true, _physicsEngine);
physics::WorldPtr world = physics::get_world("default");
ASSERT_TRUE(world != NULL);
physics::PhysicsEnginePtr physics = world->GetPhysicsEngine();
ASSERT_TRUE(physics != NULL);
EXPECT_EQ(physics->GetType(), _physicsEngine);
double dt = physics->GetMaxStepSize();
unsigned int steps = 250;
// Step forward, verify time increasing
world->Step(steps);
double simTime = world->GetSimTime().Double();
EXPECT_NEAR(simTime, dt*steps, dt);
physics::ModelPtr model = world->GetModel("model_00");
ASSERT_TRUE(model != NULL);
// store all initial pose
std::list<ignition::math::Pose3d> modelPoses;
std::list<physics::ModelPtr> models;
models.push_back(model);
while (!models.empty())
{
physics::ModelPtr m = models.front();
modelPoses.push_back(m->GetWorldPose().Ign());
models.pop_front();
for (const auto &nested : m->NestedModels())
models.push_back(nested);
}
// move model to new pose
ignition::math::Pose3d newPose(9, 5, 2.5, 0, 0, 0);
model->SetWorldPose(newPose);
EXPECT_EQ(model->GetWorldPose(), newPose);
// Reset world repeatedly
for (int i = 0; i < _resets; ++i)
{
// Reset world, verify time == 0
world->Reset();
simTime = world->GetSimTime().Double();
EXPECT_NEAR(simTime, 0.0, dt);
// Step forward, verify time increasing
world->Step(steps);
simTime = world->GetSimTime().Double();
EXPECT_NEAR(simTime, dt*steps, dt);
// verify all nested models have moved back to initial pose
models.clear();
models.push_back(model);
auto modelPosesCopy = modelPoses;
while (!models.empty())
{
physics::ModelPtr m = models.front();
EXPECT_EQ(m->GetWorldPose(), modelPosesCopy.front());
models.pop_front();
modelPosesCopy.pop_front();
for (const auto &nested : m->NestedModels())
models.push_back(nested);
}
}
}
/////////////////////////////////////////////////
TEST_P(WorldResetTest, NestedModelPose)
{
std::string physics = std::tr1::get<0>(GetParam());
std::string worldName = std::tr1::get<1>(GetParam());
int resets = std::tr1::get<2>(GetParam());
gzdbg << "Physics engine [" << physics << "] "
<< "world name [" << worldName << "] "
<< "reset count [" << resets << "]"
<< std::endl;
NestedModelPose(physics, worldName, resets);
}
/////////////////////////////////////////////////
void WorldResetTest::WorldName(const std::string &_physicsEngine,
const std::string &_world, const int _resets)
{
if (_physicsEngine == "simbody" &&
_world.find("pr2") != std::string::npos)
{
gzerr << "Simbody fails this test with the PR2 due to issue #1672"
<< std::endl;
return;
}
if (_physicsEngine == "simbody" &&
_world.find("nested_model") != std::string::npos)
{
gzerr << "Simbody fails this test with nested models due to issue #1718"
<< std::endl;
return;
}
if (_physicsEngine == "dart" &&
_world.find("pr2") != std::string::npos)
{
gzerr << "Abort test since dart does not support ray sensor in PR2, "
<< "Please see issue #911.\n";
return;
}
Load(_world, true, _physicsEngine);
physics::WorldPtr world = physics::get_world("default");
ASSERT_TRUE(world != NULL);
physics::PhysicsEnginePtr physics = world->GetPhysicsEngine();
ASSERT_TRUE(physics != NULL);
EXPECT_EQ(physics->GetType(), _physicsEngine);
double dt = physics->GetMaxStepSize();
unsigned int steps = 250;
// Step forward, verify time increasing
world->Step(steps);
double simTime = world->GetSimTime().Double();
EXPECT_NEAR(simTime, dt*steps, dt);
// Reset world repeatedly
for (int i = 0; i < _resets; ++i)
{
// Reset world, verify time == 0
world->Reset();
simTime = world->GetSimTime().Double();
EXPECT_NEAR(simTime, 0.0, dt);
// Step forward, verify time increasing
world->Step(steps);
simTime = world->GetSimTime().Double();
EXPECT_NEAR(simTime, dt*steps, dt);
}
}
/////////////////////////////////////////////////
TEST_P(WorldResetTest, WorldName)
{
std::string physics = std::tr1::get<0>(GetParam());
std::string worldName = std::tr1::get<1>(GetParam());
int resets = std::tr1::get<2>(GetParam());
gzdbg << "Physics engine [" << physics << "] "
<< "world name [" << worldName << "] "
<< "reset count [" << resets << "]"
<< std::endl;
WorldName(physics, worldName, resets);
}
INSTANTIATE_TEST_CASE_P(PhysicsEngines, WorldControlResetTest,
PHYSICS_ENGINE_VALUES);
INSTANTIATE_TEST_CASE_P(PhysicsEngines, WorldResetTest,
::testing::Combine(PHYSICS_ENGINE_VALUES,
::testing::Values("worlds/empty.world",
"worlds/pr2.world",
"worlds/nested_model.world"),
::testing::Range(1, 3)));
/////////////////////////////////////////////////
int main(int argc, char **argv)
{
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}