4242#include " rclcpp/rclcpp.hpp"
4343#include " vesc_driver/vesc_packet.hpp"
4444
45+ namespace
46+ {
47+ constexpr char CUSTOM_HW_IF_SERVO [] = " servo" ;
48+ } // namespace
49+
4550namespace vesc_hardware
4651{
4752hardware_interface::CallbackReturn VescHardware::on_init (
@@ -92,82 +97,64 @@ hardware_interface::CallbackReturn VescHardware::on_init(
9297 const auto & joint = info_.joints [0 ];
9398
9499 // Initialize list of supported interfaces
95- state_interfaces_ = {{hardware_interface::HW_IF_POSITION , " position" , false },
96- {hardware_interface::HW_IF_VELOCITY , " velocity" , false },
97- {" servo" , " servo" , false }};
98-
99- command_interfaces_ = {
100- {hardware_interface::HW_IF_POSITION , " position" , false },
101- {hardware_interface::HW_IF_VELOCITY , " velocity" , false },
102- {" servo" , " servo" , false }};
100+ populate_state_definitions ();
101+ populate_command_definitions ();
103102
104103 // Check which state interfaces are requested
105104 for (const auto & state_interface : joint.state_interfaces ) {
106- bool found = false ;
107- for (auto & supported_interface : state_interfaces_) {
108- if (state_interface.name == supported_interface.name ) {
109- if (supported_interface.requested ) {
110- RCLCPP_FATAL (
111- get_logger (),
112- " Duplicate state interface '%s' requested for joint '%s'" ,
113- state_interface.name .c_str (), joint.name .c_str ());
114- return hardware_interface::CallbackReturn::ERROR ;
115- }
116- supported_interface.requested = true ;
117- found = true ;
118- RCLCPP_INFO (get_logger (), " State interface '%s' requested" ,
119- state_interface.name .c_str ());
120- break ;
121- }
122- }
123- if (!found) {
105+ auto it = state_interfaces_.find (state_interface.name );
106+ if (it == state_interfaces_.end ()) {
124107 RCLCPP_FATAL (get_logger (),
125108 " Unsupported state interface '%s' requested for joint '%s'" ,
126109 state_interface.name .c_str (), joint.name .c_str ());
127110 return hardware_interface::CallbackReturn::ERROR ;
128111 }
112+ if (it->second .requested ) {
113+ RCLCPP_FATAL (
114+ get_logger (),
115+ " Duplicate state interface '%s' requested for joint '%s'" ,
116+ state_interface.name .c_str (), joint.name .c_str ());
117+ return hardware_interface::CallbackReturn::ERROR ;
118+ }
119+ it->second .requested = true ;
120+ RCLCPP_INFO (get_logger (), " State interface '%s' requested" ,
121+ state_interface.name .c_str ());
129122 }
130123
131124 // Check which command interfaces are requested
132125 for (const auto & command_interface : joint.command_interfaces ) {
133- bool found = false ;
134- for (auto & supported_interface : command_interfaces_) {
135- if (command_interface.name == supported_interface.name ) {
136- if (supported_interface.requested ) {
137- RCLCPP_FATAL (
138- get_logger (),
139- " Duplicate command interface '%s' requested for joint '%s'" ,
140- command_interface.name .c_str (), joint.name .c_str ());
141- return hardware_interface::CallbackReturn::ERROR ;
142- }
143- supported_interface.requested = true ;
144- found = true ;
145- RCLCPP_INFO (get_logger (), " Command interface '%s' requested" ,
146- command_interface.name .c_str ());
147- break ;
148- }
149- }
150- if (!found) {
126+ auto it = command_interfaces_.find (command_interface.name );
127+ if (it == command_interfaces_.end ()) {
151128 RCLCPP_FATAL (
152129 get_logger (),
153130 " Unsupported command interface '%s' requested for joint '%s'" ,
154131 command_interface.name .c_str (), joint.name .c_str ());
155132 return hardware_interface::CallbackReturn::ERROR ;
156133 }
134+ if (it->second .requested ) {
135+ RCLCPP_FATAL (
136+ get_logger (),
137+ " Duplicate command interface '%s' requested for joint '%s'" ,
138+ command_interface.name .c_str (), joint.name .c_str ());
139+ return hardware_interface::CallbackReturn::ERROR ;
140+ }
141+ it->second .requested = true ;
142+ RCLCPP_INFO (get_logger (), " Command interface '%s' requested" ,
143+ command_interface.name .c_str ());
157144 }
158145
159146 // Check that at least one interface is requested
160147 bool has_state_interface = false ;
161- for (const auto & iface : state_interfaces_) {
162- if (iface .requested ) {
148+ for (const auto & [name, data] : state_interfaces_) {
149+ if (data .requested ) {
163150 has_state_interface = true ;
164151 break ;
165152 }
166153 }
167154
168155 bool has_command_interface = false ;
169- for (const auto & iface : command_interfaces_) {
170- if (iface .requested ) {
156+ for (const auto & [name, data] : command_interfaces_) {
157+ if (data .requested ) {
171158 has_command_interface = true ;
172159 break ;
173160 }
@@ -186,8 +173,6 @@ hardware_interface::CallbackReturn VescHardware::on_init(
186173 // Initialize state and command storage
187174 hw_state_position_ = 0.0 ;
188175 hw_state_velocity_ = 0.0 ;
189- hw_command_position_ = 0.0 ;
190- hw_command_velocity_ = 0.0 ;
191176 hw_command_servo_ = 0.0 ;
192177
193178 return hardware_interface::CallbackReturn::SUCCESS ;
@@ -200,15 +185,15 @@ VescHardware::on_configure(const rclcpp_lifecycle::State & /*previous_state*/)
200185
201186 // Log which interfaces are active
202187 RCLCPP_INFO (get_logger (), " Active state interfaces:" );
203- for (const auto & iface : state_interfaces_) {
204- if (iface .requested ) {
205- RCLCPP_INFO (get_logger (), " - %s" , iface. type .c_str ());
188+ for (const auto & [name, data] : state_interfaces_) {
189+ if (data .requested ) {
190+ RCLCPP_INFO (get_logger (), " - %s" , name .c_str ());
206191 }
207192 }
208193 RCLCPP_INFO (get_logger (), " Active command interfaces:" );
209- for (const auto & iface : command_interfaces_) {
210- if (iface .requested ) {
211- RCLCPP_INFO (get_logger (), " - %s" , iface. type .c_str ());
194+ for (const auto & [name, data] : command_interfaces_) {
195+ if (data .requested ) {
196+ RCLCPP_INFO (get_logger (), " - %s" , name .c_str ());
212197 }
213198 }
214199
@@ -289,14 +274,9 @@ VescHardware::read(
289274 // (These are updated asynchronously by vescPacketCallback)
290275 for (const auto &[name, descr] : joint_state_interfaces_) {
291276 std::string interface_type = name.substr (name.find_last_of (" /" ) + 1 );
292-
293- if (interface_type == hardware_interface::HW_IF_POSITION ) {
294- set_state (name, hw_state_position_.load (std::memory_order_relaxed));
295- } else if (interface_type == hardware_interface::HW_IF_VELOCITY ) {
296- set_state (name, hw_state_velocity_.load (std::memory_order_relaxed));
297- } else if (interface_type == " servo" ) {
298- // Servo state mirrors command because the VESC cannot read servo position
299- set_state (name, hw_command_servo_);
277+ auto it = state_interfaces_.find (interface_type);
278+ if (it != state_interfaces_.end () && it->second .get_value ) {
279+ set_state (name, it->second .get_value ());
300280 }
301281 }
302282
@@ -317,22 +297,9 @@ VescHardware::write(
317297 for (const auto &[name, descr] : joint_command_interfaces_) {
318298 // Extract interface type from full name "motor_joint/velocity"
319299 std::string interface_type = name.substr (name.find_last_of (" /" ) + 1 );
320-
321- if (interface_type == hardware_interface::HW_IF_POSITION ) {
322- hw_command_position_ = get_command (name);
323- double vesc_position = convertMechanicalRadToDeg (hw_command_position_);
324- vesc_interface_->setPosition (vesc_position);
325- } else if (interface_type == hardware_interface::HW_IF_VELOCITY ) {
326- hw_command_velocity_ = get_command (name);
327- double vesc_erpm = convertMechanicalRadSecToERPM (hw_command_velocity_);
328- vesc_interface_->setSpeed (vesc_erpm);
329- } else if (interface_type == " servo" ) {
330- hw_command_servo_ = get_command (name);
331- vesc_interface_->setServo (hw_command_servo_);
332- } else {
333- RCLCPP_WARN_THROTTLE (get_logger (), *get_clock (), 1000 ,
334- " Unknown command interface type: %s" ,
335- interface_type.c_str ());
300+ auto it = command_interfaces_.find (interface_type);
301+ if (it != command_interfaces_.end () && it->second .set_command ) {
302+ it->second .set_command (get_command (name));
336303 }
337304 }
338305
@@ -368,6 +335,47 @@ double VescHardware::convertMechanicalRadSecToERPM(
368335 return erpm;
369336}
370337
338+ void VescHardware::populate_state_definitions ()
339+ {
340+ state_interfaces_[hardware_interface::HW_IF_POSITION ] = {
341+ false ,
342+ [this ]() {return hw_state_position_.load (std::memory_order_relaxed);}
343+ };
344+ state_interfaces_[hardware_interface::HW_IF_VELOCITY ] = {
345+ false ,
346+ [this ]() {return hw_state_velocity_.load (std::memory_order_relaxed);}
347+ };
348+ state_interfaces_[CUSTOM_HW_IF_SERVO ] = {
349+ false ,
350+ [this ]() {return hw_command_servo_;}
351+ };
352+ }
353+
354+ void VescHardware::populate_command_definitions ()
355+ {
356+ command_interfaces_[hardware_interface::HW_IF_POSITION ] = {
357+ false ,
358+ [this ](double value) {
359+ double vesc_position = convertMechanicalRadToDeg (value);
360+ vesc_interface_->setPosition (vesc_position);
361+ }
362+ };
363+ command_interfaces_[hardware_interface::HW_IF_VELOCITY ] = {
364+ false ,
365+ [this ](double value) {
366+ double vesc_erpm = convertMechanicalRadSecToERPM (value);
367+ vesc_interface_->setSpeed (vesc_erpm);
368+ }
369+ };
370+ command_interfaces_[CUSTOM_HW_IF_SERVO ] = {
371+ false ,
372+ [this ](double value) {
373+ hw_command_servo_ = value;
374+ vesc_interface_->setServo (hw_command_servo_);
375+ }
376+ };
377+ }
378+
371379void VescHardware::processValuesPacket (
372380 const vesc_driver::VescPacketValues *values_packet)
373381{
0 commit comments