UrdfParserTest.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include <AzCore/UnitTest/TestTypes.h>
  9. #include <AzCore/std/string/string.h>
  10. #include <AzTest/AzTest.h>
  11. #include <RobotImporter/URDF/UrdfParser.h>
  12. #include <RobotImporter/Utils/RobotImporterUtils.h>
  13. #include <RobotImporter/xacro/XacroUtils.h>
  14. namespace UnitTest
  15. {
  16. class UrdfParserTest : public LeakDetectionFixture
  17. {
  18. public:
  19. AZStd::string GetXacroParams()
  20. {
  21. return "<robot name=\"test\" xmlns:xacro=\"http://ros.org/wiki/xacro\">\n"
  22. " <xacro:arg name=\"laser_enabled\" default=\"false\" />\n"
  23. "</robot>";
  24. }
  25. AZStd::string GetUrdfWithOneLink()
  26. {
  27. return "<robot name=\"test_one_link\">"
  28. " <material name=\"some_material\">\n"
  29. " <color rgba=\"0 0 0 1\"/>\n"
  30. " </material>"
  31. " <link name=\"link1\">"
  32. " <inertial>"
  33. " <mass value=\"1.0\"/>"
  34. " <inertia ixx=\"1.0\" iyy=\"1.0\" izz=\"1.0\" ixy=\"0\" ixz=\"0\" iyz=\"0\"/>"
  35. " </inertial>"
  36. " <visual>"
  37. " <geometry>"
  38. " <box size=\"1.0 2.0 1.0\"/>"
  39. " </geometry>"
  40. " <material name=\"some_material\"/>"
  41. " </visual>"
  42. " <collision>"
  43. " <geometry>"
  44. " <box size=\"1.0 2.0 1.0\"/>"
  45. " </geometry>"
  46. " </collision>"
  47. " </link>"
  48. "</robot>";
  49. }
  50. AZStd::string GetUrdfWithTwoLinksAndJoint()
  51. {
  52. return "<robot name=\"test_two_links_one_joint\"> "
  53. " <material name=\"some_material\">\n"
  54. " <color rgba=\"0 0 0 1\"/>\n"
  55. " </material>"
  56. " <link name=\"link1\">"
  57. " <inertial>"
  58. " <mass value=\"1.0\"/>"
  59. " <inertia ixx=\"1.0\" iyy=\"1.0\" izz=\"1.0\" ixy=\"0\" ixz=\"0\" iyz=\"0\"/>"
  60. " </inertial>"
  61. " <visual>"
  62. " <geometry>"
  63. " <box size=\"1.0 2.0 1.0\"/>"
  64. " </geometry>"
  65. " <material name=\"some_material\"/>"
  66. " </visual>"
  67. " </link>"
  68. " <link name=\"link2\">"
  69. " <inertial>"
  70. " <mass value=\"1.0\"/>"
  71. " <inertia ixx=\"1.0\" iyy=\"1.0\" izz=\"1.0\" ixy=\"0\" ixz=\"0\" iyz=\"0\"/>"
  72. " </inertial>"
  73. " <visual>"
  74. " <geometry>"
  75. " <box size=\"1.0 1.0 1.0\"/>"
  76. " </geometry>"
  77. " <material name=\"some_material\"/>"
  78. " </visual>"
  79. " </link>"
  80. " <joint name=\"joint12\" type=\"fixed\">"
  81. " <parent link=\"link1\"/>"
  82. " <child link=\"link2\"/>"
  83. " <origin rpy=\"0 0 0\" xyz=\"1.0 0.5 0.0\"/>"
  84. " <dynamics damping=\"10.0\" friction=\"5.0\"/>"
  85. " <limit lower=\"10.0\" upper=\"20.0\" effort=\"90.0\" velocity=\"10.0\"/>"
  86. " </joint>"
  87. "</robot>";
  88. }
  89. AZStd::string GetURDFWithTranforms()
  90. {
  91. return "<?xml version=\"1.0\"?>\n"
  92. "<robot name=\"complicated\">\n"
  93. " <link name=\"base_link\">\n"
  94. " </link>\n"
  95. " <link name=\"link1\">\n"
  96. " <inertial>\n"
  97. " <origin xyz=\"0. 0. 0.\"/>\n"
  98. " <mass value=\"1.\"/>\n"
  99. " <inertia ixx=\"1.\" ixy=\"0.\" ixz=\"0.\" iyy=\"1.\" iyz=\"0.\" izz=\"1.\"/>\n"
  100. " </inertial>\n"
  101. " <visual>\n"
  102. " <origin rpy=\"0.000000 -0.000000 0\" xyz=\"-1.2 0 0\"/>\n"
  103. " <geometry>\n"
  104. " <box size=\"2.000000 0.200000 0.200000\"/>\n"
  105. " </geometry>\n"
  106. " </visual>\n"
  107. " <collision>\n"
  108. " <origin rpy=\"0.000000 -0.000000 0\" xyz=\"-1.2 0 0.000000\"/>\n"
  109. " <geometry>\n"
  110. " <box size=\"2.000000 0.200000 0.200000\"/>\n"
  111. " </geometry> \n"
  112. " </collision>\n"
  113. " </link>\n"
  114. " <link name=\"link2\">\n"
  115. " <inertial>\n"
  116. " <origin xyz=\"0. 0. 0.\"/>\n"
  117. " <mass value=\"1.\"/>\n"
  118. " <inertia ixx=\"1.\" ixy=\"0.\" ixz=\"0.\" iyy=\"1.\" iyz=\"0.\" izz=\"1.\"/>\n"
  119. " </inertial>\n"
  120. " <visual>\n"
  121. " <origin rpy=\"0.000000 -0.000000 0\" xyz=\"-1.2 0 0\"/>\n"
  122. " <geometry>\n"
  123. " <box size=\"2.000000 0.200000 0.200000\"/>\n"
  124. " </geometry>\n"
  125. " </visual>\n"
  126. " <collision>\n"
  127. " <origin rpy=\"0.000000 -0.000000 0\" xyz=\"-1.2 0 0.000000\"/>\n"
  128. " <geometry>\n"
  129. " <box size=\"2.000000 0.200000 0.200000\"/>\n"
  130. " </geometry> \n"
  131. " </collision>\n"
  132. " </link>\n"
  133. " <link name=\"link3\">\n"
  134. " <inertial>\n"
  135. " <origin xyz=\"0. 0. 0.\"/>\n"
  136. " <mass value=\"1.\"/>\n"
  137. " <inertia ixx=\"1.\" ixy=\"0.\" ixz=\"0.\" iyy=\"1.\" iyz=\"0.\" izz=\"1.\"/>\n"
  138. " </inertial>\n"
  139. " <visual>\n"
  140. " <origin rpy=\"0.000000 -0.000000 0\" xyz=\"-1.2 0 0\"/>\n"
  141. " <geometry>\n"
  142. " <box size=\"2.000000 0.200000 0.200000\"/>\n"
  143. " </geometry>\n"
  144. " </visual>\n"
  145. " <collision>\n"
  146. " <origin rpy=\"0.000000 -0.000000 0\" xyz=\"-1.2 0 0.000000\"/>\n"
  147. " <geometry>\n"
  148. " <box size=\"2.000000 0.200000 0.200000\"/>\n"
  149. " </geometry> \n"
  150. " </collision>\n"
  151. " </link>\n"
  152. " <joint name=\"joint_bs\" type=\"fixed\">\n"
  153. " <parent link=\"base_link\"/>\n"
  154. " <child link=\"link1\"/>\n"
  155. " <axis xyz=\"0. 0. 1.\"/>\n"
  156. " <origin rpy=\"0 0 0\" xyz=\"0 0 0\"/>\n"
  157. " </joint> \n"
  158. " <joint name=\"joint0\" type=\"continuous\">\n"
  159. " <parent link=\"link1\"/>\n"
  160. " <child link=\"link2\"/>\n"
  161. " <axis xyz=\"0. 0. 1.\"/>\n"
  162. " <origin rpy=\"0.000000 -0.000000 2.094395\" xyz=\"-1.200000 2.078460 0.000000\"/>\n"
  163. " </joint> \n"
  164. " <joint name=\"joint1\" type=\"continuous\">\n"
  165. " <parent link=\"link2\"/>\n"
  166. " <child link=\"link3\"/>\n"
  167. " <axis xyz=\"0. 0. 1.\"/>\n"
  168. " <origin rpy=\"0.000000 0.000000 2.094395\" xyz=\"-1.200000286102295 2.078460931777954 0.\"/>\n"
  169. " </joint> \n"
  170. " <joint name=\"joint2\" type=\"continuous\">\n"
  171. " <parent link=\"link1\"/>\n"
  172. " <child link=\"link3\"/>\n"
  173. " <axis xyz=\"0. 0. 1.\"/>\n"
  174. " <origin rpy=\"0.000000 0.000000 -2.094395160675049\" xyz=\"-2.4000000953674316 0.0 0.0\"/>\n"
  175. " </joint>\n"
  176. "</robot>";
  177. }
  178. AZStd::string GetURDFWithWheel(
  179. const AZStd::string& wheel_name,
  180. const AZStd::string& wheel_joint_type,
  181. bool wheel_has_visual = true,
  182. bool wheel_has_collider = true)
  183. {
  184. // clang-format off
  185. return "<robot name=\"wheel_test\">\n"
  186. " <link name=\"base_link\">\n"
  187. " <inertial>\n"
  188. " <origin xyz=\"0. 0. 0.\"/>\n"
  189. " <mass value=\"1.\"/>\n"
  190. " <inertia ixx=\"1.\" ixy=\"0.\" ixz=\"0.\" iyy=\"1.\" iyz=\"0.\" izz=\"1.\"/>\n"
  191. " </inertial>\n"
  192. " </link>\n"
  193. " <link name=\""+wheel_name+"\">\n"
  194. " <inertial>\n"
  195. " <origin xyz=\"0. 0. 0.\"/>\n"
  196. " <mass value=\"1.\"/>\n"
  197. " <inertia ixx=\"1.\" ixy=\"0.\" ixz=\"0.\" iyy=\"1.\" iyz=\"0.\" izz=\"1.\"/>\n"
  198. " </inertial>\n"
  199. +(wheel_has_visual?"<visual>\n"
  200. " <origin rpy=\"0 0 0\" xyz=\"0 0 0\"/>\n"
  201. " <geometry>\n"
  202. " <box size=\"1 1 1\"/>\n"
  203. " </geometry>\n"
  204. " </visual>\n":"")+
  205. +(wheel_has_collider?"<collision>\n"
  206. " <origin rpy=\"0 0 0\" xyz=\"0 0 0\"/>\n"
  207. " <geometry>\n"
  208. " <box size=\"1 1 1\"/>\n"
  209. " </geometry>\n"
  210. " </collision>\n":"")+
  211. " </link>\n"
  212. " <joint name=\"joint0\" type=\""+wheel_joint_type+"\">\n"
  213. " <parent link=\"base_link\"/>\n"
  214. " <child link=\""+wheel_name+"\"/>\n"
  215. " <axis xyz=\"0. 0. 1.\"/>\n"
  216. " <origin rpy=\"0. 0. 0.\" xyz=\"2. 0. 0.\"/>\n"
  217. " </joint>\n"
  218. "</robot>";
  219. // clang-format on
  220. }
  221. };
  222. TEST_F(UrdfParserTest, ParseUrdfWithOneLink)
  223. {
  224. const auto xmlStr = GetUrdfWithOneLink();
  225. const auto urdf = ROS2::UrdfParser::Parse(xmlStr);
  226. EXPECT_EQ(urdf->getName(), "test_one_link");
  227. std::vector<urdf::LinkSharedPtr> links;
  228. urdf->getLinks(links);
  229. EXPECT_EQ(links.size(), 1U);
  230. const auto link1 = urdf->getLink("link1");
  231. ASSERT_TRUE(link1);
  232. EXPECT_EQ(link1->inertial->mass, 1.0);
  233. EXPECT_EQ(link1->inertial->ixx, 1.0);
  234. EXPECT_EQ(link1->inertial->ixy, 0.0);
  235. EXPECT_EQ(link1->inertial->ixz, 0.0);
  236. EXPECT_EQ(link1->inertial->iyy, 1.0);
  237. EXPECT_EQ(link1->inertial->iyz, 0.0);
  238. EXPECT_EQ(link1->inertial->izz, 1.0);
  239. EXPECT_EQ(link1->visual->geometry->type, 1);
  240. const auto visualBox = std::dynamic_pointer_cast<urdf::Box>(link1->visual->geometry);
  241. EXPECT_EQ(visualBox->dim.x, 1.0);
  242. EXPECT_EQ(visualBox->dim.y, 2.0);
  243. EXPECT_EQ(visualBox->dim.z, 1.0);
  244. EXPECT_EQ(link1->collision->geometry->type, 1);
  245. const auto collisionBox = std::dynamic_pointer_cast<urdf::Box>(link1->visual->geometry);
  246. EXPECT_EQ(collisionBox->dim.x, 1.0);
  247. EXPECT_EQ(collisionBox->dim.y, 2.0);
  248. EXPECT_EQ(collisionBox->dim.z, 1.0);
  249. }
  250. TEST_F(UrdfParserTest, ParseUrdfWithTwoLinksAndJoint)
  251. {
  252. const auto xmlStr = GetUrdfWithTwoLinksAndJoint();
  253. const auto urdf = ROS2::UrdfParser::Parse(xmlStr);
  254. EXPECT_EQ(urdf->getName(), "test_two_links_one_joint");
  255. std::vector<urdf::LinkSharedPtr> links;
  256. urdf->getLinks(links);
  257. EXPECT_EQ(links.size(), 2U);
  258. const auto link1 = urdf->getLink("link1");
  259. ASSERT_TRUE(link1);
  260. const auto link2 = urdf->getLink("link2");
  261. ASSERT_TRUE(link2);
  262. const auto joint12 = urdf->getJoint("joint12");
  263. ASSERT_TRUE(joint12);
  264. EXPECT_EQ(joint12->parent_link_name, "link1");
  265. EXPECT_EQ(joint12->child_link_name, "link2");
  266. EXPECT_EQ(joint12->parent_to_joint_origin_transform.position.x, 1.0);
  267. EXPECT_EQ(joint12->parent_to_joint_origin_transform.position.y, 0.5);
  268. EXPECT_EQ(joint12->parent_to_joint_origin_transform.position.z, 0.0);
  269. double roll, pitch, yaw;
  270. joint12->parent_to_joint_origin_transform.rotation.getRPY(roll, pitch, yaw);
  271. EXPECT_DOUBLE_EQ(roll, 0.0);
  272. EXPECT_DOUBLE_EQ(pitch, 0.0);
  273. EXPECT_DOUBLE_EQ(yaw, 0.0);
  274. EXPECT_EQ(joint12->dynamics->damping, 10.0);
  275. EXPECT_EQ(joint12->dynamics->friction, 5.0);
  276. EXPECT_EQ(joint12->limits->lower, 10.0);
  277. EXPECT_EQ(joint12->limits->upper, 20.0);
  278. EXPECT_EQ(joint12->limits->effort, 90.0);
  279. EXPECT_EQ(joint12->limits->velocity, 10.0);
  280. }
  281. TEST_F(UrdfParserTest, WheelHeuristicNameValid)
  282. {
  283. const AZStd::string wheel_name("wheel_left_link");
  284. const auto xmlStr = GetURDFWithWheel(wheel_name, "continuous");
  285. const auto urdf = ROS2::UrdfParser::Parse(xmlStr);
  286. auto wheel_candidate = urdf->getLink(wheel_name.c_str());
  287. ASSERT_TRUE(wheel_candidate);
  288. EXPECT_EQ(ROS2::Utils::IsWheelURDFHeuristics(wheel_candidate), true);
  289. }
  290. TEST_F(UrdfParserTest, WheelHeuristicNameNotValid1)
  291. {
  292. const AZStd::string wheel_name("wheel_left_joint");
  293. const auto xmlStr = GetURDFWithWheel(wheel_name, "continuous");
  294. const auto urdf = ROS2::UrdfParser::Parse(xmlStr);
  295. auto wheel_candidate = urdf->getLink(wheel_name.c_str());
  296. ASSERT_TRUE(wheel_candidate);
  297. EXPECT_EQ(ROS2::Utils::IsWheelURDFHeuristics(wheel_candidate), false);
  298. }
  299. TEST_F(UrdfParserTest, WheelHeuristicJointNotValid)
  300. {
  301. const AZStd::string wheel_name("wheel_left_link");
  302. const auto xmlStr = GetURDFWithWheel(wheel_name, "fixed");
  303. const auto urdf = ROS2::UrdfParser::Parse(xmlStr);
  304. auto wheel_candidate = urdf->getLink(wheel_name.c_str());
  305. ASSERT_TRUE(wheel_candidate);
  306. EXPECT_EQ(ROS2::Utils::IsWheelURDFHeuristics(wheel_candidate), false);
  307. }
  308. TEST_F(UrdfParserTest, WheelHeuristicJointVisualNotValid)
  309. {
  310. const AZStd::string wheel_name("wheel_left_link");
  311. const auto xmlStr = GetURDFWithWheel(wheel_name, "continuous", false, true);
  312. const auto urdf = ROS2::UrdfParser::Parse(xmlStr);
  313. auto wheel_candidate = urdf->getLink(wheel_name.c_str());
  314. ASSERT_TRUE(wheel_candidate);
  315. EXPECT_EQ(ROS2::Utils::IsWheelURDFHeuristics(wheel_candidate), false);
  316. }
  317. TEST_F(UrdfParserTest, WheelHeuristicJointColliderNotValid)
  318. {
  319. const AZStd::string wheel_name("wheel_left_link");
  320. const auto xmlStr = GetURDFWithWheel(wheel_name, "continuous", true, false);
  321. const auto urdf = ROS2::UrdfParser::Parse(xmlStr);
  322. auto wheel_candidate = urdf->getLink(wheel_name.c_str());
  323. ASSERT_TRUE(wheel_candidate);
  324. EXPECT_EQ(ROS2::Utils::IsWheelURDFHeuristics(wheel_candidate), false);
  325. }
  326. TEST_F(UrdfParserTest, TestLinkListing)
  327. {
  328. const auto xmlStr = GetURDFWithTranforms();
  329. const auto urdf = ROS2::UrdfParser::Parse(xmlStr);
  330. auto links = ROS2::Utils::GetAllLinks(urdf->getRoot()->child_links);
  331. EXPECT_EQ(links.size(), 3);
  332. ASSERT_TRUE(links.contains("link1"));
  333. ASSERT_TRUE(links.contains("link2"));
  334. ASSERT_TRUE(links.contains("link3"));
  335. EXPECT_EQ(links.at("link1")->name, "link1");
  336. EXPECT_EQ(links.at("link2")->name, "link2");
  337. EXPECT_EQ(links.at("link3")->name, "link3");
  338. }
  339. TEST_F(UrdfParserTest, TestJointLink)
  340. {
  341. const auto xmlStr = GetURDFWithTranforms();
  342. const auto urdf = ROS2::UrdfParser::Parse(xmlStr);
  343. auto joints = ROS2::Utils::GetAllJoints(urdf->getRoot()->child_links);
  344. EXPECT_EQ(joints.size(), 3);
  345. }
  346. TEST_F(UrdfParserTest, TestTransforms)
  347. {
  348. const auto xmlStr = GetURDFWithTranforms();
  349. const auto urdf = ROS2::UrdfParser::Parse(xmlStr);
  350. const auto links = ROS2::Utils::GetAllLinks(urdf->getRoot()->child_links);
  351. const auto link1_ptr = links.at("link1");
  352. const auto link2_ptr = links.at("link2");
  353. const auto link3_ptr = links.at("link3");
  354. // values exported from Blender
  355. const AZ::Vector3 expected_translation_link1{ 0.0, 0.0, 0.0 };
  356. const AZ::Vector3 expected_translation_link2{ -1.2000000476837158, 2.0784599781036377, 0.0 };
  357. const AZ::Vector3 expected_translation_link3{ -2.4000000953674316, 0.0, 0.0 };
  358. const AZ::Transform transform_from_urdf_link1 = ROS2::Utils::GetWorldTransformURDF(link1_ptr);
  359. EXPECT_NEAR(expected_translation_link1.GetX(), transform_from_urdf_link1.GetTranslation().GetX(), 1e-5);
  360. EXPECT_NEAR(expected_translation_link1.GetY(), transform_from_urdf_link1.GetTranslation().GetY(), 1e-5);
  361. EXPECT_NEAR(expected_translation_link1.GetZ(), transform_from_urdf_link1.GetTranslation().GetZ(), 1e-5);
  362. const AZ::Transform transform_from_urdf_link2 = ROS2::Utils::GetWorldTransformURDF(link2_ptr);
  363. EXPECT_NEAR(expected_translation_link2.GetX(), transform_from_urdf_link2.GetTranslation().GetX(), 1e-5);
  364. EXPECT_NEAR(expected_translation_link2.GetY(), transform_from_urdf_link2.GetTranslation().GetY(), 1e-5);
  365. EXPECT_NEAR(expected_translation_link2.GetZ(), transform_from_urdf_link2.GetTranslation().GetZ(), 1e-5);
  366. const AZ::Transform transform_from_urdf_link3 = ROS2::Utils::GetWorldTransformURDF(link3_ptr);
  367. EXPECT_NEAR(expected_translation_link3.GetX(), transform_from_urdf_link3.GetTranslation().GetX(), 1e-5);
  368. EXPECT_NEAR(expected_translation_link3.GetY(), transform_from_urdf_link3.GetTranslation().GetY(), 1e-5);
  369. EXPECT_NEAR(expected_translation_link3.GetZ(), transform_from_urdf_link3.GetTranslation().GetZ(), 1e-5);
  370. }
  371. TEST_F(UrdfParserTest, TestPathResolvementGlobal)
  372. {
  373. AZStd::string dae = "file:///home/foo/ros_ws/install/foo_robot/meshes/bar.dae";
  374. AZStd::string urdf = "/home/foo/ros_ws/install/foo_robot/foo_robot.urdf";
  375. auto result = ROS2::Utils::ResolveURDFPath(
  376. dae,
  377. urdf, "",
  378. [](const AZStd::string& p) -> bool
  379. {
  380. return false;
  381. });
  382. EXPECT_EQ(result, "/home/foo/ros_ws/install/foo_robot/meshes/bar.dae");
  383. }
  384. TEST_F(UrdfParserTest, TestPathResolvementRelative)
  385. {
  386. AZStd::string dae = "meshes/bar.dae";
  387. AZStd::string urdf = "/home/foo/ros_ws/install/foo_robot/foo_robot.urdf";
  388. auto result = ROS2::Utils::ResolveURDFPath(
  389. dae,
  390. urdf, "",
  391. [](const AZStd::string& p) -> bool
  392. {
  393. return false;
  394. });
  395. EXPECT_EQ(result, "/home/foo/ros_ws/install/foo_robot/meshes/bar.dae");
  396. }
  397. TEST_F(UrdfParserTest, TestPathResolvementRelativePackage)
  398. {
  399. AZStd::string dae = "package://meshes/bar.dae";
  400. AZStd::string urdf = "/home/foo/ros_ws/install/foo_robot/description/foo_robot.urdf";
  401. AZStd::string xml = "/home/foo/ros_ws/install/foo_robot/package.xml";
  402. AZStd::string resolvedDae = "/home/foo/ros_ws/install/foo_robot/meshes/bar.dae";
  403. auto mockFileSystem = [&](const AZStd::string& p) -> bool
  404. {
  405. return (p == xml || p == resolvedDae);
  406. };
  407. auto result = ROS2::Utils::ResolveURDFPath(dae, urdf, "", mockFileSystem);
  408. EXPECT_EQ(result, resolvedDae);
  409. }
  410. TEST_F(UrdfParserTest, TestPathResolvementExplicitPackageName)
  411. {
  412. AZStd::string dae = "package://foo_robot/meshes/bar.dae";
  413. AZStd::string urdf = "/home/foo/ros_ws/install/foo_robot/share/foo_robot/description/foo_robot.urdf";
  414. AZStd::string xml = "/home/foo/ros_ws/install/foo_robot/share/foo_robot/package.xml";
  415. AZStd::string resolvedDae = "/home/foo/ros_ws/install/foo_robot/share/foo_robot/meshes/bar.dae";
  416. auto mockFileSystem = [&](const AZStd::string& p) -> bool
  417. {
  418. return (p == xml || p == resolvedDae);
  419. };
  420. auto result = ROS2::Utils::ResolveURDFPath(dae, urdf, "/home/foo/ros_ws/install/foo_robot", mockFileSystem);
  421. EXPECT_EQ(result, resolvedDae);
  422. }
  423. TEST_F(UrdfParserTest, XacroParseArgsInvalid)
  424. {
  425. AZStd::string xacroParams = GetXacroParams();
  426. ROS2::Utils::xacro::Params params = ROS2::Utils::xacro::GetParameterFromXacroData("");
  427. EXPECT_EQ(params.size(), 0);
  428. }
  429. TEST_F(UrdfParserTest, XacroParseArgs)
  430. {
  431. AZStd::string xacroParams = GetXacroParams();
  432. ROS2::Utils::xacro::Params params = ROS2::Utils::xacro::GetParameterFromXacroData(xacroParams);
  433. EXPECT_EQ(params.size(), 1);
  434. ASSERT_TRUE(params.contains("laser_enabled"));
  435. EXPECT_EQ(params["laser_enabled"], "false");
  436. }
  437. } // namespace UnitTest