""" personality.launch.py — Launch the saltybot personality node. Usage ----- # Defaults (bundled SOUL.md, ~/.ros/saltybot_personality.db): ros2 launch saltybot_social_personality personality.launch.py # Custom persona file: ros2 launch saltybot_social_personality personality.launch.py \\ soul_file:=/home/robot/my_persona/SOUL.md # Custom DB + faster reload: ros2 launch saltybot_social_personality personality.launch.py \\ db_path:=/data/saltybot.db reload_interval:=2.0 # Use a params file: ros2 launch saltybot_social_personality personality.launch.py \\ params_file:=/my/personality_params.yaml Dynamic reconfigure (no restart required) ----------------------------------------- ros2 param set /personality_node soul_file /new/SOUL.md ros2 param set /personality_node publish_rate 5.0 """ import os from ament_index_python.packages import get_package_share_directory from launch import LaunchDescription from launch.actions import DeclareLaunchArgument, OpaqueFunction from launch.substitutions import LaunchConfiguration from launch_ros.actions import Node def _launch_personality(context, *args, **kwargs): pkg_share = get_package_share_directory("saltybot_social_personality") params_file = LaunchConfiguration("params_file").perform(context) soul_file = LaunchConfiguration("soul_file").perform(context) db_path = LaunchConfiguration("db_path").perform(context) # Default soul_file to bundled config if not specified if not soul_file: soul_file = os.path.join(pkg_share, "config", "SOUL.md") # Expand ~ in db_path if db_path: db_path = os.path.expanduser(db_path) inline_params = { "soul_file": soul_file, "db_path": db_path or os.path.expanduser("~/.ros/saltybot_personality.db"), "reload_interval": float(LaunchConfiguration("reload_interval").perform(context)), "publish_rate": float(LaunchConfiguration("publish_rate").perform(context)), } node_params = [params_file, inline_params] if params_file else [inline_params] return [Node( package = "saltybot_social_personality", executable = "personality_node", name = "personality_node", output = "screen", parameters = node_params, )] def generate_launch_description(): pkg_share = get_package_share_directory("saltybot_social_personality") default_params = os.path.join(pkg_share, "config", "personality_params.yaml") return LaunchDescription([ DeclareLaunchArgument( "params_file", default_value=default_params, description="Full path to personality_params.yaml (base config)"), DeclareLaunchArgument( "soul_file", default_value="", description="Path to SOUL.md persona file (empty = bundled default)"), DeclareLaunchArgument( "db_path", default_value="~/.ros/saltybot_personality.db", description="SQLite relationship memory database path"), DeclareLaunchArgument( "reload_interval", default_value="5.0", description="SOUL.md hot-reload polling interval (s)"), DeclareLaunchArgument( "publish_rate", default_value="2.0", description="Personality state publish rate (Hz)"), OpaqueFunction(function=_launch_personality), ])