AutoAPMS
Streamlining behaviors in ROS 2
Loading...
Searching...
No Matches
direct_actuators_control.cpp
1// Copyright 2026 Robin Müller
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#include <limits>
16
17#include "auto_apms_px4/mode.hpp"
18#include "auto_apms_px4/mode_executor.hpp"
19#include "auto_apms_px4_interfaces/action/set_actuators.hpp"
20#include "px4_ros2/control/setpoint_types/direct_actuators.hpp"
21
22namespace auto_apms_px4
23{
24
25using SetActuatorsActionType = auto_apms_px4_interfaces::action::SetActuators;
26
27class SetActuatorsMode : public ModeBase<SetActuatorsActionType>
28{
29 std::shared_ptr<px4_ros2::DirectActuatorsSetpointType> actuator_setpoint_ptr_;
30 rclcpp::Time activation_time_;
31 bool commands_sent_{false};
32
33public:
34 SetActuatorsMode(
35 rclcpp::Node & node, px4_ros2::ModeBase::Settings settings, std::shared_ptr<ActionContextType> action_context_ptr)
36 : ModeBase{node, settings, action_context_ptr}
37 {
38 actuator_setpoint_ptr_ = std::make_shared<px4_ros2::DirectActuatorsSetpointType>(*this);
39 }
40
41private:
42 void OnActivateWithGoal(std::shared_ptr<const Goal> /*goal_ptr*/) final
43 {
44 activation_time_ = node().get_clock()->now();
45 commands_sent_ = false;
46 }
47
48 void UpdateSetpointWithGoal(
49 float /*dt_s*/, std::shared_ptr<const Goal> goal_ptr, std::shared_ptr<Feedback> /*feedback_ptr*/,
50 std::shared_ptr<Result> /*result_ptr*/) final
51 {
52 constexpr auto kNaN = std::numeric_limits<float>::quiet_NaN();
53 constexpr int kMaxMotors = px4_ros2::DirectActuatorsSetpointType::kMaxNumMotors;
54 constexpr int kMaxServos = px4_ros2::DirectActuatorsSetpointType::kMaxNumServos;
55
56 // Build motor command vector (NaN = disarmed for unspecified channels)
57 Eigen::Matrix<float, kMaxMotors, 1> motor_cmds = Eigen::Matrix<float, kMaxMotors, 1>::Constant(kNaN);
58 for (size_t i = 0; i < std::min(goal_ptr->motor_commands.size(), static_cast<size_t>(kMaxMotors)); ++i) {
59 motor_cmds(i) = goal_ptr->motor_commands[i];
60 }
61
62 // Build servo command vector (NaN = disarmed for unspecified channels)
63 Eigen::Matrix<float, kMaxServos, 1> servo_cmds = Eigen::Matrix<float, kMaxServos, 1>::Constant(kNaN);
64 for (size_t i = 0; i < std::min(goal_ptr->servo_commands.size(), static_cast<size_t>(kMaxServos)); ++i) {
65 servo_cmds(i) = goal_ptr->servo_commands[i];
66 }
67
68 const rclcpp::Duration elapsed = node().get_clock()->now() - activation_time_;
69 const rclcpp::Duration hold_duration =
70 rclcpp::Duration::from_nanoseconds(static_cast<int64_t>(goal_ptr->hold_period_ms) * 1'000'000LL);
71
72 if (!commands_sent_ || elapsed < hold_duration) {
73 // First call or still within hold period: send the requested commands
74 actuator_setpoint_ptr_->updateMotors(motor_cmds);
75 actuator_setpoint_ptr_->updateServos(servo_cmds);
76 commands_sent_ = true;
77 } else {
78 // Hold period elapsed: stop all actuators and signal completion
79 actuator_setpoint_ptr_->updateMotors(Eigen::Matrix<float, kMaxMotors, 1>::Constant(kNaN));
80 actuator_setpoint_ptr_->updateServos(Eigen::Matrix<float, kMaxServos, 1>::Constant(kNaN));
81 completed(px4_ros2::Result::Success);
82 }
83 }
84};
85
86class SetActuatorsSkill : public ModeExecutorFactory<SetActuatorsActionType, SetActuatorsMode>
87{
88public:
89 explicit SetActuatorsSkill(const rclcpp::NodeOptions & options)
90 : ModeExecutorFactory{_AUTO_APMS_PX4__SET_ACTUATORS_ACTION_NAME, options}
91 {
92 }
93};
94
95} // namespace auto_apms_px4
96
97#include "rclcpp_components/register_node_macro.hpp"
98RCLCPP_COMPONENTS_REGISTER_NODE(auto_apms_px4::SetActuatorsSkill)
Generic template class for a custom PX4 mode.
Definition mode.hpp:42
Helper template class that creates a ModeExecutor for a custom PX4 mode implemented by inheriting fro...
Implementation of PX4 mode peers offered by px4_ros2_cpp enabling integration with AutoAPMS.
Definition mode.hpp:28