sl-jetson 50971c0946
Some checks failed
social-bot integration tests / Lint (flake8 + pep257) (push) Failing after 2s
social-bot integration tests / Core integration tests (mock sensors, no GPU) (push) Has been skipped
social-bot integration tests / Lint (flake8 + pep257) (pull_request) Failing after 2s
social-bot integration tests / Core integration tests (mock sensors, no GPU) (pull_request) Has been skipped
social-bot integration tests / Latency profiling (GPU, Orin) (push) Has been cancelled
social-bot integration tests / Latency profiling (GPU, Orin) (pull_request) Has been cancelled
feat(social): facial expression recognition — TRT FP16 emotion CNN (Issue #161)
- Add Expression.msg / ExpressionArray.msg ROS2 message definitions
- Add emotion_classifier.py: 7-class CNN (happy/sad/angry/surprised/fearful/disgusted/neutral)
  via TensorRT FP16 with landmark-geometry fallback; EMA per-person smoothing; opt-out registry
- Add emotion_node.py: subscribes /social/faces/detections, runs TRT crop inference (<5ms),
  publishes /social/faces/expressions and /social/emotion/context JSON for LLM
- Wire emotion context into conversation_node.py: emotion hint injected into LLM prompt
  when speaker shows non-neutral affect; subscribes /social/emotion/context
- Add emotion_params.yaml config and emotion.launch.py launch file
- Add 67-test suite (test_emotion_classifier.py): classifier, tracker, opt-out, heuristic

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 10:40:54 -05:00

68 lines
2.6 KiB
Python

"""emotion.launch.py — Launch emotion_node for facial expression recognition (Issue #161)."""
from launch import LaunchDescription
from launch.actions import DeclareLaunchArgument
from launch.substitutions import LaunchConfiguration, PathJoinSubstitution
from launch_ros.actions import Node
from launch_ros.substitutions import FindPackageShare
def generate_launch_description() -> LaunchDescription:
pkg = FindPackageShare("saltybot_social")
params_file = PathJoinSubstitution([pkg, "config", "emotion_params.yaml"])
return LaunchDescription([
DeclareLaunchArgument(
"params_file",
default_value=params_file,
description="Path to emotion_node parameter YAML",
),
DeclareLaunchArgument(
"engine_path",
default_value="/models/emotion_fp16.trt",
description="Path to TensorRT FP16 emotion engine (empty = landmark heuristic)",
),
DeclareLaunchArgument(
"min_confidence",
default_value="0.40",
description="Minimum detection confidence to publish an expression",
),
DeclareLaunchArgument(
"smoothing_alpha",
default_value="0.30",
description="EMA smoothing weight (0=frozen, 1=no smoothing)",
),
DeclareLaunchArgument(
"opt_out_persons",
default_value="",
description="Comma-separated person_ids that opted out",
),
DeclareLaunchArgument(
"landmark_fallback",
default_value="true",
description="Use landmark heuristic when TRT engine unavailable",
),
DeclareLaunchArgument(
"publish_context",
default_value="true",
description="Publish /social/emotion/context JSON for LLM context",
),
Node(
package="saltybot_social",
executable="emotion_node",
name="emotion_node",
output="screen",
parameters=[
LaunchConfiguration("params_file"),
{
"engine_path": LaunchConfiguration("engine_path"),
"min_confidence": LaunchConfiguration("min_confidence"),
"smoothing_alpha": LaunchConfiguration("smoothing_alpha"),
"opt_out_persons": LaunchConfiguration("opt_out_persons"),
"landmark_fallback": LaunchConfiguration("landmark_fallback"),
"publish_context": LaunchConfiguration("publish_context"),
},
],
),
])