Program Listing for File action_client.hpp
↰ Return to documentation for file (/tmp/ws/src/robot_calibration/robot_calibration/include/robot_calibration/util/action_client.hpp
)
/*
* Copyright (C) 2022 Michael Ferguson
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Author: Michael Ferguson
#ifndef ROBOT_CALIBRATION_UTIL_ACTION_CLIENT_HPP
#define ROBOT_CALIBRATION_UTIL_ACTION_CLIENT_HPP
#include <chrono>
#include <string>
#include <rclcpp/rclcpp.hpp>
#include <rclcpp_action/rclcpp_action.hpp>
namespace robot_calibration
{
// Goal States
enum class ActionClientState
{
ACTIVE,
SUCCEEDED,
ABORTED,
};
template <typename ActionType>
class ActionClient
{
using GoalHandle = typename rclcpp_action::ClientGoalHandle<ActionType>;
using ActionWrappedResult = typename rclcpp_action::ClientGoalHandle<ActionType>::WrappedResult;
using ActionGoal = typename ActionType::Goal;
using ActionResult = typename ActionType::Result::SharedPtr;
public:
ActionClient() : state_(ActionClientState::ABORTED)
{
}
bool init(rclcpp::Node::SharedPtr node,
const std::string& name)
{
node_ = node;
name_ = name;
client_ = rclcpp_action::create_client<ActionType>(node, name);
return true;
}
bool waitForServer(double timeout)
{
auto node = node_.lock();
if (!node)
{
// Can't even really warn here...
return false;
}
RCLCPP_INFO(node->get_logger(), "Waiting for %s...", name_.c_str());
return client_->wait_for_action_server(std::chrono::milliseconds(static_cast<int>(1000 * timeout)));
}
void sendGoal(const typename ActionType::Goal& goal)
{
auto goal_options = typename rclcpp_action::Client<ActionType>::SendGoalOptions();
goal_options.result_callback =
std::bind(&ActionClient<ActionType>::resultCallback, this, std::placeholders::_1);
client_->async_send_goal(goal, goal_options);
state_ = ActionClientState::ACTIVE;
}
ActionClientState waitForResult(rclcpp::Duration timeout)
{
// Make sure we can lock the node
auto node = node_.lock();
if (!node)
{
// Can't even really warn here...
return state_;
}
// Wait for result, or timeout
rclcpp::Time start = node->now();
while (state_ == ActionClientState::ACTIVE)
{
rclcpp::spin_some(node);
rclcpp::sleep_for(std::chrono::milliseconds(10));
if ((node->now() - start) > timeout)
{
RCLCPP_WARN(node->get_logger(), "Timed out waiting for action result");
return state_;
}
}
return state_;
}
ActionResult getResult()
{
return result_;
}
private:
void resultCallback(const ActionWrappedResult& result)
{
if (result.code == rclcpp_action::ResultCode::SUCCEEDED)
{
state_ = ActionClientState::SUCCEEDED;
}
else
{
state_ = ActionClientState::ABORTED;
}
result_ = result.result;
}
std::string name_;
rclcpp::Node::WeakPtr node_;
std::shared_ptr<rclcpp_action::Client<ActionType>> client_;
ActionClientState state_;
ActionResult result_;
};
} // namespace robot_calibration
#endif // ROBOT_CALIBRATION_UTIL_ACTION_CLIENT_HPP