Skill set_expression
Version: 1.0.0
Default path:
/skill/set_expressionDatatype: interaction_skills/msg/SetExpression
Definition source:
package.xmlin 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
stringName of the expression. See 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
floatThe desired valence of the expression, ranging from -1 (very negative) to 1 (very positive).
expression.arousal
floatThe desired arousal of the expression, ranging from -1 (very calm) to 1 (very excited).
Quick snippets
Call the skill from the command-line
$ ros2 topic pub /skill/set_expression interaction_skills/msg/SetExpression # then press Tab to complete the message prototype
Call the action from a Python script:
Call the action from a C++ program:
#include <functional>
#include <future>
#include <memory>
#include <string>
#include <sstream>
#include <chrono>
#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<const ::Feedback> 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)
You can call this skill from QML using the following code snippet. See ros_qml_plugin to learn more.
import Ros 2.0
// ...
SetExpressionSkill {
id: mySkill
}
// Call the skill
mySkill.set_expression();
See also
List of other Interaction skills