How to Use Core Client Behaviors
SMACC2 includes reusable client behaviors in smacc2/include/smacc2/client_behaviors/ that work with any client library. This guide documents each one with header locations and usage.
CbSequence
Header: smacc2/client_behaviors/cb_sequence.hpp
Chains multiple behaviors to run sequentially within a single state. Each behavior starts after the previous one completes.
#include <smacc2/client_behaviors/cb_sequence.hpp>
static void staticConfigure()
{
auto sequence = configure_orthogonal<OrNavigation, CbSequence>();
sequence->then<OrNavigation, CbNavigateGlobalPosition>(2.0, 0.0, 0.0);
sequence->then<OrNavigation, CbRotate>(M_PI);
sequence->then<OrNavigation, CbNavigateGlobalPosition>(0.0, 0.0, 0.0);
}
The sequence posts EvCbSuccess when the last behavior in the chain completes.
CbSleepFor
Header: smacc2/client_behaviors/cb_sleep_for.hpp
Async sleep for a specified duration, then posts success.
#include <smacc2/client_behaviors/cb_sleep_for.hpp>
static void staticConfigure()
{
configure_orthogonal<OrTimer, CbSleepFor>(rclcpp::Duration(5, 0)); // 5 seconds
}
CbCallService
Header: smacc2/client_behaviors/cb_call_service.hpp
Template class for calling a ROS 2 service. Posts success on response, failure on timeout.
#include <smacc2/client_behaviors/cb_call_service.hpp>
// Usage: CbServiceCall<ServiceType>
static void staticConfigure()
{
auto cb = configure_orthogonal<OrService,
CbServiceCall<std_srvs::srv::Trigger>>();
// Configure the request before the state is entered
}
Override onServiceResponse() for custom response handling:
class CbMyServiceCall : public CbServiceCall<MyService>
{
void onServiceResponse(
const typename MyService::Response::SharedPtr & response) override
{
// Handle response
}
};
CbWaitTopicMessage
Header: smacc2/client_behaviors/cb_wait_topic_message.hpp
Waits for the first message on a topic, with an optional guard predicate.
#include <smacc2/client_behaviors/cb_wait_topic_message.hpp>
static void staticConfigure()
{
// Wait for any message
configure_orthogonal<OrSensor,
CbWaitTopicMessage<sensor_msgs::msg::LaserScan>>("/scan");
// Wait for a message matching a condition
configure_orthogonal<OrSensor,
CbWaitTopicMessage<sensor_msgs::msg::LaserScan>>(
"/scan",
[](const sensor_msgs::msg::LaserScan & msg) {
return msg.ranges.size() > 0;
});
}
CbWaitTopic
Header: smacc2/client_behaviors/cb_wait_topic.hpp
Waits for a topic to appear in the ROS 2 graph. Posts success when the topic exists.
#include <smacc2/client_behaviors/cb_wait_topic.hpp>
static void staticConfigure()
{
configure_orthogonal<OrSensor, CbWaitTopic>("/scan");
}
CbWaitActionServer
Header: smacc2/client_behaviors/cb_wait_action_server.hpp
Waits for an action server to become available, with a timeout.
#include <smacc2/client_behaviors/cb_wait_action_server.hpp>
static void staticConfigure()
{
configure_orthogonal<OrNavigation, CbWaitActionServer>(
std::chrono::seconds(30));
}
CbSubscriptionCallbackBase
Header: smacc2/client_behaviors/cb_subscription_callback_base.hpp
Base class for subscription-driven behaviors. Override onMessageReceived() in your subclass.
#include <smacc2/client_behaviors/cb_subscription_callback_base.hpp>
class CbMySubscription
: public CbSubscriptionCallbackBase<sensor_msgs::msg::LaserScan>
{
void onMessageReceived(const sensor_msgs::msg::LaserScan & msg) override
{
// Process each message
}
};
CbServiceServerCallbackBase
Header: smacc2/client_behaviors/cb_service_server_callback_base.hpp
Base class for service server behaviors. Override onServiceRequestReceived() in your subclass.
#include <smacc2/client_behaviors/cb_service_server_callback_base.hpp>
class CbMyServiceServer
: public CbServiceServerCallbackBase<std_srvs::srv::Trigger>
{
void onServiceRequestReceived(
const std::shared_ptr<std_srvs::srv::Trigger::Request> request,
std::shared_ptr<std_srvs::srv::Trigger::Response> response) override
{
response->success = true;
}
};
CbRosLaunch
Header: smacc2/client_behaviors/cb_ros_launch.hpp
Launches a ROS 2 package with configurable lifetime mode.
#include <smacc2/client_behaviors/cb_ros_launch.hpp>
static void staticConfigure()
{
// Detached: process outlives the behavior
configure_orthogonal<OrLaunch, CbRosLaunch>(
"my_package", "my_launch.py", RosLaunchMode::DETACHED);
// Behavior-scoped: process stops when behavior exits
configure_orthogonal<OrLaunch, CbRosLaunch>(
"my_package", "my_launch.py", RosLaunchMode::CLIENT_BEHAVIOR_LIFETIME);
}
CbWaitNode
Header: smacc2/client_behaviors/cb_wait_node.hpp
Waits for a ROS 2 node to appear in the node graph. Posts success when found.
#include <smacc2/client_behaviors/cb_wait_node.hpp>
static void staticConfigure()
{
configure_orthogonal<OrSystem, CbWaitNode>("/my_node");
}