diff --git a/.github/workflows/package_xml.yml b/.github/workflows/package_xml.yml
new file mode 100644
index 000000000..4bd4a9aa0
--- /dev/null
+++ b/.github/workflows/package_xml.yml
@@ -0,0 +1,11 @@
+name: Validate package.xml
+
+on:
+ pull_request:
+
+jobs:
+ package-xml:
+ runs-on: ubuntu-latest
+ name: Validate package.xml
+ steps:
+ - uses: gazebo-tooling/action-gz-ci/validate_package_xml@jammy
diff --git a/Changelog.md b/Changelog.md
index 3216b1855..44167531a 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -4,6 +4,22 @@
## libsdformat 14.X
+### libsdformat 14.2.0 (2024-04-23)
+
+1. Fix trivial warning on 24.04 for JointAxis_TEST.cc
+ * [Pull request #1402](https://github.com/gazebosim/sdformat/pull/1402)
+
+1. Add package.xml, fix `gz sdf` tests on Windows
+ * [Pull request #1374](https://github.com/gazebosim/sdformat/pull/1374)
+
+1. Backport mesh optimization feature
+ * [Pull request #1398](https://github.com/gazebosim/sdformat/pull/1398)
+ * [Pull request #1386](https://github.com/gazebosim/sdformat/pull/1386)
+ * [Pull request #1382](https://github.com/gazebosim/sdformat/pull/1382)
+
+1. Param_TEST: Check return values of Param::Get/Set
+ * [Pull request #1394](https://github.com/gazebosim/sdformat/pull/1394)
+
### libsdformat 14.1.1 (2024-03-28)
1. Fix warning with pybind11 2.12
diff --git a/package.xml b/package.xml
new file mode 100644
index 000000000..2cfe9abe1
--- /dev/null
+++ b/package.xml
@@ -0,0 +1,32 @@
+
+
+ sdformat15
+ 15.0.0
+ SDFormat is an XML file format that describes environments, objects, and robots
+in a manner suitable for robotic applications
+
+ Addisu Z. Taddese
+ Steve Peters
+
+ Apache License 2.0
+
+ https://github.com/gazebosim/sdformat
+
+ cmake
+ gz-cmake4
+ gz-math8
+ gz-utils3
+ tinyxml2
+ liburdfdom-dev
+ pybind11-dev
+
+ gz-tools2
+
+ libxml2-utils
+ python3-psutil
+ python3-pytest
+
+
+ cmake
+
+
diff --git a/src/Console.cc b/src/Console.cc
index d9ec8d044..558f10d87 100644
--- a/src/Console.cc
+++ b/src/Console.cc
@@ -34,13 +34,7 @@ using namespace sdf;
static std::shared_ptr myself;
static std::mutex g_instance_mutex;
-/// \todo Output disabled for windows, to allow tests to pass. We should
-/// disable output just for tests on windows.
-#ifndef _WIN32
static bool g_quiet = false;
-#else
-static bool g_quiet = true;
-#endif
static Console::ConsoleStream g_NullStream(nullptr);
diff --git a/src/JointAxis_TEST.cc b/src/JointAxis_TEST.cc
index 0e04be6fd..bc612c689 100644
--- a/src/JointAxis_TEST.cc
+++ b/src/JointAxis_TEST.cc
@@ -226,58 +226,58 @@ TEST(DOMJointAxis, ToElement)
sdf::ElementPtr dynElem = elem->GetElement("dynamics", errors);
ASSERT_TRUE(errors.empty());
- double damping = 0;
- damping = dynElem->Get(errors, "damping", damping).first;
+ double damping;
+ damping = dynElem->Get(errors, "damping", 0.0).first;
ASSERT_TRUE(errors.empty());
EXPECT_DOUBLE_EQ(0.2, damping);
- double friction = 0;
- friction = dynElem->Get(errors, "friction", friction).first;
+ double friction;
+ friction = dynElem->Get(errors, "friction", 0.0).first;
ASSERT_TRUE(errors.empty());
EXPECT_DOUBLE_EQ(1.3, friction);
- double springReference = 0;
+ double springReference;
springReference = dynElem->Get(
- errors, "spring_reference", springReference).first;
+ errors, "spring_reference", 0.0).first;
ASSERT_TRUE(errors.empty());
EXPECT_DOUBLE_EQ(2.4, springReference);
- double springStiffness = 0;
+ double springStiffness;
springStiffness = dynElem->Get(
- errors, "spring_stiffness", springStiffness).first;
+ errors, "spring_stiffness", 0.0).first;
ASSERT_TRUE(errors.empty());
EXPECT_DOUBLE_EQ(-1.2, springStiffness);
// Check //axis/limit
sdf::ElementPtr limitElem = elem->GetElement("limit", errors);
- double lower = 0;
- lower = limitElem->Get(errors, "lower", lower).first;
+ double lower;
+ lower = limitElem->Get(errors, "lower", 0.0).first;
ASSERT_TRUE(errors.empty());
EXPECT_DOUBLE_EQ(-10.8, lower);
- double upper = 0;
- upper = limitElem->Get(errors, "upper", upper).first;
+ double upper;
+ upper = limitElem->Get(errors, "upper", 0.0).first;
ASSERT_TRUE(errors.empty());
EXPECT_DOUBLE_EQ(123.4, upper);
- double effort = 0;
- effort = limitElem->Get(errors, "effort", effort).first;
+ double effort;
+ effort = limitElem->Get(errors, "effort", 0.0).first;
ASSERT_TRUE(errors.empty());
EXPECT_DOUBLE_EQ(3.2, effort);
- double maxVel = 0;
- maxVel = limitElem->Get(errors, "velocity", maxVel).first;
+ double maxVel;
+ maxVel = limitElem->Get(errors, "velocity", 0.0).first;
ASSERT_TRUE(errors.empty());
EXPECT_DOUBLE_EQ(54.2, maxVel);
- double stiffness = 0;
- stiffness = limitElem->Get(errors, "stiffness", stiffness).first;
+ double stiffness;
+ stiffness = limitElem->Get(errors, "stiffness", 0.0).first;
ASSERT_TRUE(errors.empty());
EXPECT_DOUBLE_EQ(1e2, stiffness);
- double dissipation = 0;
+ double dissipation;
dissipation = limitElem->Get(
- errors, "dissipation", dissipation).first;
+ errors, "dissipation", 0.0).first;
ASSERT_TRUE(errors.empty());
EXPECT_DOUBLE_EQ(1.5, dissipation);
@@ -286,31 +286,31 @@ TEST(DOMJointAxis, ToElement)
ASSERT_NE(nullptr, mimicElem);
std::string mimicJointName;
mimicJointName = mimicElem->Get(
- errors, "joint", mimicJointName).first;
+ errors, "joint", "").first;
ASSERT_TRUE(errors.empty());
EXPECT_EQ("test_joint", mimicJointName);
std::string mimicAxisName;
mimicAxisName = mimicElem->Get(
- errors, "axis", mimicAxisName).first;
+ errors, "axis", "").first;
ASSERT_TRUE(errors.empty());
EXPECT_EQ("axis2", mimicAxisName);
double multiplier;
multiplier = mimicElem->Get(
- errors, "multiplier", multiplier).first;
+ errors, "multiplier", 0.0).first;
ASSERT_TRUE(errors.empty());
EXPECT_DOUBLE_EQ(5.0, multiplier);
double offset;
offset = mimicElem->Get(
- errors, "offset", offset).first;
+ errors, "offset", 0.0).first;
ASSERT_TRUE(errors.empty());
EXPECT_DOUBLE_EQ(1.0, offset);
double reference;
reference = mimicElem->Get(
- errors, "reference", reference).first;
+ errors, "reference", 0.0).first;
ASSERT_TRUE(errors.empty());
EXPECT_DOUBLE_EQ(2.0, reference);
diff --git a/src/cmd/CMakeLists.txt b/src/cmd/CMakeLists.txt
index a1cf707c1..c1c91078b 100644
--- a/src/cmd/CMakeLists.txt
+++ b/src/cmd/CMakeLists.txt
@@ -31,7 +31,13 @@ set(cmd_script_configured "${CMAKE_CURRENT_BINARY_DIR}/cmd${PROJECT_NAME}.rb.con
# Set the library_location variable to the relative path to the library file
# within the install directory structure.
-set(library_location "../../../${CMAKE_INSTALL_LIBDIR}/$")
+if (MSVC)
+ set(library_location_prefix "${CMAKE_INSTALL_BINDIR}")
+else()
+ set(library_location_prefix "${CMAKE_INSTALL_LIBDIR}")
+endif()
+
+set(library_location "../../../${library_location_prefix}/$")
configure_file(
"cmd${PROJECT_NAME_NO_VERSION_LOWER}.rb.in"
diff --git a/src/cmd/cmdsdformat.rb.in b/src/cmd/cmdsdformat.rb.in
index 7c93d7680..c4bd35f4c 100644
--- a/src/cmd/cmdsdformat.rb.in
+++ b/src/cmd/cmdsdformat.rb.in
@@ -26,6 +26,8 @@ else
end
require 'optparse'
+require 'pathname'
+
# Constants.
LIBRARY_NAME = '@library_location@'
@@ -174,9 +176,7 @@ class Cmd
# puts options
# Read the plugin that handles the command.
- if LIBRARY_NAME[0] == '/'
- # If the first character is a slash, we'll assume that we've been given an
- # absolute path to the library. This is only used during test mode.
+ if Pathname.new(LIBRARY_NAME).absolute?
plugin = LIBRARY_NAME
else
# We're assuming that the library path is relative to the current
@@ -185,10 +185,18 @@ class Cmd
end
conf_version = LIBRARY_VERSION
+ if defined? RubyInstaller
+ # RubyInstaller does not search for dlls in PATH or the directory that tests are running from,
+ # so we'll add the parent directory of the plugin to the search path.
+ # https://github.com/oneclick/rubyinstaller2/wiki/For-gem-developers#-dll-loading
+ RubyInstaller::Runtime.add_dll_directory(File.dirname(plugin))
+ end
+
begin
Importer.dlload plugin
- rescue DLError
+ rescue DLError => error
puts "Library error: [#{plugin}] not found."
+ puts "DLError: #{error.message}"
exit(-1)
end
diff --git a/src/gz_TEST.cc b/src/gz_TEST.cc
index 816882f56..2e16d19db 100644
--- a/src/gz_TEST.cc
+++ b/src/gz_TEST.cc
@@ -73,7 +73,7 @@ std::string custom_exec_str(std::string _cmd)
}
/////////////////////////////////////////////////
-TEST(checkUnrecognizedElements, GZ_UTILS_TEST_DISABLED_ON_WIN32(SDF))
+TEST(checkUnrecognizedElements, SDF)
{
// Check an SDFormat file with unrecognized elements
{
@@ -120,7 +120,7 @@ TEST(checkUnrecognizedElements, GZ_UTILS_TEST_DISABLED_ON_WIN32(SDF))
}
/////////////////////////////////////////////////
-TEST(check, GZ_UTILS_TEST_DISABLED_ON_WIN32(SDF))
+TEST(check, SDF)
{
// Check a good SDF file
{
@@ -1011,7 +1011,7 @@ TEST(check, GZ_UTILS_TEST_DISABLED_ON_WIN32(SDF))
}
/////////////////////////////////////////////////
-TEST(check_shapes_sdf, GZ_UTILS_TEST_DISABLED_ON_WIN32(SDF))
+TEST(check_shapes_sdf, SDF)
{
{
const auto path =
@@ -1035,7 +1035,7 @@ TEST(check_shapes_sdf, GZ_UTILS_TEST_DISABLED_ON_WIN32(SDF))
}
/////////////////////////////////////////////////
-TEST(check_model_sdf, GZ_UTILS_TEST_DISABLED_ON_WIN32(SDF))
+TEST(check_model_sdf, SDF)
{
// Check a good SDF file by passing the absolute path
{
@@ -1062,7 +1062,7 @@ TEST(check_model_sdf, GZ_UTILS_TEST_DISABLED_ON_WIN32(SDF))
}
/////////////////////////////////////////////////
-TEST(describe, GZ_UTILS_TEST_DISABLED_ON_WIN32(SDF))
+TEST(describe, SDF)
{
// Get the description
std::string output =
@@ -1074,7 +1074,7 @@ TEST(describe, GZ_UTILS_TEST_DISABLED_ON_WIN32(SDF))
}
/////////////////////////////////////////////////
-TEST(print, GZ_UTILS_TEST_DISABLED_ON_WIN32(SDF))
+TEST(print, SDF)
{
// Check a good SDF file
{
@@ -1103,7 +1103,7 @@ TEST(print, GZ_UTILS_TEST_DISABLED_ON_WIN32(SDF))
}
/////////////////////////////////////////////////
-TEST(print_rotations_in_degrees, GZ_UTILS_TEST_DISABLED_ON_WIN32(SDF))
+TEST(print_rotations_in_degrees, SDF)
{
const std::string path =
sdf::testing::TestFile("sdf", "rotations_in_degrees.sdf");
@@ -1171,7 +1171,7 @@ TEST(print_rotations_in_degrees, GZ_UTILS_TEST_DISABLED_ON_WIN32(SDF))
}
/////////////////////////////////////////////////
-TEST(print_rotations_in_radians, GZ_UTILS_TEST_DISABLED_ON_WIN32(SDF))
+TEST(print_rotations_in_radians, SDF)
{
const std::string path =
sdf::testing::TestFile("sdf", "rotations_in_radians.sdf");
@@ -1239,7 +1239,7 @@ TEST(print_rotations_in_radians, GZ_UTILS_TEST_DISABLED_ON_WIN32(SDF))
}
/////////////////////////////////////////////////
-TEST(print_rotations_in_quaternions, GZ_UTILS_TEST_DISABLED_ON_WIN32(SDF))
+TEST(print_rotations_in_quaternions, SDF)
{
const auto path = sdf::testing::TestFile(
"sdf", "rotations_in_quaternions.sdf");
@@ -1308,7 +1308,7 @@ TEST(print_rotations_in_quaternions, GZ_UTILS_TEST_DISABLED_ON_WIN32(SDF))
}
/////////////////////////////////////////////////
-TEST(print_includes_rotations_in_degrees, GZ_UTILS_TEST_DISABLED_ON_WIN32(SDF))
+TEST(print_includes_rotations_in_degrees, SDF)
{
// Set SDF_PATH so that included models can be found
gz::utils::setenv(
@@ -1379,7 +1379,7 @@ TEST(print_includes_rotations_in_degrees, GZ_UTILS_TEST_DISABLED_ON_WIN32(SDF))
}
/////////////////////////////////////////////////
-TEST(print_includes_rotations_in_radians, GZ_UTILS_TEST_DISABLED_ON_WIN32(SDF))
+TEST(print_includes_rotations_in_radians, SDF)
{
// Set SDF_PATH so that included models can be found
gz::utils::setenv(
@@ -1450,8 +1450,7 @@ TEST(print_includes_rotations_in_radians, GZ_UTILS_TEST_DISABLED_ON_WIN32(SDF))
}
/////////////////////////////////////////////////
-TEST(print_includes_rotations_in_quaternions,
- GZ_UTILS_TEST_DISABLED_ON_WIN32(SDF))
+TEST(print_includes_rotations_in_quaternions, SDF)
{
// Set SDF_PATH so that included models can be found
gz::utils::setenv(
@@ -1523,8 +1522,7 @@ TEST(print_includes_rotations_in_quaternions,
}
/////////////////////////////////////////////////
-TEST(print_rotations_in_unnormalized_degrees,
- GZ_UTILS_TEST_DISABLED_ON_WIN32(SDF))
+TEST(print_rotations_in_unnormalized_degrees, SDF)
{
const std::string path =
sdf::testing::TestFile("sdf", "rotations_in_unnormalized_degrees.sdf");
@@ -1595,8 +1593,7 @@ TEST(print_rotations_in_unnormalized_degrees,
}
/////////////////////////////////////////////////
-TEST(print_rotations_in_unnormalized_radians,
- GZ_UTILS_TEST_DISABLED_ON_WIN32(SDF))
+TEST(print_rotations_in_unnormalized_radians, SDF)
{
const std::string path =
sdf::testing::TestFile("sdf", "rotations_in_unnormalized_radians.sdf");
@@ -1664,7 +1661,7 @@ TEST(print_rotations_in_unnormalized_radians,
}
/////////////////////////////////////////////////
-TEST(shuffled_cmd_flags, GZ_UTILS_TEST_DISABLED_ON_WIN32(SDF))
+TEST(shuffled_cmd_flags, SDF)
{
const std::string path =
sdf::testing::TestFile("sdf", "rotations_in_unnormalized_radians.sdf");
@@ -1713,8 +1710,7 @@ TEST(shuffled_cmd_flags, GZ_UTILS_TEST_DISABLED_ON_WIN32(SDF))
}
/////////////////////////////////////////////////
-TEST(print_snap_to_degrees_tolerance_too_high,
- GZ_UTILS_TEST_DISABLED_ON_WIN32(SDF))
+TEST(print_snap_to_degrees_tolerance_too_high, SDF)
{
const std::string path = sdf::testing::TestFile(
"sdf",
@@ -1731,7 +1727,7 @@ TEST(print_snap_to_degrees_tolerance_too_high,
}
/////////////////////////////////////////////////
-TEST(GraphCmd, GZ_UTILS_TEST_DISABLED_ON_WIN32(WorldPoseRelativeTo))
+TEST(GraphCmd, WorldPoseRelativeTo)
{
// world pose relative_to graph
const std::string path =
@@ -1780,7 +1776,7 @@ TEST(GraphCmd, GZ_UTILS_TEST_DISABLED_ON_WIN32(WorldPoseRelativeTo))
}
/////////////////////////////////////////////////
-TEST(GraphCmd, GZ_UTILS_TEST_DISABLED_ON_WIN32(ModelPoseRelativeTo))
+TEST(GraphCmd, ModelPoseRelativeTo)
{
const auto path =
sdf::testing::TestFile("sdf", "model_relative_to_nested_reference.sdf");
@@ -1857,7 +1853,7 @@ TEST(GraphCmd, GZ_UTILS_TEST_DISABLED_ON_WIN32(ModelPoseRelativeTo))
}
/////////////////////////////////////////////////
-TEST(GraphCmd, GZ_UTILS_TEST_DISABLED_ON_WIN32(WorldFrameAttachedTo))
+TEST(GraphCmd, WorldFrameAttachedTo)
{
const auto path =
sdf::testing::TestFile("sdf", "world_nested_frame_attached_to.sdf");
@@ -1903,7 +1899,7 @@ TEST(GraphCmd, GZ_UTILS_TEST_DISABLED_ON_WIN32(WorldFrameAttachedTo))
}
/////////////////////////////////////////////////
-TEST(GraphCmd, GZ_UTILS_TEST_DISABLED_ON_WIN32(ModelFrameAttachedTo))
+TEST(GraphCmd, ModelFrameAttachedTo)
{
const auto path =
sdf::testing::TestFile("sdf", "model_nested_frame_attached_to.sdf");
@@ -1955,7 +1951,7 @@ TEST(GraphCmd, GZ_UTILS_TEST_DISABLED_ON_WIN32(ModelFrameAttachedTo))
// Disable on arm
#if !defined __ARM_ARCH
/////////////////////////////////////////////////
-TEST(inertial_stats, GZ_UTILS_TEST_DISABLED_ON_WIN32(SDF))
+TEST(inertial_stats, SDF)
{
std::string expectedOutput =
"Inertial statistics for model: test_model\n"
@@ -2043,7 +2039,7 @@ TEST(inertial_stats, GZ_UTILS_TEST_DISABLED_ON_WIN32(SDF))
//////////////////////////////////////////////////
/// \brief Check help message and bash completion script for consistent flags
-TEST(HelpVsCompletionFlags, SDF)
+TEST(HelpVsCompletionFlags, GZ_UTILS_TEST_DISABLED_ON_WIN32(SDF))
{
// Flags in help message
std::string helpOutput = custom_exec_str(GzCommand() + " sdf --help");
@@ -2098,6 +2094,16 @@ int main(int argc, char **argv)
gz::utils::setenv("LD_LIBRARY_PATH", testLibraryPath);
#endif
+ // temporarily set HOME
+ std::string homeDir;
+ sdf::testing::TestTmpPath(homeDir);
+
+#ifdef _WIN32
+ gz::utils::setenv("HOMEPATH", homeDir);
+#else
+ gz::utils::setenv("HOME", homeDir);
+#endif
+
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}