1+ // Copyright 2021 ros2_control Development Team
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+ #ifndef CURT_MINI_SYSTEM_HPP_
16+ #define CURT_MINI_SYSTEM_HPP_
17+
18+ #include < chrono>
19+ #include < limits>
20+ #include < memory>
21+ #include < string>
22+ #include < vector>
23+
24+ #include " hardware_interface/handle.hpp"
25+ #include " hardware_interface/hardware_info.hpp"
26+ #include " hardware_interface/system_interface.hpp"
27+ #include " hardware_interface/types/hardware_interface_return_values.hpp"
28+ #include " hardware_interface/types/hardware_interface_type_values.hpp"
29+ #include " rclcpp/clock.hpp"
30+ #include " rclcpp/duration.hpp"
31+ #include " rclcpp/macros.hpp"
32+ #include " rclcpp/rclcpp.hpp"
33+ #include " rclcpp/time.hpp"
34+ #include < sensor_msgs/msg/joint_state.hpp>
35+ #include " rclcpp_lifecycle/node_interfaces/lifecycle_node_interface.hpp"
36+ #include " rclcpp_lifecycle/state.hpp"
37+
38+ #include " candle_ros2/msg/impedance_command.hpp"
39+ #include " candle_ros2/msg/motion_command.hpp"
40+ #include " candle_ros2/msg/position_pid_command.hpp"
41+ #include " candle_ros2/msg/velocity_pid_command.hpp"
42+ #include " candle_ros2/srv/add_md80s.hpp"
43+ #include " candle_ros2/srv/generic_md80_msg.hpp"
44+ #include " candle_ros2/srv/set_limits_md80.hpp"
45+ #include " candle_ros2/srv/set_mode_md80s.hpp"
46+
47+ namespace ipa_ros2_control
48+ {
49+ using CallbackReturn = rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn;
50+
51+ class CurtMiniHardwareInterface : public hardware_interface ::SystemInterface
52+ {
53+ public:
54+
55+ CallbackReturn
56+ on_init (const hardware_interface::HardwareInfo &hardware_info) override ;
57+
58+ std::vector<hardware_interface::StateInterface> export_state_interfaces () override ;
59+
60+ std::vector<hardware_interface::CommandInterface> export_command_interfaces () override ;
61+
62+ void jointsCallback (const std::shared_ptr<sensor_msgs::msg::JointState> msg);
63+
64+ CallbackReturn
65+ on_activate (const rclcpp_lifecycle::State &previous_state) override ;
66+ CallbackReturn
67+ on_deactivate (const rclcpp_lifecycle::State &previous_state) override ;
68+
69+ hardware_interface::return_type read (const rclcpp::Time &time, const rclcpp::Duration &period) override ;
70+
71+ hardware_interface::return_type write (const rclcpp::Time &time, const rclcpp::Duration &period) override ;
72+
73+ private:
74+ rclcpp::Node::SharedPtr nh_;
75+ // inspired by Jackal github
76+ void writeCommandsToHardware ();
77+ void updateJointsFromHardware ();
78+ void publishPIDParams (const candle_ros2::msg::Pid& pid_config);
79+ // bool sendGenericRequest(rclcpp::Client<candle_ros2::srv::GenericMd80Msg>::SharedPtr& client);
80+
81+ /* *
82+ *
83+ * Wrapper function for templated node's declare_parameter() which checks if
84+ * parameter is already declared.
85+ * (Copied from ControllerInterface base class)
86+ */
87+ template <typename ParameterT>
88+ auto auto_declare (const std::string& name, const ParameterT& default_value)
89+ {
90+ if (!nh_->has_parameter (name))
91+ {
92+ return nh_->declare_parameter <ParameterT>(name, default_value);
93+ }
94+ else
95+ {
96+ return nh_->get_parameter (name).get_value <ParameterT>();
97+ }
98+ }
99+
100+ template <typename candle_srv_type>
101+ bool sendCandleRequest (
102+ typename rclcpp::Client<candle_srv_type>::SharedPtr client,
103+ typename candle_srv_type::Request::SharedPtr request = std::make_shared<typename candle_srv_type::Request>())
104+ {
105+ RCLCPP_INFO_STREAM (nh_->get_logger (), " Calling " << client->get_service_name ());
106+ request->drive_ids = { 102 , 100 , 103 , 101 }; // { br , fr, bl , fl}
107+ auto result = client->async_send_request (request);
108+ if (rclcpp::spin_until_future_complete (nh_, result, std::chrono::seconds{5 }) == rclcpp::FutureReturnCode::SUCCESS)
109+ {
110+ RCLCPP_INFO_STREAM (nh_->get_logger (), " Calling " );
111+ auto res = *result.get ();
112+ if (!std::all_of (res.drives_success .begin (), res.drives_success .end (),
113+ [](bool b) { return b; }))
114+ {
115+ RCLCPP_ERROR_STREAM (nh_->get_logger (),
116+ " Service " << client->get_service_name () << " was not successfull for all motors! Exiting" );
117+ return false ;
118+ }
119+ }
120+ else
121+ {
122+ RCLCPP_ERROR_STREAM (nh_->get_logger (), " Calling " << client->get_service_name () << " failed! Exiting" );
123+ return false ;
124+ }
125+ return true ;
126+ }
127+
128+ // Store the command for the robot
129+ std::vector<double > hw_commands_;
130+ std::vector<double > hw_states_position_, hw_states_velocity_;
131+ sensor_msgs::msg::JointState motor_joint_state_;
132+ // ROS services
133+ rclcpp::Client<candle_ros2::srv::AddMd80s>::SharedPtr add_controller_service_client_;
134+ rclcpp::Client<candle_ros2::srv::SetModeMd80s>::SharedPtr set_mode_service_client_;
135+ rclcpp::Client<candle_ros2::srv::GenericMd80Msg>::SharedPtr set_zero_service_client_;
136+ rclcpp::Client<candle_ros2::srv::GenericMd80Msg>::SharedPtr enable_motors_service_client_;
137+ rclcpp::Client<candle_ros2::srv::GenericMd80Msg>::SharedPtr disable_motors_service_client_;
138+
139+ // ROS publishers
140+ rclcpp::Publisher<candle_ros2::msg::MotionCommand>::SharedPtr command_pub_;
141+ rclcpp::Publisher<candle_ros2::msg::VelocityPidCommand>::SharedPtr config_pub_;
142+
143+ // ROS subscribers
144+ rclcpp::Subscription<sensor_msgs::msg::JointState>::SharedPtr joint_state_sub_;
145+ // controller params
146+ rclcpp::node_interfaces::OnSetParametersCallbackHandle::SharedPtr param_callback_handle_;
147+ candle_ros2::msg::Pid pid_config_;
148+ double standstill_thresh_{ 0.01 };
149+ bool motors_paused_{ false };
150+
151+ void pauseMotors ();
152+ void resumeMotors ();
153+
154+ // map of joint names and there index
155+ std::map<std::string, uint8_t > wheel_joints_;
156+ };
157+
158+ } // namespace ipa_ros2_control
159+
160+ #endif // CURT_MINI_SYSTEM_HPP
0 commit comments