diff --git a/MIGRATION.md b/MIGRATION.md
index b2d6977bc7..fb3ce83d47 100644
--- a/MIGRATION.md
+++ b/MIGRATION.md
@@ -3,6 +3,7 @@
API changes in MoveIt releases
## ROS Rolling
+- [07/2026] Generated warehouse launch files now use SQLite instead of MongoDB. Use `moveit_warehouse_database_path` to select the SQLite database file. The MongoDB-specific `moveit_warehouse_host` and `moveit_warehouse_port` launch arguments were removed. By default, the database is created in `$ROS_HOME` (or `~/.ros`) with a config-package-specific filename.
- [11/2024] All MoveIt 2 headers have been updated to use the .hpp extension. .h headers are now autogenerated with a deprecation warning, and may be removed in future releases. Please update your imports to use the .hpp headers.
- [11/2024] Added flags to control padding to CollisionRequest. This change deprecates PlanningScene::checkCollisionUnpadded(..) functions. Please use PlanningScene::checkCollision(..) with a req.pad_environment_collisions = false;
diff --git a/moveit_configs_utils/moveit_configs_utils/launches.py b/moveit_configs_utils/moveit_configs_utils/launches.py
index d03d92467f..581927fa61 100644
--- a/moveit_configs_utils/moveit_configs_utils/launches.py
+++ b/moveit_configs_utils/moveit_configs_utils/launches.py
@@ -3,13 +3,14 @@
from launch import LaunchDescription
from launch.actions import (
DeclareLaunchArgument,
+ GroupAction,
IncludeLaunchDescription,
)
from launch.conditions import IfCondition
from launch.launch_description_sources import PythonLaunchDescriptionSource
from launch.substitutions import LaunchConfiguration
-from launch_ros.actions import Node
+from launch_ros.actions import Node, SetParameter
from launch_ros.parameter_descriptions import ParameterValue
from srdfdom.srdf import SRDF
@@ -134,52 +135,38 @@ def generate_spawn_controllers_launch(moveit_config):
def generate_warehouse_db_launch(moveit_config):
- """Launch file for warehouse database"""
+ """Launch file for SQLite warehouse database."""
ld = LaunchDescription()
ld.add_action(
DeclareLaunchArgument(
"moveit_warehouse_database_path",
- default_value=str(
- moveit_config.package_path / "default_warehouse_mongo_db"
+ default_value=os.path.join(
+ os.environ.get("ROS_HOME", os.path.expanduser("~/.ros")),
+ f"{moveit_config.package_path.name}_warehouse.sqlite",
),
)
)
ld.add_action(DeclareBooleanLaunchArg("reset", default_value=False))
- # The default DB port for moveit (not default MongoDB port to avoid potential conflicts)
- ld.add_action(DeclareLaunchArgument("moveit_warehouse_port", default_value="33829"))
-
- # The default DB host for moveit
ld.add_action(
- DeclareLaunchArgument("moveit_warehouse_host", default_value="localhost")
+ SetParameter(
+ name="warehouse_plugin",
+ value="warehouse_ros_sqlite::DatabaseConnection",
+ )
)
-
- # Load warehouse parameters
- db_parameters = [
- {
- "overwrite": False,
- "database_path": LaunchConfiguration("moveit_warehouse_database_path"),
- "warehouse_port": LaunchConfiguration("moveit_warehouse_port"),
- "warehouse_host": LaunchConfiguration("moveit_warehouse_host"),
- "warehouse_exec": "mongod",
- "warehouse_plugin": "warehouse_ros_mongo::MongoDatabaseConnection",
- },
- ]
- # Run the DB server
- db_node = Node(
- package="warehouse_ros_mongo",
- executable="mongo_wrapper_ros.py",
- # TODO(dlu): Figure out if this needs to be run in a specific directory
- # (ROS 1 version set cwd="ROS_HOME")
- parameters=db_parameters,
+ ld.add_action(
+ SetParameter(
+ name="warehouse_host",
+ value=LaunchConfiguration("moveit_warehouse_database_path"),
+ )
)
- ld.add_action(db_node)
- # If we want to reset the database, run this node
+ # If requested, reset the database and add the default scene and robot state.
reset_node = Node(
package="moveit_ros_warehouse",
executable="moveit_init_demo_warehouse",
output="screen",
+ parameters=[moveit_config.to_dict()],
condition=IfCondition(LaunchConfiguration("reset")),
)
ld.add_action(reset_node)
@@ -277,7 +264,7 @@ def generate_demo_launch(moveit_config, launch_package_path=None):
DeclareBooleanLaunchArg(
"db",
default_value=False,
- description="By default, we do not start a database (it can be large)",
+ description="By default, we do not configure a warehouse database",
)
)
ld.add_action(
@@ -309,31 +296,29 @@ def generate_demo_launch(moveit_config, launch_package_path=None):
)
)
+ # Limit warehouse parameters to the nodes that consume them.
ld.add_action(
- IncludeLaunchDescription(
- PythonLaunchDescriptionSource(
- str(launch_package_path / "launch/move_group.launch.py")
- ),
- )
- )
-
- # Run Rviz and load the default config to see the state of the move_group node
- ld.add_action(
- IncludeLaunchDescription(
- PythonLaunchDescriptionSource(
- str(launch_package_path / "launch/moveit_rviz.launch.py")
- ),
- condition=IfCondition(LaunchConfiguration("use_rviz")),
- )
- )
-
- # If database loading was enabled, start mongodb as well
- ld.add_action(
- IncludeLaunchDescription(
- PythonLaunchDescriptionSource(
- str(launch_package_path / "launch/warehouse_db.launch.py")
- ),
- condition=IfCondition(LaunchConfiguration("db")),
+ GroupAction(
+ actions=[
+ IncludeLaunchDescription(
+ PythonLaunchDescriptionSource(
+ str(launch_package_path / "launch/warehouse_db.launch.py")
+ ),
+ condition=IfCondition(LaunchConfiguration("db")),
+ ),
+ IncludeLaunchDescription(
+ PythonLaunchDescriptionSource(
+ str(launch_package_path / "launch/move_group.launch.py")
+ ),
+ ),
+ # Run Rviz and load the default MoveIt configuration.
+ IncludeLaunchDescription(
+ PythonLaunchDescriptionSource(
+ str(launch_package_path / "launch/moveit_rviz.launch.py")
+ ),
+ condition=IfCondition(LaunchConfiguration("use_rviz")),
+ ),
+ ]
)
)
diff --git a/moveit_configs_utils/test/test_warehouse_launch.py b/moveit_configs_utils/test/test_warehouse_launch.py
new file mode 100644
index 0000000000..9b67dcafa2
--- /dev/null
+++ b/moveit_configs_utils/test/test_warehouse_launch.py
@@ -0,0 +1,148 @@
+from pathlib import Path
+from types import SimpleNamespace
+
+from launch import LaunchContext
+from launch.actions import (
+ DeclareLaunchArgument,
+ GroupAction,
+ IncludeLaunchDescription,
+ LogInfo,
+)
+from launch.conditions import IfCondition
+from launch_ros.actions import SetParameter
+
+from moveit_configs_utils import launches
+
+
+def _execute_parameter_actions(actions, context):
+ for action in actions:
+ if isinstance(action, (DeclareLaunchArgument, SetParameter)):
+ action.execute(context)
+
+
+def test_generate_warehouse_db_launch_uses_sqlite(monkeypatch, tmp_path):
+ node_calls = []
+ ros_home = tmp_path / "ros_home"
+ config_package_path = tmp_path / "test_moveit_config"
+ monkeypatch.setenv("ROS_HOME", str(ros_home))
+
+ def capture_node(**kwargs):
+ node_calls.append(kwargs)
+ return LogInfo(msg="captured node")
+
+ monkeypatch.setattr(launches, "Node", capture_node)
+
+ moveit_parameters = {
+ "robot_description": "",
+ "robot_description_semantic": "",
+ }
+ moveit_config = SimpleNamespace(
+ package_path=config_package_path,
+ to_dict=lambda: moveit_parameters,
+ )
+
+ launch_description = launches.generate_warehouse_db_launch(moveit_config)
+ actions = launch_description.entities
+
+ launch_arguments = {
+ action.name: action
+ for action in actions
+ if isinstance(action, DeclareLaunchArgument)
+ }
+ assert set(launch_arguments) == {
+ "moveit_warehouse_database_path",
+ "reset",
+ }
+
+ set_parameters = [action for action in actions if isinstance(action, SetParameter)]
+ assert len(set_parameters) == 2
+
+ context = LaunchContext()
+ _execute_parameter_actions(actions, context)
+
+ assert context.launch_configurations["moveit_warehouse_database_path"] == str(
+ ros_home / "test_moveit_config_warehouse.sqlite"
+ )
+
+ global_parameters = dict(context.launch_configurations["global_params"])
+ assert global_parameters == {
+ "warehouse_plugin": "warehouse_ros_sqlite::DatabaseConnection",
+ "warehouse_host": str(ros_home / "test_moveit_config_warehouse.sqlite"),
+ }
+
+ custom_database_path = str(tmp_path / "custom.sqlite")
+ custom_context = LaunchContext()
+ custom_context.launch_configurations["moveit_warehouse_database_path"] = (
+ custom_database_path
+ )
+ _execute_parameter_actions(actions, custom_context)
+
+ custom_parameters = dict(custom_context.launch_configurations["global_params"])
+ assert custom_parameters["warehouse_host"] == custom_database_path
+
+ # SQLite requires no separate server, so only the reset node is generated.
+ assert len(node_calls) == 1
+
+ reset_node = node_calls[0]
+ assert reset_node["package"] == "moveit_ros_warehouse"
+ assert reset_node["executable"] == "moveit_init_demo_warehouse"
+ assert reset_node["output"] == "screen"
+ assert reset_node["parameters"] == [moveit_parameters]
+ assert isinstance(reset_node["condition"], IfCondition)
+
+ context.launch_configurations["reset"] = "true"
+ assert reset_node["condition"].evaluate(context)
+
+ context.launch_configurations["reset"] = "false"
+ assert not reset_node["condition"].evaluate(context)
+
+
+def test_demo_launch_scopes_warehouse_before_consumers(tmp_path):
+ launch_directory = tmp_path / "launch"
+ launch_directory.mkdir()
+
+ launch_file_contents = """\
+from launch import LaunchDescription
+
+
+def generate_launch_description():
+ return LaunchDescription()
+"""
+
+ for filename in (
+ "rsp.launch.py",
+ "warehouse_db.launch.py",
+ "move_group.launch.py",
+ "moveit_rviz.launch.py",
+ "spawn_controllers.launch.py",
+ ):
+ (launch_directory / filename).write_text(launch_file_contents)
+
+ moveit_config = SimpleNamespace(package_path=tmp_path)
+ launch_description = launches.generate_demo_launch(moveit_config)
+
+ groups = [
+ action
+ for action in launch_description.entities
+ if isinstance(action, GroupAction)
+ ]
+ assert len(groups) == 1
+
+ includes = [
+ action
+ for action in groups[0].get_sub_entities()
+ if isinstance(action, IncludeLaunchDescription)
+ ]
+
+ context = LaunchContext()
+ include_names = []
+ for action in includes:
+ source = action.launch_description_source
+ source.get_launch_description(context)
+ include_names.append(Path(source.location).name)
+
+ assert include_names == [
+ "warehouse_db.launch.py",
+ "move_group.launch.py",
+ "moveit_rviz.launch.py",
+ ]