diff --git a/models/posim_sensor_models/CMakeLists.txt b/models/posim_sensor_models/CMakeLists.txt
index 0a76e60b..859ed80f 100644
--- a/models/posim_sensor_models/CMakeLists.txt
+++ b/models/posim_sensor_models/CMakeLists.txt
@@ -11,4 +11,10 @@ install(
ament_environment_hooks(
"${CMAKE_CURRENT_SOURCE_DIR}/hooks/${PROJECT_NAME}.dsv.in")
+if(BUILD_TESTING)
+ find_package(ament_cmake_pytest REQUIRED)
+ ament_add_pytest_test(test_dvl_tracking_bounds
+ test/test_dvl_tracking_bounds.py)
+endif()
+
ament_package()
diff --git a/models/posim_sensor_models/description/nortek_dvl1000_300/model.sdf b/models/posim_sensor_models/description/nortek_dvl1000_300/model.sdf
index acfa0fab..c8ec07da 100644
--- a/models/posim_sensor_models/description/nortek_dvl1000_300/model.sdf
+++ b/models/posim_sensor_models/description/nortek_dvl1000_300/model.sdf
@@ -60,7 +60,7 @@
10.
- 100.
+ 75.
10
diff --git a/models/posim_sensor_models/description/teledyne_explorer1000/model.sdf b/models/posim_sensor_models/description/teledyne_explorer1000/model.sdf
index 41d78e88..35838def 100644
--- a/models/posim_sensor_models/description/teledyne_explorer1000/model.sdf
+++ b/models/posim_sensor_models/description/teledyne_explorer1000/model.sdf
@@ -59,7 +59,7 @@
10.
- 100.
+ 81.
10
diff --git a/models/posim_sensor_models/description/teledyne_explorer4000/model.sdf b/models/posim_sensor_models/description/teledyne_explorer4000/model.sdf
index 7e8a1aba..d5689603 100644
--- a/models/posim_sensor_models/description/teledyne_explorer4000/model.sdf
+++ b/models/posim_sensor_models/description/teledyne_explorer4000/model.sdf
@@ -60,7 +60,7 @@
10.
- 100.
+ 66.
10
diff --git a/models/posim_sensor_models/description/teledyne_whn/model.sdf b/models/posim_sensor_models/description/teledyne_whn/model.sdf
index fe09b26b..b51a5632 100644
--- a/models/posim_sensor_models/description/teledyne_whn/model.sdf
+++ b/models/posim_sensor_models/description/teledyne_whn/model.sdf
@@ -61,7 +61,7 @@
10.
- 100.
+ 90.
10
diff --git a/models/posim_sensor_models/package.xml b/models/posim_sensor_models/package.xml
index 34f6d89d..982f4227 100644
--- a/models/posim_sensor_models/package.xml
+++ b/models/posim_sensor_models/package.xml
@@ -8,6 +8,7 @@
Ye-Seol Kwon
Apache 2.0
ament_cmake
+ ament_cmake_pytest
ament_cmake
diff --git a/models/posim_sensor_models/test/test_dvl_tracking_bounds.py b/models/posim_sensor_models/test/test_dvl_tracking_bounds.py
new file mode 100644
index 00000000..eafce323
--- /dev/null
+++ b/models/posim_sensor_models/test/test_dvl_tracking_bounds.py
@@ -0,0 +1,34 @@
+"""Catch DVL configurations rejected by Gazebo before publication starts."""
+
+from pathlib import Path
+import re
+import xml.etree.ElementTree as ET
+
+import pytest
+
+DESCRIPTION = Path(__file__).resolve().parents[1] / "description"
+DVL_MODELS = [p for p in sorted(DESCRIPTION.glob("*/model.sdf")) if "" in p.read_text()]
+
+
+def test_dvl_catalog_is_present():
+ assert DVL_MODELS, "No DVL descriptors found; check the test resource path"
+
+
+@pytest.mark.parametrize("path", DVL_MODELS, ids=lambda p: p.parent.name)
+def test_water_mass_layer_fits_sensor_range(path):
+ # SDF accepts the gz extension without an XML namespace declaration.
+ text = re.sub(r"