Skip to content

Commit a690660

Browse files
authored
feat(motion_utils): add new calcSignedArcLength (autowarefoundation#1701)
Signed-off-by: Takayuki Murooka <takayuki5168@gmail.com> Signed-off-by: Takayuki Murooka <takayuki5168@gmail.com>
1 parent cac33b0 commit a690660

File tree

2 files changed

+177
-0
lines changed

2 files changed

+177
-0
lines changed

common/motion_utils/include/motion_utils/trajectory/trajectory.hpp

+28
Original file line numberDiff line numberDiff line change
@@ -1115,6 +1115,34 @@ double calcSignedArcLength(
11151115
return signed_length_on_traj - signed_length_src_offset + signed_length_dst_offset;
11161116
}
11171117

1118+
template <class T>
1119+
double calcSignedArcLength(
1120+
const T & points, const geometry_msgs::msg::Point & src_point, const size_t src_seg_idx,
1121+
const size_t dst_idx)
1122+
{
1123+
validateNonEmpty(points);
1124+
1125+
const double signed_length_on_traj = calcSignedArcLength(points, src_seg_idx, dst_idx);
1126+
const double signed_length_src_offset =
1127+
calcLongitudinalOffsetToSegment(points, src_seg_idx, src_point);
1128+
1129+
return signed_length_on_traj - signed_length_src_offset;
1130+
}
1131+
1132+
template <class T>
1133+
double calcSignedArcLength(
1134+
const T & points, const size_t src_idx, const geometry_msgs::msg::Point & dst_point,
1135+
const size_t dst_seg_idx)
1136+
{
1137+
validateNonEmpty(points);
1138+
1139+
const double signed_length_on_traj = calcSignedArcLength(points, src_idx, dst_seg_idx);
1140+
const double signed_length_dst_offset =
1141+
calcLongitudinalOffsetToSegment(points, dst_seg_idx, dst_point);
1142+
1143+
return signed_length_on_traj + signed_length_dst_offset;
1144+
}
1145+
11181146
template <class T>
11191147
size_t findFirstNearestIndexWithSoftConstraints(
11201148
const T & points, const geometry_msgs::msg::Pose & pose,

common/motion_utils/test/src/trajectory/test_trajectory.cpp

+149
Original file line numberDiff line numberDiff line change
@@ -4185,3 +4185,152 @@ TEST(trajectory, findFirstNearestIndexWithSoftConstraints)
41854185
}
41864186
}
41874187
}
4188+
4189+
TEST(trajectory, calcSignedArcLengthFromPointAndSegmentIndexToPointAndSegmentIndex)
4190+
{
4191+
using motion_utils::calcSignedArcLength;
4192+
4193+
const auto traj = generateTestTrajectory<Trajectory>(10, 1.0);
4194+
4195+
// Empty
4196+
EXPECT_DOUBLE_EQ(calcSignedArcLength(Trajectory{}.points, {}, {}), 0.0);
4197+
4198+
// Same point
4199+
{
4200+
const auto p = createPoint(3.0, 0.0, 0.0);
4201+
EXPECT_NEAR(calcSignedArcLength(traj.points, p, 2, p, 2), 0, epsilon);
4202+
EXPECT_NEAR(calcSignedArcLength(traj.points, p, 3, p, 3), 0, epsilon);
4203+
}
4204+
4205+
// Forward
4206+
{
4207+
const auto p1 = createPoint(0.0, 0.0, 0.0);
4208+
const auto p2 = createPoint(3.0, 1.0, 0.0);
4209+
EXPECT_NEAR(calcSignedArcLength(traj.points, p1, 0, p2, 2), 3, epsilon);
4210+
EXPECT_NEAR(calcSignedArcLength(traj.points, p1, 0, p2, 3), 3, epsilon);
4211+
}
4212+
4213+
// Backward
4214+
{
4215+
const auto p1 = createPoint(9.0, 0.0, 0.0);
4216+
const auto p2 = createPoint(8.0, 0.0, 0.0);
4217+
EXPECT_NEAR(calcSignedArcLength(traj.points, p1, 8, p2, 7), -1, epsilon);
4218+
EXPECT_NEAR(calcSignedArcLength(traj.points, p1, 8, p2, 8), -1, epsilon);
4219+
}
4220+
4221+
// Point before start point
4222+
{
4223+
const auto p1 = createPoint(-3.9, 3.0, 0.0);
4224+
const auto p2 = createPoint(6.0, -10.0, 0.0);
4225+
EXPECT_NEAR(calcSignedArcLength(traj.points, p1, 0, p2, 5), 9.9, epsilon);
4226+
EXPECT_NEAR(calcSignedArcLength(traj.points, p1, 0, p2, 6), 9.9, epsilon);
4227+
}
4228+
4229+
// Point after end point
4230+
{
4231+
const auto p1 = createPoint(7.0, -5.0, 0.0);
4232+
const auto p2 = createPoint(13.3, -10.0, 0.0);
4233+
EXPECT_NEAR(calcSignedArcLength(traj.points, p1, 6, p2, 8), 6.3, epsilon);
4234+
EXPECT_NEAR(calcSignedArcLength(traj.points, p1, 7, p2, 8), 6.3, epsilon);
4235+
}
4236+
4237+
// Point before start point and after end point
4238+
{
4239+
const auto p1 = createPoint(-4.3, 10.0, 0.0);
4240+
const auto p2 = createPoint(13.8, -1.0, 0.0);
4241+
EXPECT_NEAR(calcSignedArcLength(traj.points, p1, 0, p2, 8), 18.1, epsilon);
4242+
}
4243+
4244+
// Random cases
4245+
{
4246+
const auto p1 = createPoint(1.0, 3.0, 0.0);
4247+
const auto p2 = createPoint(9.0, -1.0, 0.0);
4248+
EXPECT_NEAR(calcSignedArcLength(traj.points, p1, 0, p2, 8), 8, epsilon);
4249+
EXPECT_NEAR(calcSignedArcLength(traj.points, p1, 1, p2, 8), 8, epsilon);
4250+
}
4251+
{
4252+
const auto p1 = createPoint(4.3, 7.0, 0.0);
4253+
const auto p2 = createPoint(2.0, 3.0, 0.0);
4254+
EXPECT_NEAR(calcSignedArcLength(traj.points, p1, 4, p2, 2), -2.3, epsilon);
4255+
EXPECT_NEAR(calcSignedArcLength(traj.points, p1, 4, p2, 1), -2.3, epsilon);
4256+
}
4257+
}
4258+
4259+
TEST(trajectory, calcSignedArcLengthFromPointAndSegmentIndexToPointIndex)
4260+
{
4261+
using motion_utils::calcSignedArcLength;
4262+
4263+
const auto traj = generateTestTrajectory<Trajectory>(10, 1.0);
4264+
4265+
// Empty
4266+
EXPECT_DOUBLE_EQ(calcSignedArcLength(Trajectory{}.points, {}, {}), 0.0);
4267+
4268+
// Same point
4269+
{
4270+
const auto p = createPoint(3.0, 0.0, 0.0);
4271+
EXPECT_NEAR(calcSignedArcLength(traj.points, p, 2, 3), 0, epsilon);
4272+
EXPECT_NEAR(calcSignedArcLength(traj.points, 3, p, 3), 0, epsilon);
4273+
}
4274+
4275+
// Forward
4276+
{
4277+
const auto p1 = createPoint(0.0, 0.0, 0.0);
4278+
const auto p2 = createPoint(3.0, 1.0, 0.0);
4279+
EXPECT_NEAR(calcSignedArcLength(traj.points, p1, 0, 3), 3, epsilon);
4280+
EXPECT_NEAR(calcSignedArcLength(traj.points, 0, p2, 2), 3, epsilon);
4281+
EXPECT_NEAR(calcSignedArcLength(traj.points, 0, p2, 3), 3, epsilon);
4282+
}
4283+
4284+
// Backward
4285+
{
4286+
const auto p1 = createPoint(9.0, 0.0, 0.0);
4287+
const auto p2 = createPoint(8.0, 0.0, 0.0);
4288+
EXPECT_NEAR(calcSignedArcLength(traj.points, p1, 8, 8), -1, epsilon);
4289+
EXPECT_NEAR(calcSignedArcLength(traj.points, 8, p2, 7), 0, epsilon);
4290+
EXPECT_NEAR(calcSignedArcLength(traj.points, 8, p2, 8), 0, epsilon);
4291+
}
4292+
4293+
// Point before start point
4294+
{
4295+
const auto p1 = createPoint(-3.9, 3.0, 0.0);
4296+
EXPECT_NEAR(calcSignedArcLength(traj.points, p1, 0, 6), 9.9, epsilon);
4297+
}
4298+
4299+
// Point after end point
4300+
{
4301+
const auto p2 = createPoint(13.3, -10.0, 0.0);
4302+
EXPECT_NEAR(calcSignedArcLength(traj.points, 7, p2, 8), 6.3, epsilon);
4303+
}
4304+
4305+
// Start point
4306+
{
4307+
const auto p1 = createPoint(0.0, 3.0, 0.0);
4308+
const auto p2 = createPoint(5.3, -10.0, 0.0);
4309+
EXPECT_NEAR(calcSignedArcLength(traj.points, p1, 0, 5), 5, epsilon);
4310+
EXPECT_NEAR(calcSignedArcLength(traj.points, 0, p2, 5), 5.3, epsilon);
4311+
}
4312+
4313+
// Point after end point
4314+
{
4315+
const auto p1 = createPoint(7.3, -5.0, 0.0);
4316+
const auto p2 = createPoint(9.0, -10.0, 0.0);
4317+
EXPECT_NEAR(calcSignedArcLength(traj.points, p1, 7, 9), 1.7, epsilon);
4318+
EXPECT_NEAR(calcSignedArcLength(traj.points, 7, p2, 8), 2.0, epsilon);
4319+
}
4320+
4321+
// Random cases
4322+
{
4323+
const auto p1 = createPoint(1.0, 3.0, 0.0);
4324+
const auto p2 = createPoint(9.0, -1.0, 0.0);
4325+
EXPECT_NEAR(calcSignedArcLength(traj.points, p1, 0, 9), 8, epsilon);
4326+
EXPECT_NEAR(calcSignedArcLength(traj.points, p1, 1, 9), 8, epsilon);
4327+
EXPECT_NEAR(calcSignedArcLength(traj.points, 1, p2, 8), 8, epsilon);
4328+
}
4329+
{
4330+
const auto p1 = createPoint(4.3, 7.0, 0.0);
4331+
const auto p2 = createPoint(2.3, 3.0, 0.0);
4332+
EXPECT_NEAR(calcSignedArcLength(traj.points, p1, 4, 2), -2.3, epsilon);
4333+
EXPECT_NEAR(calcSignedArcLength(traj.points, 4, p2, 2), -1.7, epsilon);
4334+
EXPECT_NEAR(calcSignedArcLength(traj.points, 4, p2, 1), -1.7, epsilon);
4335+
}
4336+
}

0 commit comments

Comments
 (0)