1 /*
2  * Copyright 2015 Open Source Robotics Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16 */
17 
18 #include <array>
19 #include <string>
20 
21 #include <gtest/gtest.h>
22 
23 #include "sdf/sdf.hh"
24 #include "sdf/Converter.hh"
25 
26 #include "test_config.h"
27 
28 const std::string CONVERT_DOC =
29   sdf::filesystem::append(PROJECT_SOURCE_PATH, "sdf", "1.6", "1_5.convert");
30 
31 /////////////////////////////////////////////////
32 /// Test conversion of imu in 1.5 to 1.6
TEST(ConverterIntegration,IMU_15_to_16)33 TEST(ConverterIntegration, IMU_15_to_16)
34 {
35   // The imu noise in 1.5 format
36   std::string xmlString = R"(
37 <?xml version="1.0" ?>
38 <sdf version="1.5">
39   <world name="default">
40     <model name="box_old_imu_noise">
41       <link name="link">
42         <sensor name='imu_sensor' type='imu'>
43           <imu>
44             <noise>
45               <type>gaussian</type>
46               <rate>
47                 <mean>0</mean>
48                 <stddev>0.0002</stddev>
49                 <bias_mean>7.5e-06</bias_mean>
50                 <bias_stddev>8e-07</bias_stddev>
51               </rate>
52               <accel>
53                 <mean>0</mean>
54                 <stddev>0.017</stddev>
55                 <bias_mean>0.1</bias_mean>
56                 <bias_stddev>0.001</bias_stddev>
57               </accel>
58             </noise>
59           </imu>
60         </sensor>
61       </link>
62     </model>
63   </world>
64 </sdf>)";
65 
66   TiXmlDocument xmlDoc;
67   xmlDoc.Parse(xmlString.c_str());
68 
69   // Convert
70   TiXmlDocument convertXmlDoc;
71   convertXmlDoc.LoadFile(CONVERT_DOC);
72   sdf::Converter::Convert(&xmlDoc, &convertXmlDoc);
73 
74   // Check some basic elements
75   TiXmlElement *convertedElem =  xmlDoc.FirstChildElement();
76   EXPECT_EQ(convertedElem->ValueStr(), "sdf");
77   convertedElem = convertedElem->FirstChildElement();
78   EXPECT_EQ(convertedElem->ValueStr(), "world");
79   convertedElem = convertedElem->FirstChildElement();
80   EXPECT_EQ(convertedElem->ValueStr(), "model");
81   convertedElem = convertedElem->FirstChildElement();
82   EXPECT_EQ(convertedElem->ValueStr(), "link");
83   convertedElem = convertedElem->FirstChildElement();
84   EXPECT_EQ(convertedElem->ValueStr(), "sensor");
85 
86   // Get the imu
87   TiXmlElement *imuElem = convertedElem->FirstChildElement();
88   EXPECT_EQ(imuElem->ValueStr(), "imu");
89 
90   // Get the angular_velocity
91   TiXmlElement *angVelElem = imuElem->FirstChildElement();
92   EXPECT_EQ(angVelElem->ValueStr(), "angular_velocity");
93 
94   // Get the linear_acceleration
95   TiXmlElement *linAccElem = angVelElem->NextSiblingElement();
96   EXPECT_EQ(linAccElem->ValueStr(), "linear_acceleration");
97 
98   std::array<char, 3> axis = {'x', 'y', 'z'};
99 
100   TiXmlElement *angVelAxisElem = angVelElem->FirstChildElement();
101   TiXmlElement *linAccAxisElem = linAccElem->FirstChildElement();
102 
103   // Iterate over <x>, <y>, and <z> elements under <angular_velocity> and
104   // <linear_acceleration>
105   for (auto const &a : axis)
106   {
107     EXPECT_EQ(angVelAxisElem->Value()[0], a);
108     EXPECT_EQ(linAccAxisElem->Value()[0], a);
109 
110     TiXmlElement *angVelAxisNoiseElem = angVelAxisElem->FirstChildElement();
111     TiXmlElement *linAccAxisNoiseElem = linAccAxisElem->FirstChildElement();
112 
113     EXPECT_EQ(angVelAxisNoiseElem->ValueStr(), "noise");
114     EXPECT_EQ(linAccAxisNoiseElem->ValueStr(), "noise");
115 
116     EXPECT_STREQ(angVelAxisNoiseElem->Attribute("type"), "gaussian");
117     EXPECT_STREQ(linAccAxisNoiseElem->Attribute("type"), "gaussian");
118 
119     EXPECT_STREQ(angVelAxisNoiseElem->FirstChildElement("mean")->GetText(),
120                  "0");
121     EXPECT_STREQ(linAccAxisNoiseElem->FirstChildElement("mean")->GetText(),
122                  "0");
123 
124     EXPECT_STREQ(angVelAxisNoiseElem->FirstChildElement("stddev")->GetText(),
125                  "0.0002");
126     EXPECT_STREQ(linAccAxisNoiseElem->FirstChildElement("stddev")->GetText(),
127                  "0.017");
128 
129     EXPECT_STREQ(angVelAxisNoiseElem->FirstChildElement("bias_mean")->GetText(),
130                  "7.5e-06");
131     EXPECT_STREQ(linAccAxisNoiseElem->FirstChildElement("bias_mean")->GetText(),
132                  "0.1");
133 
134     EXPECT_STREQ(angVelAxisNoiseElem->FirstChildElement(
135           "bias_stddev")->GetText(), "8e-07");
136     EXPECT_STREQ(linAccAxisNoiseElem->FirstChildElement(
137           "bias_stddev")->GetText(), "0.001");
138 
139     angVelAxisElem = angVelAxisElem->NextSiblingElement();
140     linAccAxisElem = linAccAxisElem->NextSiblingElement();
141   }
142 }
143 
144 /////////////////////////////////////////////////
145 /// Test conversion using the parser sdf file converter interface.
TEST(ConverterIntegration,ParserFileConverter)146 TEST(ConverterIntegration, ParserFileConverter)
147 {
148   std::string filename = sdf::filesystem::append(PROJECT_SOURCE_PATH, "test",
149                                                  "integration", "audio.sdf");
150 
151   sdf::SDFPtr sdf(new sdf::SDF());
152   sdf::init(sdf);
153 
154   EXPECT_TRUE(sdf::convertFile(filename, "1.6", sdf));
155 
156   sdf::ElementPtr rootElem = sdf->Root();
157   ASSERT_NE(nullptr, rootElem);
158   EXPECT_EQ("1.6", rootElem->Get<std::string>("version"));
159 
160   sdf::ElementPtr modelElem = rootElem->GetElement("model");
161   ASSERT_NE(nullptr, modelElem);
162   EXPECT_EQ(modelElem->Get<std::string>("name"), "full_audio_parameters");
163 
164   sdf::ElementPtr linkElem = modelElem->GetElement("link");
165   ASSERT_NE(nullptr, linkElem);
166   EXPECT_EQ(linkElem->Get<std::string>("name"), "link");
167 
168   sdf::ElementPtr collElem = linkElem->GetElement("collision");
169   ASSERT_NE(nullptr, collElem);
170   EXPECT_EQ(collElem->Get<std::string>("name"), "collision");
171 
172   sdf::ElementPtr sinkElem = linkElem->GetElement("audio_sink");
173   ASSERT_NE(nullptr, sinkElem);
174 
175   sdf::ElementPtr sourceElem = linkElem->GetElement("audio_source");
176   ASSERT_NE(nullptr, sourceElem);
177 }
178 
179 /////////////////////////////////////////////////
180 /// Convert to a previous SDF version
TEST(ConverterIntegration,convertFileToNotLatestVersion)181 TEST(ConverterIntegration, convertFileToNotLatestVersion)
182 {
183   std::string filename = sdf::filesystem::append(PROJECT_SOURCE_PATH, "test",
184                                                  "integration", "audio.sdf");
185 
186   sdf::SDFPtr sdf(new sdf::SDF());
187   sdf::init(sdf);
188 
189   EXPECT_TRUE(sdf::convertFile(filename, "1.5", sdf));
190 
191   sdf::ElementPtr rootElem = sdf->Root();
192   ASSERT_NE(nullptr, rootElem);
193   EXPECT_EQ("1.5", rootElem->Get<std::string>("version"));
194 }
195 
196 /////////////////////////////////////////////////
197 /// Test conversion using the parser sdf string converter interface.
TEST(ConverterIntegration,ParserStringConverter)198 TEST(ConverterIntegration, ParserStringConverter)
199 {
200   // The gravity and magnetic_field in 1.5 format
201   std::string xmlString = R"(
202 <?xml version="1.0" ?>
203 <sdf version="1.5">
204   <world name="default">
205     <physics type="ode">
206       <gravity>0 0 -9.8</gravity>
207       <magnetic_field>1 2 3</magnetic_field>
208     </physics>
209   </world>
210 </sdf>)";
211 
212   sdf::SDFPtr sdf(new sdf::SDF());
213   sdf::init(sdf);
214 
215   EXPECT_TRUE(sdf::convertString(xmlString, "1.6", sdf));
216   ASSERT_NE(nullptr, sdf->Root());
217   EXPECT_EQ(sdf->Root()->GetName(), "sdf");
218   EXPECT_EQ("1.6", sdf->Root()->Get<std::string>("version"));
219 
220   sdf::ElementPtr worldElem = sdf->Root()->GetElement("world");
221   ASSERT_NE(nullptr, worldElem);
222   EXPECT_EQ(worldElem->Get<std::string>("name"), "default");
223 
224   sdf::ElementPtr physicsElem = worldElem->GetElement("physics");
225   ASSERT_NE(nullptr, physicsElem);
226   EXPECT_EQ(physicsElem->Get<std::string>("name"), "default_physics");
227   EXPECT_EQ(physicsElem->Get<std::string>("type"), "ode");
228 
229   sdf::ElementPtr gravityElem = worldElem->GetElement("gravity");
230   ASSERT_NE(nullptr, gravityElem);
231   EXPECT_EQ(gravityElem->Get<ignition::math::Vector3d>(),
232             ignition::math::Vector3d(0, 0, -9.8));
233 
234   sdf::ElementPtr magElem = worldElem->GetElement("magnetic_field");
235   ASSERT_NE(nullptr, magElem);
236   EXPECT_EQ(magElem->Get<ignition::math::Vector3d>(),
237             ignition::math::Vector3d(1, 2, 3));
238 }
239 
240 /////////////////////////////////////////////////
241 /// Test conversion of gravity, magnetic_field in 1.5 to 1.6
TEST(ConverterIntegration,World_15_to_16)242 TEST(ConverterIntegration, World_15_to_16)
243 {
244   // The gravity and magnetic_field in 1.5 format
245   std::string xmlString = R"(
246 <?xml version="1.0" ?>
247 <sdf version="1.5">
248   <world name="default">
249     <physics type="ode">
250       <gravity>0 0 -9.8</gravity>
251       <magnetic_field>1 2 3</magnetic_field>
252     </physics>
253   </world>
254 </sdf>)";
255 
256   TiXmlDocument xmlDoc;
257   xmlDoc.Parse(xmlString.c_str());
258 
259   // Convert
260   TiXmlDocument convertXmlDoc;
261   convertXmlDoc.LoadFile(CONVERT_DOC);
262   sdf::Converter::Convert(&xmlDoc, &convertXmlDoc);
263 
264   // Check some basic elements
265   TiXmlElement *convertedElem =  xmlDoc.FirstChildElement();
266   EXPECT_EQ(convertedElem->ValueStr(), "sdf");
267   convertedElem = convertedElem->FirstChildElement();
268   EXPECT_EQ(convertedElem->ValueStr(), "world");
269   convertedElem = convertedElem->FirstChildElement();
270   EXPECT_EQ(convertedElem->ValueStr(), "physics");
271 
272   // Get the gravity
273   TiXmlElement *gravityElem = convertedElem->NextSiblingElement("gravity");
274   ASSERT_NE(nullptr, gravityElem);
275   EXPECT_STREQ(gravityElem->GetText(), "0 0 -9.8");
276 
277   // Get the magnetic_field
278   TiXmlElement *magneticFieldElem =
279     convertedElem->NextSiblingElement("magnetic_field");
280   ASSERT_NE(nullptr, magneticFieldElem);
281   EXPECT_STREQ(magneticFieldElem->GetText(), "1 2 3");
282 }
283