Skip to content

Commit 79f917e

Browse files
authored
Fill point_before_trajectory with same information as trajectory (#2043)
1 parent d099cff commit 79f917e

File tree

3 files changed

+74
-0
lines changed

3 files changed

+74
-0
lines changed

doc/release_notes.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,10 @@ This list summarizes important changes between Kilted Kaiju (previous) and Lyric
88
force_torque_sensor_broadcaster
99
*******************************
1010
* Added support for transforming Wrench messages to a given list of target frames. This is useful when applications need force/torque data in their preferred coordinate frames. (`#2021 <https://github.com/ros-controls/ros2_controllers/pull/2021/files>`__).
11+
12+
joint_trajectory_controller
13+
***************************
14+
* Fill in 0 velocities and accelerations into point before trajectories if the state interfaces
15+
don't contain velocity / acceleration information, but the trajectory does. This way, the segment
16+
up to the first waypoint will use the same interpolation as the rest of the trajectory. (`#2043
17+
<https://github.com/ros-controls/ros2_controllers/pull/2043>`_)

joint_trajectory_controller/src/trajectory.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,20 @@ void Trajectory::set_point_before_trajectory_msg(
5050
time_before_traj_msg_ = current_time;
5151
state_before_traj_msg_ = current_point;
5252

53+
// If the current state doesn't contain velocities / accelerations, but the first trajectory
54+
// point does, initialize them to zero. Otherwise the segment going from the current state to the
55+
// first trajectory point will use another degree of spline interpolation than the rest of the
56+
// trajectory.
57+
if (current_point.velocities.empty() && !trajectory_msg_->points[0].velocities.empty())
58+
{
59+
state_before_traj_msg_.velocities.resize(trajectory_msg_->points[0].velocities.size(), 0.0);
60+
}
61+
if (current_point.accelerations.empty() && !trajectory_msg_->points[0].accelerations.empty())
62+
{
63+
state_before_traj_msg_.accelerations.resize(
64+
trajectory_msg_->points[0].accelerations.size(), 0.0);
65+
}
66+
5367
// Compute offsets due to wrapping joints
5468
wraparound_joint(
5569
state_before_traj_msg_.positions, trajectory_msg_->points[0].positions,

joint_trajectory_controller/test/test_trajectory.cpp

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -725,6 +725,59 @@ TEST(TestTrajectory, sample_trajectory_acceleration_with_interpolation)
725725
}
726726
}
727727

728+
TEST(TestTrajectory, fill_point_before_with_same_degree_as_traj)
729+
{
730+
auto full_msg = std::make_shared<trajectory_msgs::msg::JointTrajectory>();
731+
full_msg->header.stamp = rclcpp::Time(0);
732+
733+
// definitions
734+
double time_first_seg = 1.0;
735+
double time_second_seg = 2.0;
736+
double position_first_seg = 1.0;
737+
double position_second_seg = 2.0;
738+
double velocity_first_seg = 0.0;
739+
double velocity_second_seg = 0.0;
740+
double acceleration_first_seg = 0.0;
741+
double acceleration_second_seg = 0.0;
742+
743+
trajectory_msgs::msg::JointTrajectoryPoint p1;
744+
p1.time_from_start = rclcpp::Duration::from_seconds(time_first_seg);
745+
p1.positions.push_back(position_first_seg);
746+
p1.velocities.push_back(velocity_first_seg);
747+
p1.accelerations.push_back(acceleration_first_seg);
748+
full_msg->points.push_back(p1);
749+
750+
trajectory_msgs::msg::JointTrajectoryPoint p2;
751+
p2.time_from_start = rclcpp::Duration::from_seconds(time_second_seg);
752+
p2.positions.push_back(position_second_seg);
753+
p2.velocities.push_back(velocity_second_seg);
754+
p2.accelerations.push_back(acceleration_second_seg);
755+
full_msg->points.push_back(p2);
756+
757+
trajectory_msgs::msg::JointTrajectoryPoint point_before_msg;
758+
point_before_msg.time_from_start = rclcpp::Duration::from_seconds(0.0);
759+
point_before_msg.positions.push_back(0.0);
760+
761+
const rclcpp::Time time_now = rclcpp::Clock().now();
762+
auto traj = joint_trajectory_controller::Trajectory(time_now, point_before_msg, full_msg);
763+
764+
trajectory_msgs::msg::JointTrajectoryPoint expected_state;
765+
joint_trajectory_controller::TrajectoryPointConstIter start, end;
766+
767+
// sample at trajectory starting time
768+
// Since the trajectory defines positions, velocities, and accelerations, we expect quintic
769+
// spline interpolation. Due to the unspecified initial acceleration, it should be zero.
770+
{
771+
traj.sample(time_now, DEFAULT_INTERPOLATION, expected_state, start, end);
772+
EXPECT_EQ(0, traj.last_sample_index());
773+
ASSERT_EQ(traj.begin(), start);
774+
ASSERT_EQ(traj.begin(), end);
775+
EXPECT_NEAR(point_before_msg.positions[0], expected_state.positions[0], EPS);
776+
EXPECT_NEAR(0.0, expected_state.velocities[0], EPS);
777+
EXPECT_NEAR(0.0, expected_state.accelerations[0], EPS);
778+
}
779+
}
780+
728781
TEST(TestTrajectory, skip_interpolation)
729782
{
730783
// Simple passthrough without extra interpolation

0 commit comments

Comments
 (0)