.. index:: set_expression .. _skill-set_expression: Skill ``set_expression`` ----------------------------------------------------------- - **Version**: 1.0.0 - **Default path**: ``/skill/set_expression`` - **Datatype**: :topic:`interaction_skills/msg/SetExpression` - **Definition source**: ``package.xml`` in `ros4hri/interaction_skills `_ Sets the expression of the robot. This might include changing the robot's face, body posture, or other expressive features. One either sets the expression by name, or by specifying the valence and arousal of the expression. Input parameters ~~~~~~~~~~~~~~~~ - **expression.expression** ``string`` Name of the expression. See :ref:`list_eyes_expressions` for details. One of: - neutral - angry - sad - happy - surprised - disgusted - scared - pleading - vulnerable - despaired - guilty - disappointed - embarrassed - horrified - skeptical - annoyed - furious - suspicious - rejected - bored - tired - asleep - confused - amazed - excited - **expression.valence** ``float`` The desired valence of the expression, ranging from -1 (very negative) to 1 (very positive). - **expression.arousal** ``float`` The desired arousal of the expression, ranging from -1 (very calm) to 1 (very excited). Quick snippets ~~~~~~~~~~~~~~ .. tabs:: .. tab:: Command-line Call the skill from the command-line .. code-block:: sh $ ros2 topic pub /skill/set_expression interaction_skills/msg/SetExpression # then press Tab to complete the message prototype .. tab:: ROS 2 action (Python) Call the action from a Python script: .. code-block:: python .. tab:: ROS 2 action (C++) Call the action from a C++ program: .. code-block:: cpp #include #include #include #include #include #include #include "interaction_skills/action/.hpp" #include "rclcpp/rclcpp.hpp" #include "rclcpp_action/rclcpp_hpp" #include "rclcpp_components/register_node_macro.hpp" using namespace std::chrono_literals; using namespace std; class SetexpressionActionClient : public rclcpp::Node { public: using = interaction_skills::action::; using GoalHandle = rclcpp_action::ClientGoalHandle<>; explicit SetexpressionActionClient(const rclcpp::NodeOptions & options) : Node("set_expression_action_client", options) { this->client_ptr_ = rclcpp_action::create_client<>( this, ""); this->timer_ = this->create_wall_timer( 500ms, bind(&SetexpressionActionClient::send_goal, this)); } void send_goal() { using namespace std::placeholders; this->timer_->cancel(); if (!this->client_ptr_->wait_for_action_server()) { RCLCPP_ERROR(this->get_logger(), "Action server not available after waiting"); rclcpp::shutdown(); } auto goal_msg = ::Goal(); // check the SetExpressionGoal message // definition for the possible goal parameters // goal_msg.... = ...; RCLCPP_INFO(this->get_logger(), "Sending goal"); auto send_goal_options = rclcpp_action::Client<>::SendGoalOptions(); send_goal_options.goal_response_callback = bind(&SetexpressionActionClient::goal_response_callback, this, _1); send_goal_options.feedback_callback = bind(&SetexpressionActionClient::feedback_callback, this, _1, _2); send_goal_options.result_callback = bind(&SetexpressionActionClient::result_callback, this, _1); this->client_ptr_->async_send_goal(goal_msg, send_goal_options); } private: rclcpp_action::Client<>::SharedPtr client_ptr_; rclcpp::TimerBase::SharedPtr timer_; void goal_response_callback(const GoalHandle::SharedPtr & goal_handle) { if (!goal_handle) { RCLCPP_ERROR(this->get_logger(), "Goal was rejected by server"); } else { RCLCPP_INFO(this->get_logger(), "Goal accepted by server, waiting for result"); } } void feedback_callback( GoalHandle::SharedPtr, const shared_ptr feedback) { stringstream ss; ss << "Next number in sequence received: "; for (auto number : feedback->partial_sequence) { ss << number << " "; } RCLCPP_INFO(this->get_logger(), ss.str().c_str()); } void result_callback(const GoalHandle::WrappedResult & result) { switch (result.code) { case rclcpp_action::ResultCode::SUCCEEDED: break; case rclcpp_action::ResultCode::ABORTED: RCLCPP_ERROR(this->get_logger(), "Goal was aborted"); return; case rclcpp_action::ResultCode::CANCELED: RCLCPP_ERROR(this->get_logger(), "Goal was canceled"); return; default: RCLCPP_ERROR(this->get_logger(), "Unknown result code"); return; } stringstream ss; ss << "Result received: "; for (auto number : result.result->sequence) { ss << number << " "; } RCLCPP_INFO(this->get_logger(), ss.str().c_str()); rclcpp::shutdown(); } }; // class SetexpressionActionClient RCLCPP_COMPONENTS_REGISTER_NODE(SetexpressionActionClient) .. tab:: QML You can call this skill from QML using the following code snippet. See :ref:`ros_qml_plugin` to learn more. .. code-block:: qml import Ros 2.0 // ... SetExpressionSkill { id: mySkill } // Call the skill mySkill.set_expression(); See also ~~~~~~~~ * List of other :ref:`interaction_skills` skills