/* * Copyright (C) 2015 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 #include #include "gazebo/msgs/msgs.hh" #include "gazebo/physics/physics.hh" #include "gazebo/transport/transport.hh" #include "gazebo/test/ServerFixture.hh" #include "gazebo/test/helper_physics_generator.hh" using namespace gazebo; ////////////////////////////////////////////////// class SavingLoadingTest : public ServerFixture, public testing::WithParamInterface { /// \brief Test scaling a model and then saving it. The scale should show up /// in the state SDF instead of the initial model SDF. /// \param[in] _physicsEngine Physics Engine type. public: void SaveScaledModel(const std::string &_physicsEngine); /// \brief Test loading a world with models scaled in the world state. /// \param[in] _physicsEngine Physics Engine type. public: void LoadScaledModels(const std::string &_physicsEngine); }; ////////////////////////////////////////////////// void SavingLoadingTest::SaveScaledModel(const std::string &_physicsEngine) { // load a world with simple shapes this->Load("worlds/shapes.world", true, _physicsEngine); auto world = physics::get_world("default"); ASSERT_TRUE(world != NULL); auto physics = world->GetPhysicsEngine(); ASSERT_TRUE(physics != NULL); // Get box and check scale auto box = world->GetModel("box"); ASSERT_TRUE(box != NULL); EXPECT_EQ(box->Scale(), ignition::math::Vector3d::One); // Create transport auto node = transport::NodePtr(new transport::Node()); node->Init(); auto modelPub = node->Advertise("~/model/modify"); // scale box ignition::math::Vector3d newScale(0.1, 2, 3); msgs::Model msg; msg.set_name("box"); msgs::Set(msg.mutable_scale(), newScale); modelPub->Publish(msg); // Check box has been scaled int sleep = 0; int maxSleep = 10; while (box->Scale() != newScale && sleep < maxSleep) { gazebo::common::Time::MSleep(100); sleep++; } EXPECT_EQ(box->Scale(), newScale); // request SDF to save world auto response = transport::request("default", "world_sdf_save"); EXPECT_NE(response->response(), "error"); std::string str = response->serialized_data(); // Remove strange characters from the front str = str.substr(3); sdf::SDF sdf_parsed; sdf_parsed.SetFromString(str); ASSERT_TRUE(sdf_parsed.Root()->HasElement("world")); auto worldElem = sdf_parsed.Root()->GetElement("world"); // Check all model sizes (scales) EXPECT_TRUE(worldElem->HasElement("model")); auto modelElem = worldElem->GetElement("model"); while (modelElem) { EXPECT_TRUE(modelElem->HasElement("link")); EXPECT_TRUE(modelElem->GetElement("link")->HasElement("visual")); EXPECT_TRUE(modelElem->GetElement("link")->HasElement("collision")); EXPECT_TRUE(modelElem->GetElement("link")->GetElement("visual")-> HasElement("geometry")); EXPECT_TRUE(modelElem->GetElement("link")->GetElement("collision")-> HasElement("geometry")); auto visualGeom = modelElem->GetElement("link")->GetElement("visual")-> GetElement("geometry"); auto collisionGeom = modelElem->GetElement("link")-> GetElement("collision")->GetElement("geometry"); EXPECT_TRUE(modelElem->HasAttribute("name")); auto name = modelElem->GetAttribute("name")->GetAsString(); // Check that all sizes are still one if (name == "box") { gzdbg << "Checking box model geometry size." << std::endl; EXPECT_TRUE(visualGeom->HasElement("box")); EXPECT_TRUE(collisionGeom->HasElement("box")); EXPECT_TRUE(visualGeom->GetElement("box")->HasElement("size")); EXPECT_TRUE(collisionGeom->GetElement("box")->HasElement("size")); auto visualSize = visualGeom->GetElement("box")-> Get("size"); auto collisionSize = collisionGeom->GetElement("box")-> Get("size"); EXPECT_EQ(visualSize, ignition::math::Vector3d::One); EXPECT_EQ(collisionSize, ignition::math::Vector3d::One); } else if (name == "sphere") { gzdbg << "Checking sphere model geometry size." << std::endl; EXPECT_TRUE(visualGeom->HasElement("sphere")); EXPECT_TRUE(collisionGeom->HasElement("sphere")); EXPECT_TRUE(visualGeom->GetElement("sphere")->HasElement("radius")); EXPECT_TRUE(collisionGeom->GetElement("sphere")->HasElement("radius")); auto visualSize = visualGeom->GetElement("sphere")->Get("radius"); auto collisionSize = collisionGeom->GetElement("sphere")-> Get("radius"); EXPECT_EQ(visualSize, 0.5); EXPECT_EQ(collisionSize, 0.5); } else if (name == "cylinder") { gzdbg << "Checking cylinder model geometry size." << std::endl; EXPECT_TRUE(visualGeom->HasElement("cylinder")); EXPECT_TRUE(collisionGeom->HasElement("cylinder")); EXPECT_TRUE(visualGeom->GetElement("cylinder")->HasElement("radius")); EXPECT_TRUE(collisionGeom->GetElement("cylinder")->HasElement("radius")); EXPECT_TRUE(visualGeom->GetElement("cylinder")->HasElement("length")); EXPECT_TRUE(collisionGeom->GetElement("cylinder")->HasElement("length")); auto visualRadius = visualGeom->GetElement("cylinder")-> Get("radius"); auto collisionRadius = collisionGeom->GetElement("cylinder")-> Get("radius"); auto visualLength = visualGeom->GetElement("cylinder")-> Get("length"); auto collisionLength = collisionGeom->GetElement("cylinder")-> Get("length"); EXPECT_EQ(visualRadius, 0.5); EXPECT_EQ(collisionRadius, 0.5); EXPECT_EQ(visualLength, 1.0); EXPECT_EQ(collisionLength, 1.0); } modelElem = modelElem->GetNextElement("model"); } // Check scale in all model states EXPECT_TRUE(worldElem->HasElement("state")); EXPECT_TRUE(worldElem->GetElement("state")->HasElement("model")); auto modelStateElem = worldElem->GetElement("state")->GetElement("model"); while (modelStateElem) { EXPECT_TRUE(modelStateElem->HasAttribute("name")); auto name = modelStateElem->GetAttribute("name")->GetAsString(); EXPECT_TRUE(modelStateElem->HasElement("scale")); auto scale = modelStateElem->Get("scale"); // Check that only box state has new scale if (name == "box") { gzdbg << "Checking box model state scale." << std::endl; EXPECT_EQ(scale, newScale); } else if (name == "sphere") { gzdbg << "Checking sphere model state scale." << std::endl; EXPECT_EQ(scale, ignition::math::Vector3d::One); } else if (name == "cylinder") { gzdbg << "Checking cylinder model state scale." << std::endl; EXPECT_EQ(scale, ignition::math::Vector3d::One); } modelStateElem = modelStateElem->GetNextElement("model"); } } ////////////////////////////////////////////////// void SavingLoadingTest::LoadScaledModels(const std::string &_physicsEngine) { // load a world which has models scaled in the state this->Load("test/worlds/scaled_shapes.world", true, _physicsEngine); auto world = physics::get_world("default"); ASSERT_TRUE(world != NULL); auto physics = world->GetPhysicsEngine(); ASSERT_TRUE(physics != NULL); // Get box and check scale auto box = world->GetModel("box"); ASSERT_TRUE(box != NULL); EXPECT_EQ(box->Scale(), ignition::math::Vector3d(3.34637, 2.87999, 0.123722)); // Get sphere and check scale auto sphere = world->GetModel("sphere"); ASSERT_TRUE(sphere != NULL); EXPECT_EQ(sphere->Scale(), ignition::math::Vector3d(0.402674, 0.402674, 0.402674)); // Get cylinder and check scale auto cylinder = world->GetModel("cylinder"); ASSERT_TRUE(cylinder != NULL); EXPECT_EQ(cylinder->Scale(), ignition::math::Vector3d(2.2969, 2.2969, 2.09564)); } ///////////////////////////////////////////////// TEST_P(SavingLoadingTest, SaveScaledModel) { this->SaveScaledModel(GetParam()); } ///////////////////////////////////////////////// TEST_P(SavingLoadingTest, LoadScaledModels) { this->LoadScaledModels(GetParam()); } INSTANTIATE_TEST_CASE_P(PhysicsEngines, SavingLoadingTest, PHYSICS_ENGINE_VALUES); ///////////////////////////////////////////////// int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); }