New packages: - saltybot_social_msgs: PersonalityState.msg + QueryMood.srv custom interfaces - saltybot_social_personality: full personality node Features: - SOUL.md YAML/Markdown persona file: name, humor_level (0-10), sass_level (0-10), base_mood, per-tier greeting templates, mood prefix strings - Hot-reload: SoulWatcher polls SOUL.md every reload_interval seconds, applies changes live without restarting the node - Per-person relationship memory in SQLite: score, interaction_count, first/last_seen, learned preferences (JSON), full interaction log - Mood engine (pure functions): happy | curious | annoyed | playful driven by relationship score, interaction count, recent event window (120s) - Greeting personalisation: stranger | regular | favorite tiers keyed on interaction count thresholds from SOUL.md - Publishes /social/personality/state (PersonalityState) at publish_rate Hz - /social/personality/query_mood (QueryMood) service for on-demand mood query - Full ROS2 dynamic reconfigure: soul_file, db_path, reload_interval, publish_rate - 52 unit tests, no ROS2 runtime required ROS2 interfaces: Sub: /social/person_detected (std_msgs/String JSON) Pub: /social/personality/state (saltybot_social_msgs/PersonalityState) Srv: /social/personality/query_mood (saltybot_social_msgs/QueryMood)
100 lines
3.4 KiB
Python
100 lines
3.4 KiB
Python
"""
|
|
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),
|
|
])
|