pxmlw6n2f/Gazebo_Distributed_MPI/test/integration/factory.cc

375 lines
13 KiB
C++

/*
* Copyright (C) 2012 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/math/Helpers.hh"
#include "gazebo/transport/TransportTypes.hh"
#include "gazebo/transport/Node.hh"
#include "gazebo/rendering/RenderEngine.hh"
#include "gazebo/rendering/Camera.hh"
#include "gazebo/sensors/SensorsIface.hh"
#include "gazebo/sensors/CameraSensor.hh"
#include "gazebo/test/ServerFixture.hh"
#include "images_cmp.h"
#include "gazebo/test/helper_physics_generator.hh"
using namespace gazebo;
class FactoryTest : public ServerFixture,
public testing::WithParamInterface<const char*>
{
public: void BoxSdf(const std::string &_physicsEngine);
public: void Box(const std::string &_physicsEngine);
public: void Sphere(const std::string &_physicsEngine);
public: void Cylinder(const std::string &_physicsEngine);
public: void Clone(const std::string &_physicsEngine);
};
class LightFactoryTest : public ServerFixture
{
/// \brief Light factory publisher.
protected: transport::PublisherPtr lightFactoryPub;
};
///////////////////////////////////////////////////
// Verify that sdf is retained by entities spawned
// via factory messages. A change between 1.6, 1.7
// caused entities to lose their sdf data
// (see issue #651)
void FactoryTest::BoxSdf(const std::string &_physicsEngine)
{
ignition::math::Pose3d setPose;
Load("worlds/empty.world", true, _physicsEngine);
physics::WorldPtr world = physics::get_world("default");
ASSERT_TRUE(world != NULL);
unsigned int entityCount = 6;
for (unsigned int i = 0; i < entityCount; ++i)
{
std::ostringstream name;
name << "test_box_" << i;
setPose.Set(ignition::math::Vector3d(0, 0, i+0.5),
ignition::math::Quaterniond(0, 0, 0));
SpawnBox(name.str(), ignition::math::Vector3d(1, 1, 1), setPose.Pos(),
setPose.Rot().Euler());
}
// This loop must be separate from the previous loop to cause
// the failure.
for (unsigned int i = 0; i < entityCount; ++i)
{
std::ostringstream name;
name << "test_box_" << i;
physics::ModelPtr model = world->GetModel(name.str());
ASSERT_TRUE(model != NULL);
msgs::Model msg;
model->FillMsg(msg);
EXPECT_TRUE(msg.has_pose());
// gzerr << msg.DebugString() << '\n';
}
}
/////////////////////////////////////////////////
TEST_P(FactoryTest, BoxSdf)
{
BoxSdf(GetParam());
}
/////////////////////////////////////////////////
void FactoryTest::Box(const std::string &_physicsEngine)
{
ignition::math::Pose3d setPose, testPose;
Load("worlds/empty.world", true, _physicsEngine);
for (unsigned int i = 0; i < 100; i++)
{
std::ostringstream name;
name << "test_box_" << i;
setPose.Set(ignition::math::Vector3d(0, 0, i+0.5),
ignition::math::Quaterniond(0, 0, 0));
SpawnBox(name.str(), math::Vector3(1, 1, 1), setPose.Pos(),
setPose.Rot().Euler());
testPose = GetEntityPose(name.str()).Ign();
EXPECT_TRUE(math::equal(testPose.Pos().X(), setPose.Pos().X(), 0.1));
EXPECT_TRUE(math::equal(testPose.Pos().Y(), setPose.Pos().Y(), 0.1));
EXPECT_TRUE(math::equal(testPose.Pos().Z(), setPose.Pos().Z(), 0.1));
}
}
/////////////////////////////////////////////////
TEST_P(FactoryTest, Box)
{
Box(GetParam());
}
/////////////////////////////////////////////////
void FactoryTest::Sphere(const std::string &_physicsEngine)
{
ignition::math::Pose3d setPose, testPose;
Load("worlds/empty.world", true, _physicsEngine);
for (unsigned int i = 0; i < 100; i++)
{
std::ostringstream name;
name << "test_sphere_" << i;
setPose.Set(ignition::math::Vector3d(0, 0, i+0.5),
ignition::math::Quaterniond(0, 0, 0));
SpawnSphere(name.str(), setPose.Pos(), setPose.Rot().Euler());
testPose = GetEntityPose(name.str()).Ign();
EXPECT_TRUE(math::equal(testPose.Pos().X(), setPose.Pos().X(), 0.1));
EXPECT_TRUE(math::equal(testPose.Pos().Y(), setPose.Pos().Y(), 0.1));
EXPECT_TRUE(math::equal(testPose.Pos().Z(), setPose.Pos().Z(), 0.1));
}
}
/////////////////////////////////////////////////
TEST_P(FactoryTest, Sphere)
{
Sphere(GetParam());
}
/////////////////////////////////////////////////
void FactoryTest::Cylinder(const std::string &_physicsEngine)
{
ignition::math::Pose3d setPose, testPose;
Load("worlds/empty.world", true, _physicsEngine);
for (unsigned int i = 0; i < 100; i++)
{
std::ostringstream name;
name << "test_cylinder_" << i;
setPose.Set(
ignition::math::Vector3d(0, 0, i+0.5),
ignition::math::Quaterniond(0, 0, 0));
SpawnCylinder(name.str(), setPose.Pos(), setPose.Rot().Euler());
testPose = GetEntityPose(name.str()).Ign();
EXPECT_TRUE(math::equal(testPose.Pos().X(), setPose.Pos().X(), 0.1));
EXPECT_TRUE(math::equal(testPose.Pos().Y(), setPose.Pos().Y(), 0.1));
EXPECT_TRUE(math::equal(testPose.Pos().Z(), setPose.Pos().Z(), 0.1));
}
}
/////////////////////////////////////////////////
TEST_P(FactoryTest, Cylinder)
{
Cylinder(GetParam());
}
/////////////////////////////////////////////////
void FactoryTest::Clone(const std::string &_physicsEngine)
{
ignition::math::Pose3d testPose;
Load("worlds/pr2.world", true, _physicsEngine);
// clone the pr2
std::string name = "pr2";
msgs::Factory msg;
ignition::math::Pose3d clonePose;
clonePose.Set(ignition::math::Vector3d(2, 3, 0.5),
ignition::math::Quaterniond(0, 0, 0));
msgs::Set(msg.mutable_pose(), clonePose);
msg.set_clone_model_name(name);
this->factoryPub->Publish(msg);
// Wait for the pr2 clone to spawn
std::string cloneName = name + "_clone";
this->WaitUntilEntitySpawn(cloneName, 100, 100);
EXPECT_TRUE(this->HasEntity(cloneName));
testPose = GetEntityPose(cloneName).Ign();
EXPECT_TRUE(math::equal(testPose.Pos().X(), clonePose.Pos().X(), 0.1));
EXPECT_TRUE(math::equal(testPose.Pos().Y(), clonePose.Pos().Y(), 0.1));
EXPECT_TRUE(math::equal(testPose.Pos().Z(), clonePose.Pos().Z(), 0.1));
// Verify properties of the pr2 clone with the original model.
physics::WorldPtr world = physics::get_world("default");
ASSERT_TRUE(world != NULL);
// Check model
physics::ModelPtr model = world->GetModel(name);
ASSERT_TRUE(model != NULL);
physics::ModelPtr modelClone = world->GetModel(cloneName);
ASSERT_TRUE(modelClone != NULL);
EXPECT_EQ(model->GetJointCount(), modelClone->GetJointCount());
EXPECT_EQ(model->GetLinks().size(), modelClone->GetLinks().size());
EXPECT_EQ(model->GetSensorCount(), modelClone->GetSensorCount());
EXPECT_EQ(model->GetPluginCount(), modelClone->GetPluginCount());
EXPECT_EQ(model->GetAutoDisable(), modelClone->GetAutoDisable());
// Check links
physics::Link_V links = model->GetLinks();
physics::Link_V linkClones = modelClone->GetLinks();
for (unsigned int i = 0; i < links.size(); ++i)
{
physics::LinkPtr link = links[i];
physics::LinkPtr linkClone = linkClones[i];
EXPECT_EQ(link->GetSensorCount(), linkClone->GetSensorCount());
EXPECT_EQ(link->GetKinematic(), linkClone->GetKinematic());
// Check collisions
physics::Collision_V collisions = link->GetCollisions();
physics::Collision_V collisionClones = linkClone->GetCollisions();
EXPECT_EQ(collisions.size(), collisionClones.size());
for (unsigned int j = 0; j < collisions.size(); ++j)
{
physics::CollisionPtr collision = collisions[j];
physics::CollisionPtr collisionClone = collisionClones[j];
EXPECT_EQ(collision->GetShapeType(), collisionClone->GetShapeType());
EXPECT_EQ(collision->GetMaxContacts(), collisionClone->GetMaxContacts());
// Check surface
physics::SurfaceParamsPtr surface = collision->GetSurface();
physics::SurfaceParamsPtr cloneSurface = collisionClone->GetSurface();
EXPECT_EQ(surface->collideWithoutContact,
cloneSurface->collideWithoutContact);
EXPECT_EQ(surface->collideWithoutContactBitmask,
cloneSurface->collideWithoutContactBitmask);
}
// Check inertial
physics::InertialPtr inertial = link->GetInertial();
physics::InertialPtr inertialClone = linkClone->GetInertial();
EXPECT_EQ(inertial->GetMass(), inertialClone->GetMass());
EXPECT_EQ(inertial->GetCoG(), inertialClone->GetCoG());
EXPECT_EQ(inertial->GetPrincipalMoments(),
inertialClone->GetPrincipalMoments());
EXPECT_EQ(inertial->GetProductsofInertia(),
inertialClone->GetProductsofInertia());
}
// Check joints
physics::Joint_V joints = model->GetJoints();
physics::Joint_V jointClones = modelClone->GetJoints();
for (unsigned int i = 0; i < joints.size(); ++i)
{
physics::JointPtr joint = joints[i];
physics::JointPtr jointClone = jointClones[i];
EXPECT_EQ(joint->GetAngleCount(), jointClone->GetAngleCount());
for (unsigned j = 0; j < joint->GetAngleCount(); ++j)
{
EXPECT_EQ(joint->GetUpperLimit(j), jointClone->GetUpperLimit(j));
EXPECT_EQ(joint->GetLowerLimit(j), jointClone->GetLowerLimit(j));
EXPECT_EQ(joint->GetEffortLimit(j), jointClone->GetEffortLimit(j));
EXPECT_EQ(joint->GetVelocityLimit(j), jointClone->GetVelocityLimit(j));
EXPECT_EQ(joint->GetStopStiffness(j), jointClone->GetStopStiffness(j));
EXPECT_EQ(joint->GetStopDissipation(j),
jointClone->GetStopDissipation(j));
EXPECT_EQ(joint->GetLocalAxis(j), jointClone->GetLocalAxis(j));
EXPECT_EQ(joint->GetDamping(j), jointClone->GetDamping(j));
}
}
}
/////////////////////////////////////////////////
TEST_P(FactoryTest, Clone)
{
Clone(GetParam());
}
// Disabling this test for now. Different machines return different
// camera images. Need a better way to evaluate rendered content.
// TEST_F(FactoryTest, Camera)
// {
/*
if (rendering::RenderEngine::Instance()->GetRenderPathType() ==
rendering::RenderEngine::NONE)
return;
math::Pose setPose, testPose;
Load("worlds/empty.world");
setPose.Set(math::Vector3(-5, 0, 5), math::Quaternion(0, GZ_DTOR(15), 0));
SpawnCamera("camera_model", "camera_sensor2", setPose.pos,
setPose.rot.GetAsEuler());
unsigned char *img = NULL;
unsigned int width;
unsigned int height;
GetFrame("camera_sensor2", &img, width, height);
ASSERT_EQ(width, static_cast<unsigned int>(320));
ASSERT_EQ(height, static_cast<unsigned int>(240));
unsigned int diffMax = 0;
unsigned int diffSum = 0;
double diffAvg = 0;
ImageCompare(&img, &empty_world_camera1,
width, height, 3, diffMax, diffSum, diffAvg);
// PrintImage("empty_world_camera1", &img, width, height, 3);
ASSERT_LT(diffSum, static_cast<unsigned int>(100));
ASSERT_EQ(static_cast<unsigned int>(0), diffMax);
ASSERT_EQ(0.0, diffAvg);
*/
// }
/////////////////////////////////////////////////
TEST_F(LightFactoryTest, SpawnLight)
{
Load("worlds/empty.world");
physics::WorldPtr world = physics::get_world("default");
ASSERT_TRUE(world != nullptr);
// create lights using ~/factory/light topic
this->lightFactoryPub = this->node->Advertise<msgs::Light>("~/factory/light");
std::string light1Name = "new1_light";
std::string light2Name = "new2_light";
msgs::Light msg;
msg.set_name(light1Name);
ignition::math::Pose3d light1Pose = ignition::math::Pose3d(0, 2, 1, 0, 0, 0);
msgs::Set(msg.mutable_pose(), light1Pose);
this->lightFactoryPub->Publish(msg);
msg.set_name(light2Name);
ignition::math::Pose3d light2Pose = ignition::math::Pose3d(1, 0, 5, 0, 2, 0);
msgs::Set(msg.mutable_pose(), light2Pose);
this->lightFactoryPub->Publish(msg);
// wait for light to spawn
int sleep = 0;
int maxSleep = 50;
while ((!world->Light(light1Name) || !world->Light(light2Name)) &&
sleep++ < maxSleep)
{
common::Time::MSleep(100);
}
// verify lights in world
physics::LightPtr light1 = world->Light(light1Name);
physics::LightPtr light2 = world->Light(light2Name);
ASSERT_NE(nullptr, light1);
ASSERT_NE(nullptr, light2);
EXPECT_EQ(light1Name, light1->GetScopedName());
EXPECT_EQ(light1Pose, light1->GetWorldPose().Ign());
EXPECT_EQ(light2Name, light2->GetScopedName());
EXPECT_EQ(light2Pose, light2->GetWorldPose().Ign());
}
INSTANTIATE_TEST_CASE_P(PhysicsEngines, FactoryTest, PHYSICS_ENGINE_VALUES);
/////////////////////////////////////////////////
int main(int argc, char **argv)
{
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}