Skip to content

Commit b1e7308

Browse files
soblinyhisaki
andauthored
feat(autoware_trajectory): use move semantics and return expected<T, E> for propagating failure reason (#254)
Signed-off-by: Mamoru Sobue <mamoru.sobue@tier4.jp> Co-authored-by: Yukinari Hisaki <42021302+yhisaki@users.noreply.github.com>
1 parent e2064d5 commit b1e7308

29 files changed

+280
-102
lines changed

common/autoware_trajectory/include/autoware/trajectory/detail/interpolated_array.hpp

+7-5
Original file line numberDiff line numberDiff line change
@@ -64,16 +64,18 @@ class InterpolatedArray
6464

6565
InterpolatedArray(InterpolatedArray && other) = default;
6666

67-
bool build(const std::vector<double> & bases, const std::vector<T> & values)
67+
interpolator::InterpolationResult build(
68+
const std::vector<double> & bases, const std::vector<T> & values)
6869
{
6970
bases_ = bases;
7071
values_ = values;
7172
return interpolator_->build(bases_, values_);
7273
}
7374

74-
bool build(std::vector<double> && bases, std::vector<T> && values)
75+
interpolator::InterpolationResult build(
76+
const std::vector<double> & bases, std::vector<T> && values)
7577
{
76-
bases_ = std::move(bases);
78+
bases_ = bases;
7779
values_ = std::move(values);
7880
return interpolator_->build(bases_, values_);
7981
}
@@ -160,7 +162,7 @@ class InterpolatedArray
160162
// Set the values in the specified range
161163
std::fill(values.begin() + start_index, values.begin() + end_index + 1, value);
162164

163-
bool success = parent_.interpolator_->build(bases, values);
165+
const auto success = parent_.interpolator_->build(bases, values);
164166
if (!success) {
165167
throw std::runtime_error(
166168
"Failed to build interpolator."); // This Exception should not be thrown.
@@ -194,7 +196,7 @@ class InterpolatedArray
194196
InterpolatedArray & operator=(const T & value)
195197
{
196198
std::fill(values_.begin(), values_.end(), value);
197-
bool success = interpolator_->build(bases_, values_);
199+
const auto success = interpolator_->build(bases_, values_);
198200
if (!success) {
199201
throw std::runtime_error(
200202
"Failed to build interpolator."); // This Exception should not be thrown.

common/autoware_trajectory/include/autoware/trajectory/interpolator/akima_spline.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ class AkimaSpline : public detail::InterpolatorMixin<AkimaSpline, double>
6262
* @param values The values to interpolate.
6363
*/
6464
[[nodiscard]] bool build_impl(
65-
std::vector<double> && bases, std::vector<double> && values) override;
65+
const std::vector<double> & bases, std::vector<double> && values) override;
6666

6767
/**
6868
* @brief Compute the interpolated value at the given point.

common/autoware_trajectory/include/autoware/trajectory/interpolator/cubic_spline.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ class CubicSpline : public detail::InterpolatorMixin<CubicSpline, double>
6565
* @return True if the interpolator was built successfully, false otherwise.
6666
*/
6767
[[nodiscard]] bool build_impl(
68-
std::vector<double> && bases, std::vector<double> && values) override;
68+
const std::vector<double> & bases, std::vector<double> && values) override;
6969

7070
/**
7171
* @brief Compute the interpolated value at the given point.

common/autoware_trajectory/include/autoware/trajectory/interpolator/detail/interpolator_common_interface.hpp

+17-7
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@
1515
#ifndef AUTOWARE__TRAJECTORY__INTERPOLATOR__DETAIL__INTERPOLATOR_COMMON_INTERFACE_HPP_
1616
#define AUTOWARE__TRAJECTORY__INTERPOLATOR__DETAIL__INTERPOLATOR_COMMON_INTERFACE_HPP_
1717

18-
#include <Eigen/Dense>
18+
#include "autoware/trajectory/interpolator/result.hpp"
19+
1920
#include <rclcpp/logging.hpp>
2021

2122
#include <utility>
@@ -76,7 +77,8 @@ class InterpolatorCommonInterface
7677
* @param bases The bases values.
7778
* @param values The values to interpolate.
7879
*/
79-
[[nodiscard]] virtual bool build_impl(std::vector<double> && bases, std::vector<T> && values) = 0;
80+
[[nodiscard]] virtual bool build_impl(
81+
const std::vector<double> & bases, std::vector<T> && values) = 0;
8082

8183
/**
8284
* @brief Validate the input to the compute method.
@@ -141,15 +143,23 @@ class InterpolatorCommonInterface
141143
std::conjunction_v<
142144
std::is_same<std::decay_t<BaseVectorT>, std::vector<double>>,
143145
std::is_same<std::decay_t<ValueVectorT>, std::vector<T>>>,
144-
bool>
146+
InterpolationResult>
145147
{
146148
if (bases.size() != values.size()) {
147-
return false;
149+
return tl::unexpected(InterpolationFailure{
150+
"base size " + std::to_string(bases.size()) + " and value size " +
151+
std::to_string(values.size()) + " are different"});
152+
}
153+
if (const auto minimum_required = minimum_required_points(); bases.size() < minimum_required) {
154+
return tl::unexpected(InterpolationFailure{
155+
"base size " + std::to_string(bases.size()) + " is less than minimum required " +
156+
std::to_string(minimum_required)});
148157
}
149-
if (bases.size() < minimum_required_points()) {
150-
return false;
158+
if (!build_impl(std::forward<BaseVectorT>(bases), std::forward<ValueVectorT>(values))) {
159+
return tl::unexpected(
160+
InterpolationFailure{"failed to interpolate from given base and values"});
151161
}
152-
return build_impl(std::forward<BaseVectorT>(bases), std::forward<ValueVectorT>(values));
162+
return InterpolationSuccess{};
153163
}
154164

155165
/**

common/autoware_trajectory/include/autoware/trajectory/interpolator/detail/interpolator_mixin.hpp

+5-3
Original file line numberDiff line numberDiff line change
@@ -81,12 +81,14 @@ struct InterpolatorMixin : public InterpolatorInterface<T>
8181
}
8282

8383
template <typename... Args>
84-
[[nodiscard]] std::optional<InterpolatorType> build(Args &&... args)
84+
[[nodiscard]] tl::expected<InterpolatorType, interpolator::InterpolationFailure> build(
85+
Args &&... args)
8586
{
8687
auto interpolator = InterpolatorType(std::forward<Args>(args)...);
87-
const bool success = interpolator.build(std::move(bases_), std::move(values_));
88+
const interpolator::InterpolationResult success =
89+
interpolator.build(std::move(bases_), std::move(values_));
8890
if (!success) {
89-
return std::nullopt;
91+
return tl::unexpected(success.error());
9092
}
9193
return interpolator;
9294
}

common/autoware_trajectory/include/autoware/trajectory/interpolator/detail/nearest_neighbor_common_impl.hpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,10 @@ class NearestNeighborCommonImpl : public detail::InterpolatorMixin<NearestNeighb
7676
* @param values The values to interpolate.
7777
* @return True if the interpolator was built successfully, false otherwise.
7878
*/
79-
[[nodiscard]] bool build_impl(std::vector<double> && bases, std::vector<T> && values) override
79+
[[nodiscard]] bool build_impl(
80+
const std::vector<double> & bases, std::vector<T> && values) override
8081
{
81-
this->bases_ = std::move(bases);
82+
this->bases_ = bases;
8283
this->values_ = std::move(values);
8384
return true;
8485
}

common/autoware_trajectory/include/autoware/trajectory/interpolator/detail/stairstep_common_impl.hpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,10 @@ class StairstepCommonImpl : public detail::InterpolatorMixin<Stairstep<T>, T>
7373
* @param bases The bases values.
7474
* @param values The values to interpolate.
7575
*/
76-
[[nodiscard]] bool build_impl(std::vector<double> && bases, std::vector<T> && values) override
76+
[[nodiscard]] bool build_impl(
77+
const std::vector<double> & bases, std::vector<T> && values) override
7778
{
78-
this->bases_ = std::move(bases);
79+
this->bases_ = bases;
7980
this->values_ = std::move(values);
8081
return true;
8182
}

common/autoware_trajectory/include/autoware/trajectory/interpolator/linear.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ class Linear : public detail::InterpolatorMixin<Linear, double>
5252
* @return True if the interpolator was built successfully, false otherwise.
5353
*/
5454
[[nodiscard]] bool build_impl(
55-
std::vector<double> && bases, std::vector<double> && values) override;
55+
const std::vector<double> & bases, std::vector<double> && values) override;
5656

5757
/**
5858
* @brief Compute the interpolated value at the given point.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Copyright 2025 TIER IV, Inc.
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 AUTOWARE__TRAJECTORY__INTERPOLATOR__RESULT_HPP_
16+
#define AUTOWARE__TRAJECTORY__INTERPOLATOR__RESULT_HPP_
17+
18+
#include <tl_expected/expected.hpp>
19+
20+
#include <string>
21+
22+
namespace autoware::trajectory::interpolator
23+
{
24+
struct InterpolationSuccess
25+
{
26+
};
27+
28+
struct InterpolationFailure
29+
{
30+
const std::string what;
31+
};
32+
33+
InterpolationFailure operator+(
34+
const InterpolationFailure & primary, const InterpolationFailure & nested);
35+
36+
using InterpolationResult = tl::expected<InterpolationSuccess, InterpolationFailure>;
37+
38+
} // namespace autoware::trajectory::interpolator
39+
#endif // AUTOWARE__TRAJECTORY__INTERPOLATOR__RESULT_HPP_

common/autoware_trajectory/include/autoware/trajectory/interpolator/spherical_linear.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ class SphericalLinear
5454
* @return True if the interpolator was built successfully, false otherwise.
5555
*/
5656
[[nodiscard]] bool build_impl(
57-
std::vector<double> && bases,
57+
const std::vector<double> & bases,
5858
std::vector<geometry_msgs::msg::Quaternion> && quaternions) override;
5959

6060
/**

common/autoware_trajectory/include/autoware/trajectory/path_point.hpp

+8-5
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#define AUTOWARE__TRAJECTORY__PATH_POINT_HPP_
1717

1818
#include "autoware/trajectory/detail/interpolated_array.hpp"
19+
#include "autoware/trajectory/interpolator/result.hpp"
1920
#include "autoware/trajectory/pose.hpp"
2021

2122
#include <autoware_planning_msgs/msg/path_point.hpp>
@@ -76,7 +77,7 @@ class Trajectory<autoware_planning_msgs::msg::PathPoint>
7677
* @param points Vector of points
7778
* @return True if the build is successful
7879
*/
79-
bool build(const std::vector<PointType> & points);
80+
interpolator::InterpolationResult build(const std::vector<PointType> & points);
8081

8182
/**
8283
* @brief Compute the point on the trajectory at a given s value
@@ -150,14 +151,16 @@ class Trajectory<autoware_planning_msgs::msg::PathPoint>
150151
return *this;
151152
}
152153

153-
std::optional<Trajectory> build(const std::vector<PointType> & points)
154+
tl::expected<Trajectory, interpolator::InterpolationFailure> build(
155+
const std::vector<PointType> & points)
154156
{
155-
if (trajectory_->build(points)) {
156-
auto result = std::make_optional<Trajectory>(std::move(*trajectory_));
157+
auto trajectory_result = trajectory_->build(points);
158+
if (trajectory_result) {
159+
auto result = Trajectory(std::move(*trajectory_));
157160
trajectory_.reset();
158161
return result;
159162
}
160-
return std::nullopt;
163+
return tl::unexpected(trajectory_result.error());
161164
}
162165
};
163166
};

common/autoware_trajectory/include/autoware/trajectory/path_point_with_lane_id.hpp

+7-5
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ class Trajectory<autoware_internal_planning_msgs::msg::PathPointWithLaneId>
5252
* @param points Vector of points
5353
* @return True if the build is successful
5454
*/
55-
bool build(const std::vector<PointType> & points);
55+
interpolator::InterpolationResult build(const std::vector<PointType> & points);
5656

5757
std::vector<double> get_internal_bases() const override;
5858

@@ -136,14 +136,16 @@ class Trajectory<autoware_internal_planning_msgs::msg::PathPointWithLaneId>
136136
return *this;
137137
}
138138

139-
std::optional<Trajectory> build(const std::vector<PointType> & points)
139+
tl::expected<Trajectory, interpolator::InterpolationFailure> build(
140+
const std::vector<PointType> & points)
140141
{
141-
if (trajectory_->build(points)) {
142-
auto result = std::make_optional<Trajectory>(std::move(*trajectory_));
142+
auto trajectory_result = trajectory_->build(points);
143+
if (trajectory_result) {
144+
auto result = Trajectory(std::move(*trajectory_));
143145
trajectory_.reset();
144146
return result;
145147
}
146-
return std::nullopt;
148+
return tl::unexpected(trajectory_result.error());
147149
}
148150
};
149151
};

common/autoware_trajectory/include/autoware/trajectory/point.hpp

+7-5
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ class Trajectory<geometry_msgs::msg::Point>
9090
* @param points Vector of points
9191
* @return True if the build is successful
9292
*/
93-
bool build(const std::vector<PointType> & points);
93+
interpolator::InterpolationResult build(const std::vector<PointType> & points);
9494

9595
/**
9696
* @brief Get the azimuth angle at a given s value
@@ -148,14 +148,16 @@ class Trajectory<geometry_msgs::msg::Point>
148148
return *this;
149149
}
150150

151-
std::optional<Trajectory> build(const std::vector<PointType> & points)
151+
tl::expected<Trajectory, interpolator::InterpolationFailure> build(
152+
const std::vector<PointType> & points)
152153
{
153-
if (trajectory_->build(points)) {
154-
auto result = std::make_optional<Trajectory>(std::move(*trajectory_));
154+
auto trajectory_result = trajectory_->build(points);
155+
if (trajectory_result) {
156+
auto result = Trajectory(std::move(*trajectory_));
155157
trajectory_.reset();
156158
return result;
157159
}
158-
return std::nullopt;
160+
return tl::unexpected(trajectory_result.error());
159161
}
160162
};
161163
};

common/autoware_trajectory/include/autoware/trajectory/pose.hpp

+7-5
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ class Trajectory<geometry_msgs::msg::Pose> : public Trajectory<geometry_msgs::ms
5252
// enable making trajectory from point trajectory
5353
explicit Trajectory(const Trajectory<geometry_msgs::msg::Point> & point_trajectory);
5454

55-
bool build(const std::vector<PointType> & points);
55+
interpolator::InterpolationResult build(const std::vector<PointType> & points);
5656

5757
/**
5858
* @brief Get the internal bases(arc lengths) of the trajectory
@@ -112,14 +112,16 @@ class Trajectory<geometry_msgs::msg::Pose> : public Trajectory<geometry_msgs::ms
112112
return *this;
113113
}
114114

115-
std::optional<Trajectory> build(const std::vector<PointType> & points)
115+
tl::expected<Trajectory, interpolator::InterpolationFailure> build(
116+
const std::vector<PointType> & points)
116117
{
117-
if (trajectory_->build(points)) {
118-
auto result = std::make_optional<Trajectory>(std::move(*trajectory_));
118+
auto trajectory_result = trajectory_->build(points);
119+
if (trajectory_result) {
120+
auto result = Trajectory(std::move(*trajectory_));
119121
trajectory_.reset();
120122
return result;
121123
}
122-
return std::nullopt;
124+
return tl::unexpected(trajectory_result.error());
123125
}
124126
};
125127
};

common/autoware_trajectory/include/autoware/trajectory/trajectory_point.hpp

+7-5
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ class Trajectory<autoware_planning_msgs::msg::TrajectoryPoint>
103103
* @param points Vector of points
104104
* @return True if the build is successful
105105
*/
106-
bool build(const std::vector<PointType> & points);
106+
interpolator::InterpolationResult build(const std::vector<PointType> & points);
107107

108108
/**
109109
* @brief Compute the point on the trajectory at a given s value
@@ -201,14 +201,16 @@ class Trajectory<autoware_planning_msgs::msg::TrajectoryPoint>
201201
return *this;
202202
}
203203

204-
std::optional<Trajectory> build(const std::vector<PointType> & points)
204+
tl::expected<Trajectory, interpolator::InterpolationFailure> build(
205+
const std::vector<PointType> & points)
205206
{
206-
if (trajectory_->build(points)) {
207-
auto result = std::make_optional<Trajectory>(std::move(*trajectory_));
207+
auto trajectory_result = trajectory_->build(points);
208+
if (trajectory_result) {
209+
auto result = Trajectory(std::move(*trajectory_));
208210
trajectory_.reset();
209211
return result;
210212
}
211-
return std::nullopt;
213+
return tl::unexpected(trajectory_result.error());
212214
}
213215
};
214216
};

common/autoware_trajectory/package.xml

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
<depend>lanelet2_core</depend>
2121
<depend>rclcpp</depend>
2222
<depend>tf2</depend>
23+
<depend>tl_expected</depend>
2324

2425
<test_depend>ament_cmake_ros</test_depend>
2526
<test_depend>ament_lint_auto</test_depend>

common/autoware_trajectory/src/interpolator/akima_spline.cpp

+3-4
Original file line numberDiff line numberDiff line change
@@ -69,12 +69,11 @@ bool AkimaSpline::build_impl(const std::vector<double> & bases, const std::vecto
6969
return true;
7070
}
7171

72-
bool AkimaSpline::build_impl(std::vector<double> && bases, std::vector<double> && values)
72+
bool AkimaSpline::build_impl(const std::vector<double> & bases, std::vector<double> && values)
7373
{
74-
this->bases_ = std::move(bases);
74+
this->bases_ = bases;
7575
compute_parameters(
76-
Eigen::Map<const Eigen::VectorXd>(
77-
this->bases_.data(), static_cast<Eigen::Index>(this->bases_.size())),
76+
Eigen::Map<const Eigen::VectorXd>(bases.data(), static_cast<Eigen::Index>(bases.size())),
7877
Eigen::Map<const Eigen::VectorXd>(values.data(), static_cast<Eigen::Index>(values.size())));
7978
return true;
8079
}

0 commit comments

Comments
 (0)