Skip to content

Commit 040f077

Browse files
committed
Avoid "jumps" with states that have tracking error. All test are passing but separatelly. Is there some kind of timeout?
1 parent 325bdb6 commit 040f077

File tree

4 files changed

+319
-79
lines changed

4 files changed

+319
-79
lines changed

joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller.hpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,14 @@ class JointTrajectoryController : public controller_interface::ControllerInterfa
122122
hardware_interface::HW_IF_EFFORT,
123123
};
124124

125+
// Parameters for some special cases, e.g. hydraulics powered robots
126+
/// Read hardware states only when starting controller. This is useful when robot is not exactly
127+
/// following the commanded trajectory.
128+
bool hardware_state_has_offset_ = false;
129+
trajectory_msgs::msg::JointTrajectoryPoint current_state_when_offset_;
130+
/// Allow integration in goal trajectories to accept goals without position or velocity specified
131+
bool allow_integration_in_goal_trajectories_ = false;
132+
125133
// The interfaces are defined as the types in 'allowed_interface_types_' member.
126134
// For convenience, for each type the interfaces are ordered so that i-th position
127135
// matches i-th index in joint_names_
@@ -131,6 +139,9 @@ class JointTrajectoryController : public controller_interface::ControllerInterfa
131139
joint_state_interface_;
132140

133141
/// If true, a velocity feedforward term plus corrective PID term is used
142+
// TODO(anyone): This flag is not used for now
143+
// There should be PID-approach used as in ROS1:
144+
// https://github.com/ros-controls/ros_controllers/blob/noetic-devel/joint_trajectory_controller/include/joint_trajectory_controller/hardware_interface_adapter.h#L283
134145
bool use_closed_loop_pid_adapter = false;
135146

136147
// TODO(karsten1987): eventually activate and deactive subscriber directly when its supported
@@ -207,7 +218,25 @@ class JointTrajectoryController : public controller_interface::ControllerInterfa
207218
const JointTrajectoryPoint & current_state,
208219
const JointTrajectoryPoint & state_error);
209220

221+
void read_state_from_hardware(JointTrajectoryPoint & state);
222+
210223
private:
224+
void resize_joint_trajectory_point(
225+
trajectory_msgs::msg::JointTrajectoryPoint & point, size_t size)
226+
{
227+
point.positions.resize(size);
228+
if (check_if_interface_type_exists(
229+
state_interface_types_, hardware_interface::HW_IF_VELOCITY))
230+
{
231+
point.velocities.resize(size);
232+
}
233+
if (check_if_interface_type_exists(
234+
state_interface_types_, hardware_interface::HW_IF_ACCELERATION))
235+
{
236+
point.accelerations.resize(size);
237+
}
238+
}
239+
211240
bool check_if_interface_type_exists(
212241
const std::vector<std::string> & interface_type_list, const std::string & interface_type)
213242
{

joint_trajectory_controller/src/joint_trajectory_controller.cpp

Lines changed: 60 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
333337
rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn
334338
JointTrajectoryController::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

Comments
 (0)