@@ -71,6 +71,10 @@ JointTrajectoryController::init(const std::string & controller_name)
7171 node_->declare_parameter <double >(" state_publish_rate" , 50.0 );
7272 node_->declare_parameter <double >(" action_monitor_rate" , 20.0 );
7373 node_->declare_parameter <bool >(" allow_partial_joints_goal" , allow_partial_joints_goal_);
74+ node_->declare_parameter <bool >(
75+ " hardware_state_has_offset" , hardware_state_has_offset_);
76+ node_->declare_parameter <bool >(
77+ " allow_integration_in_goal_trajectories" , allow_integration_in_goal_trajectories_);
7478 node_->declare_parameter <double >(" constraints.stopped_velocity_tolerance" , 0.01 );
7579 node_->declare_parameter <double >(" constraints.goal_time" , 0.0 );
7680
@@ -116,21 +120,6 @@ JointTrajectoryController::update()
116120 return controller_interface::return_type::SUCCESS;
117121 }
118122
119- auto resize_joint_trajectory_point =
120- [&](trajectory_msgs::msg::JointTrajectoryPoint & point, size_t size)
121- {
122- point.positions .resize (size);
123- if (check_if_interface_type_exists (
124- state_interface_types_, hardware_interface::HW_IF_VELOCITY))
125- {
126- point.velocities .resize (size);
127- }
128- if (check_if_interface_type_exists (
129- state_interface_types_, hardware_interface::HW_IF_ACCELERATION))
130- {
131- point.accelerations .resize (size);
132- }
133- };
134123 auto compute_error_for_joint = [&](JointTrajectoryPoint & error, int index,
135124 const JointTrajectoryPoint & current, const JointTrajectoryPoint & desired)
136125 {
@@ -159,20 +148,14 @@ JointTrajectoryController::update()
159148 if (current_external_msg != *new_external_msg) {
160149 fill_partial_goal (*new_external_msg);
161150 sort_to_local_joint_order (*new_external_msg);
151+ // TODO(denis): Add here integration of position and velocity
162152 traj_external_point_ptr_->update (*new_external_msg);
163153 }
164154
165155 JointTrajectoryPoint state_current, state_desired, state_error;
166156 const auto joint_num = joint_names_.size ();
167157 resize_joint_trajectory_point (state_current, joint_num);
168158
169- auto assign_point_from_interface = [&, joint_num](
170- std::vector<double > & trajectory_point_interface, const auto & joint_inteface)
171- {
172- for (auto index = 0ul ; index < joint_num; ++index) {
173- trajectory_point_interface[index] = joint_inteface[index].get ().get_value ();
174- }
175- };
176159 // TODO(anyone): can I here also use const on joint_interface since the reference_wrapper is not
177160 // changed, but its value only?
178161 auto assign_interface_from_point = [&, joint_num](
@@ -185,35 +168,19 @@ JointTrajectoryController::update()
185168
186169 // current state update
187170 state_current.time_from_start .set__sec (0 );
188-
189- // Assign values from the hardware
190- // Position states always exist
191- assign_point_from_interface (state_current.positions , joint_state_interface_[0 ]);
192- // velocity and acceleration states are optional
193- if (check_if_interface_type_exists (state_interface_types_, hardware_interface::HW_IF_VELOCITY)) {
194- assign_point_from_interface (state_current.velocities , joint_state_interface_[1 ]);
195- // Acceleration is used only in combination with velocity
196- if (check_if_interface_type_exists (
197- state_interface_types_,
198- hardware_interface::HW_IF_ACCELERATION))
199- {
200- assign_point_from_interface (state_current.accelerations , joint_state_interface_[2 ]);
201- } else {
202- // Make empty so the property is ignored during interpolation
203- state_current.accelerations .clear ();
204- }
205- } else {
206- // Make empty so the property is ignored during interpolation
207- state_current.velocities .clear ();
208- state_current.accelerations .clear ();
209- }
171+ read_state_from_hardware (state_current);
210172
211173 // currently carrying out a trajectory
212174 if (traj_point_active_ptr_ && (*traj_point_active_ptr_)->has_trajectory_msg () == false ) {
213175 // if sampling the first time, set the point before you sample
214176 if (!(*traj_point_active_ptr_)->is_sampled_already ()) {
215- (*traj_point_active_ptr_)->set_point_before_trajectory_msg (
216- node_->now (), state_current);
177+ if (hardware_state_has_offset_) {
178+ (*traj_point_active_ptr_)->set_point_before_trajectory_msg (
179+ node_->now (), current_state_when_offset_);
180+ } else {
181+ (*traj_point_active_ptr_)->set_point_before_trajectory_msg (
182+ node_->now (), state_current);
183+ }
217184 }
218185 resize_joint_trajectory_point (state_error, joint_num);
219186
@@ -269,6 +236,9 @@ JointTrajectoryController::update()
269236 }
270237 }
271238
239+ // store command as state when hardware state has tracking offset
240+ current_state_when_offset_ = state_desired;
241+
272242 if (rt_active_goal_) {
273243 // send feedback
274244 auto feedback = std::make_shared<FollowJTrajAction::Feedback>();
@@ -330,6 +300,40 @@ JointTrajectoryController::update()
330300 return controller_interface::return_type::SUCCESS;
331301}
332302
303+ void JointTrajectoryController::read_state_from_hardware (JointTrajectoryPoint & state)
304+ {
305+ const auto joint_num = joint_names_.size ();
306+ auto assign_point_from_interface = [&, joint_num](
307+ std::vector<double > & trajectory_point_interface, const auto & joint_inteface)
308+ {
309+ for (auto index = 0ul ; index < joint_num; ++index) {
310+ trajectory_point_interface[index] = joint_inteface[index].get ().get_value ();
311+ }
312+ };
313+
314+ // Assign values from the hardware
315+ // Position states always exist
316+ assign_point_from_interface (state.positions , joint_state_interface_[0 ]);
317+ // velocity and acceleration states are optional
318+ if (check_if_interface_type_exists (state_interface_types_, hardware_interface::HW_IF_VELOCITY)) {
319+ assign_point_from_interface (state.velocities , joint_state_interface_[1 ]);
320+ // Acceleration is used only in combination with velocity
321+ if (check_if_interface_type_exists (
322+ state_interface_types_,
323+ hardware_interface::HW_IF_ACCELERATION))
324+ {
325+ assign_point_from_interface (state.accelerations , joint_state_interface_[2 ]);
326+ } else {
327+ // Make empty so the property is ignored during interpolation
328+ state.accelerations .clear ();
329+ }
330+ } else {
331+ // Make empty so the property is ignored during interpolation
332+ state.velocities .clear ();
333+ state.accelerations .clear ();
334+ }
335+ }
336+
333337rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn
334338JointTrajectoryController::on_configure (const rclcpp_lifecycle::State &)
335339{
@@ -487,6 +491,12 @@ JointTrajectoryController::on_configure(const rclcpp_lifecycle::State &)
487491
488492 default_tolerances_ = get_segment_tolerances (*node_, joint_names_);
489493
494+ // Read parameters customizing controller for special cases
495+ hardware_state_has_offset_ =
496+ node_->get_parameter (" hardware_state_has_offset" ).get_value <bool >();
497+ allow_integration_in_goal_trajectories_ =
498+ node_->get_parameter (" allow_integration_in_goal_trajectories" ).get_value <bool >();
499+
490500 // subscriber callback
491501 // non realtime
492502 // TODO(karsten): check if traj msg and point time are valid
@@ -653,6 +663,10 @@ JointTrajectoryController::on_activate(const rclcpp_lifecycle::State &)
653663 traj_point_active_ptr_ = &traj_external_point_ptr_;
654664 last_state_publish_time_ = node_->now ();
655665
666+ // Initialize current state storage if hardware state has tracking offset
667+ resize_joint_trajectory_point (current_state_when_offset_, joint_names_.size ());
668+ read_state_from_hardware (current_state_when_offset_);
669+
656670 // TODO(karsten1987): activate subscriptions of subscriber
657671 return rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn::SUCCESS;
658672}
0 commit comments