diff --git a/.github/workflows/github-release.yaml b/.github/workflows/github-release.yaml
index 23508e63bc43d..93533b54e1dd0 100644
--- a/.github/workflows/github-release.yaml
+++ b/.github/workflows/github-release.yaml
@@ -54,7 +54,7 @@ jobs:
- name: Select verb
id: select-verb
run: |
- has_previous_draft=$(gh release view --json isDraft -q ".isDraft" "${{ steps.set-tag-name.outputs.tag-name }}")
+ has_previous_draft=$(gh release view --json isDraft -q ".isDraft" "${{ steps.set-tag-name.outputs.tag-name }}") || true
verb=create
if [ "$has_previous_draft" = "true" ]; then
diff --git a/common/autoware_auto_common/CMakeLists.txt b/common/autoware_auto_common/CMakeLists.txt
index 4f7846c89eb72..b0957ad726856 100644
--- a/common/autoware_auto_common/CMakeLists.txt
+++ b/common/autoware_auto_common/CMakeLists.txt
@@ -9,7 +9,7 @@ include_directories(SYSTEM ${EIGEN3_INCLUDE_DIR})
if(BUILD_TESTING)
set(TEST_COMMON test_common_gtest)
- ament_add_gtest(${TEST_COMMON}
+ ament_add_ros_isolated_gtest(${TEST_COMMON}
test/gtest_main.cpp
test/test_bool_comparisons.cpp
test/test_byte_reader.cpp
diff --git a/common/autoware_auto_common/package.xml b/common/autoware_auto_common/package.xml
index dca22e9b29ea3..17d666e2273e6 100644
--- a/common/autoware_auto_common/package.xml
+++ b/common/autoware_auto_common/package.xml
@@ -14,7 +14,7 @@
builtin_interfaces
eigen
- ament_cmake_gtest
+ ament_cmake_ros
ament_lint_auto
autoware_lint_common
geometry_msgs
diff --git a/common/autoware_auto_geometry/CMakeLists.txt b/common/autoware_auto_geometry/CMakeLists.txt
index 0e964e3b064a2..454e0e7ef044f 100644
--- a/common/autoware_auto_geometry/CMakeLists.txt
+++ b/common/autoware_auto_geometry/CMakeLists.txt
@@ -23,7 +23,7 @@ if(BUILD_TESTING)
test/src/test_common_2d.cpp
test/src/test_intersection.cpp
)
- ament_add_gtest(${GEOMETRY_GTEST} ${GEOMETRY_SRC})
+ ament_add_ros_isolated_gtest(${GEOMETRY_GTEST} ${GEOMETRY_SRC})
target_compile_options(${GEOMETRY_GTEST} PRIVATE -Wno-conversion -Wno-sign-conversion)
target_include_directories(${GEOMETRY_GTEST} PRIVATE "test/include" "include")
ament_target_dependencies(${GEOMETRY_GTEST}
diff --git a/common/autoware_auto_geometry/package.xml b/common/autoware_auto_geometry/package.xml
index 976cf59013370..e19ac4897aab0 100644
--- a/common/autoware_auto_geometry/package.xml
+++ b/common/autoware_auto_geometry/package.xml
@@ -18,7 +18,7 @@
autoware_auto_vehicle_msgs
geometry_msgs
- ament_cmake_gtest
+ ament_cmake_ros
ament_lint_auto
autoware_lint_common
osrf_testing_tools_cpp
diff --git a/common/autoware_auto_tf2/CMakeLists.txt b/common/autoware_auto_tf2/CMakeLists.txt
index f4b3223391a7b..a8ae9ec2d962e 100755
--- a/common/autoware_auto_tf2/CMakeLists.txt
+++ b/common/autoware_auto_tf2/CMakeLists.txt
@@ -5,7 +5,7 @@ find_package(autoware_cmake REQUIRED)
autoware_package()
if(BUILD_TESTING)
- ament_add_gtest(test_tf2_autoware_auto_msgs test/test_tf2_autoware_auto_msgs.cpp)
+ ament_add_ros_isolated_gtest(test_tf2_autoware_auto_msgs test/test_tf2_autoware_auto_msgs.cpp)
target_include_directories(test_tf2_autoware_auto_msgs PRIVATE "include")
ament_target_dependencies(test_tf2_autoware_auto_msgs
"autoware_auto_common"
diff --git a/common/autoware_auto_tf2/package.xml b/common/autoware_auto_tf2/package.xml
index d6fbd4f4ce3d8..c80ce45a217ac 100644
--- a/common/autoware_auto_tf2/package.xml
+++ b/common/autoware_auto_tf2/package.xml
@@ -20,7 +20,7 @@
tf2_geometry_msgs
tf2_ros
- ament_cmake_gtest
+ ament_cmake_ros
ament_lint_auto
autoware_lint_common
diff --git a/common/autoware_point_types/CMakeLists.txt b/common/autoware_point_types/CMakeLists.txt
index e46081c5ea96f..c149f79dab71f 100644
--- a/common/autoware_point_types/CMakeLists.txt
+++ b/common/autoware_point_types/CMakeLists.txt
@@ -11,7 +11,7 @@ include_directories(
)
if(BUILD_TESTING)
- ament_add_gtest(test_autoware_point_types
+ ament_add_ros_isolated_gtest(test_autoware_point_types
test/test_point_types.cpp
)
target_include_directories(test_autoware_point_types
diff --git a/common/autoware_point_types/package.xml b/common/autoware_point_types/package.xml
index b7449dbbd13d5..8829bd7538d9b 100644
--- a/common/autoware_point_types/package.xml
+++ b/common/autoware_point_types/package.xml
@@ -23,7 +23,7 @@
pcl_ros
point_cloud_msg_wrapper
- ament_cmake_gtest
+ ament_cmake_ros
ament_lint_auto
autoware_lint_common
point_cloud_msg_wrapper
diff --git a/common/autoware_testing/autoware_testing/smoke_test.py b/common/autoware_testing/autoware_testing/smoke_test.py
index 2753861269124..8c361474034ad 100644
--- a/common/autoware_testing/autoware_testing/smoke_test.py
+++ b/common/autoware_testing/autoware_testing/smoke_test.py
@@ -16,6 +16,7 @@
import os
import shlex
+import time
import unittest
from ament_index_python import get_package_share_directory
@@ -26,21 +27,24 @@
from launch_ros.actions import Node
import launch_testing
import pytest
+import rclpy
def resolve_node(context, *args, **kwargs):
+ parameters = [
+ os.path.join(
+ get_package_share_directory(LaunchConfiguration("arg_package").perform(context)),
+ "param",
+ file_name,
+ )
+ for file_name in shlex.split(LaunchConfiguration("arg_param_filenames").perform(context))
+ ]
smoke_test_node = Node(
package=LaunchConfiguration("arg_package"),
executable=LaunchConfiguration("arg_package_exe"),
namespace="test",
- parameters=[
- os.path.join(
- get_package_share_directory(LaunchConfiguration("arg_package").perform(context)),
- "param",
- LaunchConfiguration("arg_param_filename").perform(context),
- )
- ],
+ parameters=parameters,
arguments=shlex.split(LaunchConfiguration("arg_executable_arguments").perform(context)),
)
return [smoke_test_node]
@@ -55,8 +59,8 @@ def generate_test_description():
arg_package_exe = DeclareLaunchArgument(
"arg_package_exe", default_value=["default"], description="Tested executable"
)
- arg_param_filename = DeclareLaunchArgument(
- "arg_param_filename", default_value=["test.param.yaml"], description="Test param file"
+ arg_param_filenames = DeclareLaunchArgument(
+ "arg_param_filenames", default_value=["test.param.yaml"], description="Test param file"
)
arg_executable_arguments = DeclareLaunchArgument(
"arg_executable_arguments", default_value=[""], description="Tested executable arguments"
@@ -66,7 +70,7 @@ def generate_test_description():
[
arg_package,
arg_package_exe,
- arg_param_filename,
+ arg_param_filenames,
arg_executable_arguments,
OpaqueFunction(function=resolve_node),
launch_testing.actions.ReadyToTest(),
@@ -74,8 +78,19 @@ def generate_test_description():
)
+class DummyTest(unittest.TestCase):
+ def test_wait_for_node_ready(self):
+ """Waiting for the node is ready."""
+ rclpy.init()
+ test_node = rclpy.create_node("test_node")
+ while len(test_node.get_node_names()) == 0:
+ time.sleep(0.1)
+ print("waiting for Node to be ready")
+ rclpy.shutdown()
+
+
@launch_testing.post_shutdown_test()
class TestProcessOutput(unittest.TestCase):
def test_exit_code(self, proc_output, proc_info):
- # Check that process exits with code -15 code: termination request, sent to the program
- launch_testing.asserts.assertExitCodes(proc_info, [-15])
+ # Check that process exits with code 0
+ launch_testing.asserts.assertExitCodes(proc_info)
diff --git a/common/autoware_testing/cmake/add_smoke_test.cmake b/common/autoware_testing/cmake/add_smoke_test.cmake
index 2998db4960de4..ee2cb0f06e789 100644
--- a/common/autoware_testing/cmake/add_smoke_test.cmake
+++ b/common/autoware_testing/cmake/add_smoke_test.cmake
@@ -19,18 +19,18 @@
# :type package_name: string
# :param package_exec: package executable to run during smoke test
# :type executable_name: string
-# :param PARAM_FILENAME: yaml filename containing test parameters
-# :type PARAM_FILENAME: string
+# :param PARAM_FILENAMES: yaml filenames containing test parameters
+# :type PARAM_FILENAMES: string
# :param EXECUTABLE_ARGUMENTS: arguments passed to tested executable
# :type EXECUTABLE_ARGUMENTS: string
function(add_smoke_test package_name executable_name)
- cmake_parse_arguments(PARSE_ARGV 2 smoke_test "" "PARAM_FILENAME;EXECUTABLE_ARGUMENTS" "")
+ cmake_parse_arguments(PARSE_ARGV 2 smoke_test "" "PARAM_FILENAMES;EXECUTABLE_ARGUMENTS" "")
set(ARGUMENTS "arg_package:=${package_name}" "arg_package_exe:=${executable_name}")
- if(smoke_test_PARAM_FILENAME)
- list(APPEND ARGUMENTS "arg_param_filename:=${smoke_test_PARAM_FILENAME}")
+ if(smoke_test_PARAM_FILENAMES)
+ list(APPEND ARGUMENTS "arg_param_filenames:=${smoke_test_PARAM_FILENAMES}")
endif()
if(smoke_test_EXECUTABLE_ARGUMENTS)
diff --git a/common/fake_test_node/CMakeLists.txt b/common/fake_test_node/CMakeLists.txt
index cc80077163ab1..8ad71df2777f3 100644
--- a/common/fake_test_node/CMakeLists.txt
+++ b/common/fake_test_node/CMakeLists.txt
@@ -7,7 +7,7 @@ autoware_package()
ament_auto_add_library(fake_test_node SHARED src/fake_test_node.cpp)
if(BUILD_TESTING)
- ament_add_gtest(test_fake_test_node
+ ament_add_ros_isolated_gtest(test_fake_test_node
test/test_fake_test_node.cpp
)
add_dependencies(test_fake_test_node fake_test_node)
diff --git a/common/fake_test_node/package.xml b/common/fake_test_node/package.xml
index 6d337906ff3b7..8e919d719fc6c 100644
--- a/common/fake_test_node/package.xml
+++ b/common/fake_test_node/package.xml
@@ -11,7 +11,7 @@
autoware_cmake
- ament_cmake_gtest
+ ament_cmake_ros
autoware_auto_common
rclcpp
rclcpp_components
diff --git a/common/had_map_utils/package.xml b/common/had_map_utils/package.xml
index 2baa56aa12c73..aa7f7a9e78840 100644
--- a/common/had_map_utils/package.xml
+++ b/common/had_map_utils/package.xml
@@ -23,7 +23,7 @@
lanelet2_io
visualization_msgs
- ament_cmake_gtest
+ ament_cmake_ros
ament_lint_auto
autoware_lint_common
diff --git a/common/interpolation/CMakeLists.txt b/common/interpolation/CMakeLists.txt
index bca79e0f23d98..7afed6fe57c41 100644
--- a/common/interpolation/CMakeLists.txt
+++ b/common/interpolation/CMakeLists.txt
@@ -13,7 +13,7 @@ ament_auto_add_library(interpolation SHARED
if(BUILD_TESTING)
file(GLOB_RECURSE test_files test/**/*.cpp)
- ament_add_gtest(test_interpolation ${test_files})
+ ament_add_ros_isolated_gtest(test_interpolation ${test_files})
target_link_libraries(test_interpolation
interpolation
diff --git a/common/interpolation/package.xml b/common/interpolation/package.xml
index 213616b007a19..665e26bab9a0a 100644
--- a/common/interpolation/package.xml
+++ b/common/interpolation/package.xml
@@ -14,7 +14,7 @@
tier4_autoware_utils
- ament_cmake_gtest
+ ament_cmake_ros
ament_lint_auto
autoware_lint_common
diff --git a/common/motion_testing/CMakeLists.txt b/common/motion_testing/CMakeLists.txt
index 4e7006978ab22..f8428c0df709c 100644
--- a/common/motion_testing/CMakeLists.txt
+++ b/common/motion_testing/CMakeLists.txt
@@ -7,7 +7,7 @@ autoware_package()
ament_auto_add_library(${PROJECT_NAME} SHARED src/motion_testing/motion_testing.cpp)
if(BUILD_TESTING)
- ament_add_gtest(motion_testing_unit_tests
+ ament_add_ros_isolated_gtest(motion_testing_unit_tests
test/gtest_main.cpp
test/constant_trajectory.cpp
test/trajectory_checks.cpp)
diff --git a/common/motion_testing/package.xml b/common/motion_testing/package.xml
index 33e7b4798d0e7..f292a7e5bb54b 100644
--- a/common/motion_testing/package.xml
+++ b/common/motion_testing/package.xml
@@ -19,7 +19,7 @@
autoware_auto_planning_msgs
autoware_auto_vehicle_msgs
- ament_cmake_gtest
+ ament_cmake_ros
ament_lint_auto
autoware_lint_common
diff --git a/common/osqp_interface/CMakeLists.txt b/common/osqp_interface/CMakeLists.txt
index 4180461cc261c..996f8b6153cf0 100644
--- a/common/osqp_interface/CMakeLists.txt
+++ b/common/osqp_interface/CMakeLists.txt
@@ -49,7 +49,7 @@ if(BUILD_TESTING)
test/test_csc_matrix_conv.cpp
)
set(TEST_OSQP_INTERFACE_EXE test_osqp_interface)
- ament_add_gtest(${TEST_OSQP_INTERFACE_EXE} ${TEST_SOURCES})
+ ament_add_ros_isolated_gtest(${TEST_OSQP_INTERFACE_EXE} ${TEST_SOURCES})
target_link_libraries(${TEST_OSQP_INTERFACE_EXE} ${PROJECT_NAME})
endif()
diff --git a/common/osqp_interface/package.xml b/common/osqp_interface/package.xml
index f89810ddda953..5260a3f2b07c0 100644
--- a/common/osqp_interface/package.xml
+++ b/common/osqp_interface/package.xml
@@ -17,7 +17,7 @@
rclcpp
rclcpp_components
- ament_cmake_gtest
+ ament_cmake_ros
ament_lint_auto
autoware_lint_common
eigen
diff --git a/common/signal_processing/CMakeLists.txt b/common/signal_processing/CMakeLists.txt
index e93023e703eb7..93cb7aa225a08 100644
--- a/common/signal_processing/CMakeLists.txt
+++ b/common/signal_processing/CMakeLists.txt
@@ -9,7 +9,7 @@ ament_auto_add_library(lowpass_filter_1d SHARED
)
if(BUILD_TESTING)
- ament_add_gtest(test_signal_processing
+ ament_add_ros_isolated_gtest(test_signal_processing
test/src/lowpass_filter_1d_test.cpp
)
target_link_libraries(test_signal_processing
diff --git a/common/signal_processing/package.xml b/common/signal_processing/package.xml
index 563715af77248..867f2d05da60e 100644
--- a/common/signal_processing/package.xml
+++ b/common/signal_processing/package.xml
@@ -12,7 +12,7 @@
ament_cmake_auto
- ament_cmake_gtest
+ ament_cmake_ros
ament_lint_auto
autoware_lint_common
diff --git a/common/tier4_api_utils/CMakeLists.txt b/common/tier4_api_utils/CMakeLists.txt
index e65e538fe1df4..4eda0296e520e 100644
--- a/common/tier4_api_utils/CMakeLists.txt
+++ b/common/tier4_api_utils/CMakeLists.txt
@@ -6,7 +6,7 @@ autoware_package()
if(BUILD_TESTING)
include_directories(include)
- ament_add_gtest(${PROJECT_NAME}_test test/test.cpp)
+ ament_add_ros_isolated_gtest(${PROJECT_NAME}_test test/test.cpp)
ament_target_dependencies(${PROJECT_NAME}_test rclcpp tier4_external_api_msgs)
endif()
diff --git a/common/tier4_api_utils/package.xml b/common/tier4_api_utils/package.xml
index 99a03ab92b0ec..a8378b92352ec 100644
--- a/common/tier4_api_utils/package.xml
+++ b/common/tier4_api_utils/package.xml
@@ -14,7 +14,7 @@
rclcpp
tier4_external_api_msgs
- ament_cmake_gtest
+ ament_cmake_ros
ament_lint_auto
autoware_lint_common
rclcpp
diff --git a/common/tier4_autoware_utils/CMakeLists.txt b/common/tier4_autoware_utils/CMakeLists.txt
index eeca0a2d83630..7ba9c2020a36f 100644
--- a/common/tier4_autoware_utils/CMakeLists.txt
+++ b/common/tier4_autoware_utils/CMakeLists.txt
@@ -12,11 +12,11 @@ ament_auto_add_library(tier4_autoware_utils SHARED
)
if(BUILD_TESTING)
- find_package(ament_cmake_gtest REQUIRED)
+ find_package(ament_cmake_ros REQUIRED)
file(GLOB_RECURSE test_files test/**/*.cpp)
- ament_add_gtest(test_tier4_autoware_utils ${test_files})
+ ament_add_ros_isolated_gtest(test_tier4_autoware_utils ${test_files})
target_link_libraries(test_tier4_autoware_utils
tier4_autoware_utils
diff --git a/common/tier4_autoware_utils/package.xml b/common/tier4_autoware_utils/package.xml
index f1bd523a8eda1..63fd56ae09f86 100644
--- a/common/tier4_autoware_utils/package.xml
+++ b/common/tier4_autoware_utils/package.xml
@@ -23,7 +23,7 @@
tier4_debug_msgs
visualization_msgs
- ament_cmake_gtest
+ ament_cmake_ros
ament_lint_auto
autoware_lint_common
diff --git a/common/tier4_state_rviz_plugin/package.xml b/common/tier4_state_rviz_plugin/package.xml
index 2afbe9c315f75..74f7a7418815e 100644
--- a/common/tier4_state_rviz_plugin/package.xml
+++ b/common/tier4_state_rviz_plugin/package.xml
@@ -21,6 +21,7 @@
rviz_common
tier4_control_msgs
tier4_external_api_msgs
+ tier4_planning_msgs
ament_lint_auto
autoware_lint_common
diff --git a/common/tier4_state_rviz_plugin/src/autoware_state_panel.cpp b/common/tier4_state_rviz_plugin/src/autoware_state_panel.cpp
index 78681106b3d61..825e06dac1cd9 100644
--- a/common/tier4_state_rviz_plugin/src/autoware_state_panel.cpp
+++ b/common/tier4_state_rviz_plugin/src/autoware_state_panel.cpp
@@ -80,13 +80,26 @@ AutowareStatePanel::AutowareStatePanel(QWidget * parent) : rviz_common::Panel(pa
engage_button_ptr_ = new QPushButton("Engage");
connect(engage_button_ptr_, SIGNAL(clicked()), SLOT(onClickAutowareEngage()));
+ velocity_limit_button_ptr_ = new QPushButton("Send Velocity Limit");
+ pub_velocity_limit_input_ = new QSpinBox();
+ pub_velocity_limit_input_->setRange(-100.0, 100.0);
+ pub_velocity_limit_input_->setValue(0.0);
+ pub_velocity_limit_input_->setSingleStep(5.0);
+ connect(velocity_limit_button_ptr_, SIGNAL(clicked()), this, SLOT(onClickVelocityLimit()));
+
auto * v_layout = new QVBoxLayout;
+ auto * velocity_limit_layout = new QHBoxLayout();
v_layout->addLayout(gate_layout);
v_layout->addLayout(selector_layout);
v_layout->addLayout(state_layout);
v_layout->addLayout(gear_layout);
v_layout->addLayout(engage_status_layout);
v_layout->addWidget(engage_button_ptr_);
+ v_layout->addLayout(engage_status_layout);
+ velocity_limit_layout->addWidget(velocity_limit_button_ptr_);
+ velocity_limit_layout->addWidget(pub_velocity_limit_input_);
+ velocity_limit_layout->addWidget(new QLabel(" [km/h]"));
+ v_layout->addLayout(velocity_limit_layout);
setLayout(v_layout);
}
@@ -114,6 +127,9 @@ void AutowareStatePanel::onInitialize()
client_engage_ = raw_node_->create_client(
"/api/autoware/set/engage", rmw_qos_profile_services_default);
+
+ pub_velocity_limit_ = raw_node_->create_publisher(
+ "/planning/scenario_planning/max_velocity_default", rclcpp::QoS(1));
}
void AutowareStatePanel::onGateMode(const tier4_control_msgs::msg::GateMode::ConstSharedPtr msg)
@@ -215,6 +231,13 @@ void AutowareStatePanel::onEngageStatus(
engage_status_label_ptr_->setText(QString::fromStdString(Bool2String(current_engage_)));
}
+void AutowareStatePanel::onClickVelocityLimit()
+{
+ auto velocity_limit = std::make_shared();
+ velocity_limit->max_velocity = pub_velocity_limit_input_->value() / 3.6;
+ pub_velocity_limit_->publish(*velocity_limit);
+}
+
void AutowareStatePanel::onClickAutowareEngage()
{
auto req = std::make_shared();
diff --git a/common/tier4_state_rviz_plugin/src/autoware_state_panel.hpp b/common/tier4_state_rviz_plugin/src/autoware_state_panel.hpp
index 45cd290e5f4a3..97c559bdfb3de 100644
--- a/common/tier4_state_rviz_plugin/src/autoware_state_panel.hpp
+++ b/common/tier4_state_rviz_plugin/src/autoware_state_panel.hpp
@@ -19,6 +19,7 @@
#include
#include
+#include
#include
#include
@@ -28,6 +29,7 @@
#include
#include
#include
+#include
namespace rviz_plugins
{
@@ -41,6 +43,7 @@ class AutowareStatePanel : public rviz_common::Panel
public Q_SLOTS:
void onClickAutowareEngage();
+ void onClickVelocityLimit();
protected:
void onGateMode(const tier4_control_msgs::msg::GateMode::ConstSharedPtr msg);
@@ -61,12 +64,16 @@ public Q_SLOTS:
rclcpp::Client::SharedPtr client_engage_;
+ rclcpp::Publisher::SharedPtr pub_velocity_limit_;
+
QLabel * gate_mode_label_ptr_;
QLabel * selector_mode_label_ptr_;
QLabel * autoware_state_label_ptr_;
QLabel * gear_label_ptr_;
QLabel * engage_status_label_ptr_;
QPushButton * engage_button_ptr_;
+ QPushButton * velocity_limit_button_ptr_;
+ QSpinBox * pub_velocity_limit_input_;
bool current_engage_;
};
diff --git a/common/time_utils/package.xml b/common/time_utils/package.xml
index 9b553289e09be..a248e72f125f3 100644
--- a/common/time_utils/package.xml
+++ b/common/time_utils/package.xml
@@ -12,7 +12,7 @@
autoware_cmake
builtin_interfaces
- ament_cmake_gtest
+ ament_cmake_ros
ament_lint_auto
autoware_lint_common
diff --git a/common/vehicle_constants_manager/CMakeLists.txt b/common/vehicle_constants_manager/CMakeLists.txt
index eb5f7b27663e3..1e84c5f781d39 100644
--- a/common/vehicle_constants_manager/CMakeLists.txt
+++ b/common/vehicle_constants_manager/CMakeLists.txt
@@ -18,7 +18,7 @@ ament_auto_add_library(${PROJECT_NAME} SHARED
# if(BUILD_TESTING)
# set(TEST_SOURCES test/test_vehicle_constants_manager.cpp)
# set(TEST_VEHICLE_CONSTANTS_MANAGER_EXE test_vehicle_constants_manager)
-# ament_add_gtest(${TEST_VEHICLE_CONSTANTS_MANAGER_EXE} ${TEST_SOURCES})
+# ament_add_ros_isolated_gtest(${TEST_VEHICLE_CONSTANTS_MANAGER_EXE} ${TEST_SOURCES})
# target_link_libraries(${TEST_VEHICLE_CONSTANTS_MANAGER_EXE} ${PROJECT_NAME})
# endif()
diff --git a/common/vehicle_constants_manager/package.xml b/common/vehicle_constants_manager/package.xml
index eecb3e8f2108f..8041ae90a2cb7 100644
--- a/common/vehicle_constants_manager/package.xml
+++ b/common/vehicle_constants_manager/package.xml
@@ -15,7 +15,7 @@
rclcpp
rclcpp_components
- ament_cmake_gtest
+ ament_cmake_ros
ament_cmake
diff --git a/control/trajectory_follower/CMakeLists.txt b/control/trajectory_follower/CMakeLists.txt
index 5c29617296780..5d564ba33c62b 100644
--- a/control/trajectory_follower/CMakeLists.txt
+++ b/control/trajectory_follower/CMakeLists.txt
@@ -7,6 +7,7 @@ autoware_package()
# lateral_controller
set(LATERAL_CONTROLLER_LIB lateral_controller_lib)
set(LATERAL_CONTROLLER_LIB_SRC
+ src/mpc_lateral_controller.cpp
src/interpolate.cpp
src/lowpass_filter.cpp
src/mpc.cpp
@@ -21,6 +22,9 @@ set(LATERAL_CONTROLLER_LIB_SRC
)
set(LATERAL_CONTROLLER_LIB_HEADERS
+ include/trajectory_follower/lateral_controller_base.hpp
+ include/trajectory_follower/mpc_lateral_controller.hpp
+ include/trajectory_follower/sync_data.hpp
include/trajectory_follower/visibility_control.hpp
include/trajectory_follower/interpolate.hpp
include/trajectory_follower/lowpass_filter.hpp
@@ -45,12 +49,16 @@ target_compile_options(${LATERAL_CONTROLLER_LIB} PRIVATE -Wno-error=old-style-ca
# longitudinal_controller
set(LONGITUDINAL_CONTROLLER_LIB longitudinal_controller_lib)
set(LONGITUDINAL_CONTROLLER_LIB_SRC
+ src/pid_longitudinal_controller.cpp
src/pid.cpp
src/smooth_stop.cpp
src/longitudinal_controller_utils.cpp
)
set(LONGITUDINAL_CONTROLLER_LIB_HEADERS
+ include/trajectory_follower/longitudinal_controller_base.hpp
+ include/trajectory_follower/pid_longitudinal_controller.hpp
+ include/trajectory_follower/sync_data.hpp
include/trajectory_follower/debug_values.hpp
include/trajectory_follower/pid.hpp
include/trajectory_follower/smooth_stop.hpp
@@ -72,7 +80,7 @@ if(BUILD_TESTING)
test/test_lowpass_filter.cpp
)
set(TEST_LATERAL_CONTROLLER_EXE test_lateral_controller)
- ament_add_gtest(${TEST_LATERAL_CONTROLLER_EXE} ${TEST_LAT_SOURCES})
+ ament_add_ros_isolated_gtest(${TEST_LATERAL_CONTROLLER_EXE} ${TEST_LAT_SOURCES})
target_link_libraries(${TEST_LATERAL_CONTROLLER_EXE} ${LATERAL_CONTROLLER_LIB})
set(TEST_LON_SOURCES
@@ -82,7 +90,7 @@ if(BUILD_TESTING)
test/test_longitudinal_controller_utils.cpp
)
set(TEST_LONGITUDINAL_CONTROLLER_EXE test_longitudinal_controller)
- ament_add_gtest(${TEST_LONGITUDINAL_CONTROLLER_EXE} ${TEST_LON_SOURCES})
+ ament_add_ros_isolated_gtest(${TEST_LONGITUDINAL_CONTROLLER_EXE} ${TEST_LON_SOURCES})
target_link_libraries(${TEST_LONGITUDINAL_CONTROLLER_EXE} ${LONGITUDINAL_CONTROLLER_LIB})
endif()
diff --git a/control/trajectory_follower/include/trajectory_follower/lateral_controller_base.hpp b/control/trajectory_follower/include/trajectory_follower/lateral_controller_base.hpp
new file mode 100644
index 0000000000000..44c26c26a0820
--- /dev/null
+++ b/control/trajectory_follower/include/trajectory_follower/lateral_controller_base.hpp
@@ -0,0 +1,55 @@
+// Copyright 2022 The Autoware Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef TRAJECTORY_FOLLOWER__LATERAL_CONTROLLER_BASE_HPP_
+#define TRAJECTORY_FOLLOWER__LATERAL_CONTROLLER_BASE_HPP_
+
+#include "rclcpp/rclcpp.hpp"
+#include "trajectory_follower/sync_data.hpp"
+
+#include "autoware_auto_control_msgs/msg/ackermann_lateral_command.hpp"
+
+namespace autoware
+{
+namespace motion
+{
+namespace control
+{
+namespace trajectory_follower
+{
+struct LateralOutput
+{
+ autoware_auto_control_msgs::msg::AckermannLateralCommand control_cmd;
+ LateralSyncData sync_data;
+};
+
+class LateralControllerBase
+{
+public:
+ virtual LateralOutput run() = 0;
+ void sync(LongitudinalSyncData longitudinal_sync_data)
+ {
+ longitudinal_sync_data_ = longitudinal_sync_data;
+ };
+
+protected:
+ LongitudinalSyncData longitudinal_sync_data_;
+};
+
+} // namespace trajectory_follower
+} // namespace control
+} // namespace motion
+} // namespace autoware
+
+#endif // TRAJECTORY_FOLLOWER__LATERAL_CONTROLLER_BASE_HPP_
diff --git a/control/trajectory_follower/include/trajectory_follower/longitudinal_controller_base.hpp b/control/trajectory_follower/include/trajectory_follower/longitudinal_controller_base.hpp
new file mode 100644
index 0000000000000..cb50b1a6af031
--- /dev/null
+++ b/control/trajectory_follower/include/trajectory_follower/longitudinal_controller_base.hpp
@@ -0,0 +1,51 @@
+// Copyright 2022 The Autoware Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef TRAJECTORY_FOLLOWER__LONGITUDINAL_CONTROLLER_BASE_HPP_
+#define TRAJECTORY_FOLLOWER__LONGITUDINAL_CONTROLLER_BASE_HPP_
+
+#include "rclcpp/rclcpp.hpp"
+#include "trajectory_follower/sync_data.hpp"
+
+#include "autoware_auto_control_msgs/msg/longitudinal_command.hpp"
+
+namespace autoware
+{
+namespace motion
+{
+namespace control
+{
+namespace trajectory_follower
+{
+struct LongitudinalOutput
+{
+ autoware_auto_control_msgs::msg::LongitudinalCommand control_cmd;
+ LongitudinalSyncData sync_data;
+};
+class LongitudinalControllerBase
+{
+public:
+ virtual LongitudinalOutput run() = 0;
+ void sync(LateralSyncData lateral_sync_data) { lateral_sync_data_ = lateral_sync_data; };
+
+protected:
+ LateralSyncData lateral_sync_data_;
+};
+
+} // namespace trajectory_follower
+} // namespace control
+} // namespace motion
+} // namespace autoware
+
+#endif // TRAJECTORY_FOLLOWER__LONGITUDINAL_CONTROLLER_BASE_HPP_
diff --git a/control/trajectory_follower/include/trajectory_follower/mpc_lateral_controller.hpp b/control/trajectory_follower/include/trajectory_follower/mpc_lateral_controller.hpp
new file mode 100644
index 0000000000000..db05acaab33f6
--- /dev/null
+++ b/control/trajectory_follower/include/trajectory_follower/mpc_lateral_controller.hpp
@@ -0,0 +1,238 @@
+// Copyright 2021 The Autoware Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef TRAJECTORY_FOLLOWER__MPC_LATERAL_CONTROLLER_HPP_
+#define TRAJECTORY_FOLLOWER__MPC_LATERAL_CONTROLLER_HPP_
+
+#include "common/types.hpp"
+#include "osqp_interface/osqp_interface.hpp"
+#include "rclcpp/rclcpp.hpp"
+#include "tf2/utils.h"
+#include "tf2_ros/buffer.h"
+#include "tf2_ros/transform_listener.h"
+#include "trajectory_follower/interpolate.hpp"
+#include "trajectory_follower/lateral_controller_base.hpp"
+#include "trajectory_follower/lowpass_filter.hpp"
+#include "trajectory_follower/mpc.hpp"
+#include "trajectory_follower/mpc_trajectory.hpp"
+#include "trajectory_follower/mpc_utils.hpp"
+#include "trajectory_follower/qp_solver/qp_solver_osqp.hpp"
+#include "trajectory_follower/qp_solver/qp_solver_unconstr_fast.hpp"
+#include "trajectory_follower/sync_data.hpp"
+#include "trajectory_follower/vehicle_model/vehicle_model_bicycle_dynamics.hpp"
+#include "trajectory_follower/vehicle_model/vehicle_model_bicycle_kinematics.hpp"
+#include "trajectory_follower/vehicle_model/vehicle_model_bicycle_kinematics_no_delay.hpp"
+#include "trajectory_follower/visibility_control.hpp"
+#include "vehicle_info_util/vehicle_info_util.hpp"
+
+#include "autoware_auto_control_msgs/msg/ackermann_lateral_command.hpp"
+#include "autoware_auto_planning_msgs/msg/trajectory.hpp"
+#include "autoware_auto_system_msgs/msg/float32_multi_array_diagnostic.hpp"
+#include "autoware_auto_vehicle_msgs/msg/steering_report.hpp"
+#include "autoware_auto_vehicle_msgs/msg/vehicle_odometry.hpp"
+#include "geometry_msgs/msg/pose.hpp"
+#include "geometry_msgs/msg/pose_stamped.hpp"
+#include "nav_msgs/msg/odometry.hpp"
+#include "tf2_msgs/msg/tf_message.hpp"
+
+#include
+#include
+#include
+#include
+
+namespace autoware
+{
+namespace motion
+{
+namespace control
+{
+namespace trajectory_follower
+{
+using autoware::common::types::bool8_t;
+using autoware::common::types::float64_t;
+namespace trajectory_follower = ::autoware::motion::control::trajectory_follower;
+
+class TRAJECTORY_FOLLOWER_PUBLIC MpcLateralController : public LateralControllerBase
+{
+public:
+ /**
+ * @brief constructor
+ */
+ explicit MpcLateralController(rclcpp::Node * node);
+
+ /**
+ * @brief destructor
+ */
+ virtual ~MpcLateralController();
+
+private:
+ rclcpp::Node::SharedPtr node_;
+
+ //!< @brief topic publisher for control command
+ rclcpp::Publisher::SharedPtr
+ m_pub_ctrl_cmd;
+ //!< @brief topic publisher for predicted trajectory
+ rclcpp::Publisher::SharedPtr m_pub_predicted_traj;
+ //!< @brief topic publisher for control diagnostic
+ rclcpp::Publisher::SharedPtr
+ m_pub_diagnostic;
+ //!< @brief topic subscription for reference waypoints
+ rclcpp::Subscription::SharedPtr m_sub_ref_path;
+ //!< @brief subscription for current velocity
+ rclcpp::Subscription::SharedPtr m_sub_odometry;
+ //!< @brief subscription for current steering
+ rclcpp::Subscription::SharedPtr m_sub_steering;
+ //!< @brief timer to update after a given interval
+ rclcpp::TimerBase::SharedPtr m_timer;
+ //!< @brief subscription for transform messages
+ rclcpp::Subscription::SharedPtr m_tf_sub;
+ rclcpp::Subscription::SharedPtr m_tf_static_sub;
+
+ /* parameters for path smoothing */
+ //!< @brief flag for path smoothing
+ bool8_t m_enable_path_smoothing;
+ //!< @brief param of moving average filter for path smoothing
+ int64_t m_path_filter_moving_ave_num;
+ //!< @brief point-to-point index distance for curvature calculation for trajectory //NOLINT
+ int64_t m_curvature_smoothing_num_traj;
+ //!< @brief point-to-point index distance for curvature calculation for reference steer command
+ //!< //NOLINT
+ int64_t m_curvature_smoothing_num_ref_steer;
+ //!< @brief path resampling interval [m]
+ float64_t m_traj_resample_dist;
+
+ /* parameters for stop state */
+ float64_t m_stop_state_entry_ego_speed;
+ float64_t m_stop_state_entry_target_speed;
+ float64_t m_converged_steer_rad;
+ bool m_check_steer_converged_for_stopped_state;
+
+ // MPC object
+ trajectory_follower::MPC m_mpc;
+
+ //!< @brief measured pose
+ geometry_msgs::msg::PoseStamped::SharedPtr m_current_pose_ptr;
+ //!< @brief measured velocity
+ nav_msgs::msg::Odometry::SharedPtr m_current_odometry_ptr;
+ //!< @brief measured steering
+ autoware_auto_vehicle_msgs::msg::SteeringReport::SharedPtr m_current_steering_ptr;
+ //!< @brief reference trajectory
+ autoware_auto_planning_msgs::msg::Trajectory::SharedPtr m_current_trajectory_ptr;
+
+ //!< @brief mpc filtered output in previous period
+ float64_t m_steer_cmd_prev = 0.0;
+
+ //!< @brief flag of m_ctrl_cmd_prev initialization
+ bool8_t m_is_ctrl_cmd_prev_initialized = false;
+ //!< @brief previous control command
+ autoware_auto_control_msgs::msg::AckermannLateralCommand m_ctrl_cmd_prev;
+
+ //!< @brief buffer for transforms
+ tf2::BufferCore m_tf_buffer{tf2::BUFFER_CORE_DEFAULT_CACHE_TIME};
+ tf2_ros::TransformListener m_tf_listener{m_tf_buffer};
+
+ LateralSyncData lateral_sync_data_;
+
+ //!< initialize timer to work in real, simulation, and replay
+ void initTimer(float64_t period_s);
+ /**
+ * @brief compute and publish control command for path follow with a constant control period
+ */
+ LateralOutput run() override;
+
+ /**
+ * @brief set m_current_trajectory with received message
+ */
+ void onTrajectory(const autoware_auto_planning_msgs::msg::Trajectory::SharedPtr);
+
+ /**
+ * @brief update current_pose from tf
+ * @return true if the current pose was updated, false otherwise
+ */
+ bool8_t updateCurrentPose();
+
+ /**
+ * @brief check if the received data is valid.
+ */
+ bool8_t checkData() const;
+
+ /**
+ * @brief set current_velocity with received message
+ */
+ void onOdometry(const nav_msgs::msg::Odometry::SharedPtr msg);
+
+ /**
+ * @brief set current_steering with received message
+ */
+ void onSteering(const autoware_auto_vehicle_msgs::msg::SteeringReport::SharedPtr msg);
+
+ /**
+ * @brief create control command
+ * @param [in] cmd published control command
+ */
+ autoware_auto_control_msgs::msg::AckermannLateralCommand createCtrlCmdMsg(
+ autoware_auto_control_msgs::msg::AckermannLateralCommand cmd);
+
+ /**
+ * @brief publish predicted future trajectory
+ * @param [in] predicted_traj published predicted trajectory
+ */
+ void publishPredictedTraj(autoware_auto_planning_msgs::msg::Trajectory & predicted_traj) const;
+
+ /**
+ * @brief publish diagnostic message
+ * @param [in] diagnostic published diagnostic
+ */
+ void publishDiagnostic(
+ autoware_auto_system_msgs::msg::Float32MultiArrayDiagnostic & diagnostic) const;
+
+ /**
+ * @brief get stop command
+ */
+ autoware_auto_control_msgs::msg::AckermannLateralCommand getStopControlCommand() const;
+
+ /**
+ * @brief get initial command
+ */
+ autoware_auto_control_msgs::msg::AckermannLateralCommand getInitialControlCommand() const;
+
+ /**
+ * @brief check ego car is in stopped state
+ */
+ bool8_t isStoppedState() const;
+
+ /**
+ * @brief check if the trajectory has valid value
+ */
+ bool8_t isValidTrajectory(const autoware_auto_planning_msgs::msg::Trajectory & traj) const;
+
+ rclcpp::Node::OnSetParametersCallbackHandle::SharedPtr m_set_param_res;
+
+ /**
+ * @brief Declare MPC parameters as ROS parameters to allow tuning on the fly
+ */
+ void declareMPCparameters();
+
+ /**
+ * @brief Called when parameters are changed outside of node
+ */
+ rcl_interfaces::msg::SetParametersResult paramCallback(
+ const std::vector & parameters);
+};
+} // namespace trajectory_follower
+} // namespace control
+} // namespace motion
+} // namespace autoware
+
+#endif // TRAJECTORY_FOLLOWER__MPC_LATERAL_CONTROLLER_HPP_
diff --git a/control/trajectory_follower/include/trajectory_follower/pid_longitudinal_controller.hpp b/control/trajectory_follower/include/trajectory_follower/pid_longitudinal_controller.hpp
new file mode 100644
index 0000000000000..e66d87bb0ec22
--- /dev/null
+++ b/control/trajectory_follower/include/trajectory_follower/pid_longitudinal_controller.hpp
@@ -0,0 +1,381 @@
+// Copyright 2021 Tier IV, Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef TRAJECTORY_FOLLOWER__PID_LONGITUDINAL_CONTROLLER_HPP_
+#define TRAJECTORY_FOLLOWER__PID_LONGITUDINAL_CONTROLLER_HPP_
+
+#include "eigen3/Eigen/Core"
+#include "eigen3/Eigen/Geometry"
+#include "motion_common/motion_common.hpp"
+#include "motion_common/trajectory_common.hpp"
+#include "rclcpp/rclcpp.hpp"
+#include "tf2/utils.h"
+#include "tf2_ros/buffer.h"
+#include "tf2_ros/transform_listener.h"
+#include "trajectory_follower/debug_values.hpp"
+#include "trajectory_follower/longitudinal_controller_base.hpp"
+#include "trajectory_follower/longitudinal_controller_utils.hpp"
+#include "trajectory_follower/lowpass_filter.hpp"
+#include "trajectory_follower/pid.hpp"
+#include "trajectory_follower/smooth_stop.hpp"
+#include "vehicle_info_util/vehicle_info_util.hpp"
+
+#include "autoware_auto_control_msgs/msg/longitudinal_command.hpp"
+#include "autoware_auto_planning_msgs/msg/trajectory.hpp"
+#include "autoware_auto_system_msgs/msg/float32_multi_array_diagnostic.hpp"
+#include "autoware_auto_vehicle_msgs/msg/vehicle_odometry.hpp"
+#include "geometry_msgs/msg/pose_stamped.hpp"
+#include "nav_msgs/msg/odometry.hpp"
+#include "tf2_msgs/msg/tf_message.hpp"
+
+#include
+#include
+#include
+#include
+
+namespace autoware
+{
+namespace motion
+{
+namespace control
+{
+namespace trajectory_follower
+{
+using autoware::common::types::bool8_t;
+using autoware::common::types::float64_t;
+namespace trajectory_follower = ::autoware::motion::control::trajectory_follower;
+namespace motion_common = ::autoware::motion::motion_common;
+
+/// \class PidLongitudinalController
+/// \brief The node class used for generating longitudinal control commands (velocity/acceleration)
+class TRAJECTORY_FOLLOWER_PUBLIC PidLongitudinalController : public LongitudinalControllerBase
+{
+public:
+ explicit PidLongitudinalController(rclcpp::Node * node);
+
+private:
+ struct Motion
+ {
+ float64_t vel{0.0};
+ float64_t acc{0.0};
+ };
+
+ enum class Shift { Forward = 0, Reverse };
+
+ struct ControlData
+ {
+ bool8_t is_far_from_trajectory{false};
+ size_t nearest_idx{0}; // nearest_idx = 0 when nearest_idx is not found with findNearestIdx
+ Motion current_motion{};
+ Shift shift{Shift::Forward}; // shift is used only to calculate the sign of pitch compensation
+ float64_t stop_dist{0.0}; // signed distance that is positive when car is before the stopline
+ float64_t slope_angle{0.0};
+ float64_t dt{0.0};
+ };
+ rclcpp::Node::SharedPtr node_;
+ rclcpp::Logger logger_;
+ rclcpp::Clock::SharedPtr clock_;
+
+ // ros variables
+ rclcpp::Subscription::SharedPtr m_sub_current_velocity;
+ rclcpp::Subscription::SharedPtr m_sub_trajectory;
+ rclcpp::Publisher::SharedPtr
+ m_pub_control_cmd;
+ rclcpp::Publisher::SharedPtr
+ m_pub_slope;
+ rclcpp::Publisher::SharedPtr
+ m_pub_debug;
+ rclcpp::TimerBase::SharedPtr m_timer_control;
+
+ rclcpp::Subscription::SharedPtr m_tf_sub;
+ rclcpp::Subscription::SharedPtr m_tf_static_sub;
+ tf2::BufferCore m_tf_buffer{tf2::BUFFER_CORE_DEFAULT_CACHE_TIME};
+ tf2_ros::TransformListener m_tf_listener{m_tf_buffer};
+
+ rclcpp::Node::OnSetParametersCallbackHandle::SharedPtr m_set_param_res;
+ rcl_interfaces::msg::SetParametersResult paramCallback(
+ const std::vector & parameters);
+
+ // pointers for ros topic
+ std::shared_ptr m_current_velocity_ptr{nullptr};
+ std::shared_ptr m_prev_velocity_ptr{nullptr};
+ std::shared_ptr m_trajectory_ptr{nullptr};
+
+ // vehicle info
+ float64_t m_wheel_base;
+
+ // control state
+ enum class ControlState { DRIVE = 0, STOPPING, STOPPED, EMERGENCY };
+ ControlState m_control_state{ControlState::STOPPED};
+
+ // control period
+ float64_t m_longitudinal_ctrl_period;
+
+ // delay compensation
+ float64_t m_delay_compensation_time;
+
+ // enable flags
+ bool8_t m_enable_smooth_stop;
+ bool8_t m_enable_overshoot_emergency;
+ bool8_t m_enable_slope_compensation;
+ bool8_t m_enable_keep_stopped_until_steer_convergence;
+
+ // smooth stop transition
+ struct StateTransitionParams
+ {
+ // drive
+ float64_t drive_state_stop_dist;
+ float64_t drive_state_offset_stop_dist;
+ // stopping
+ float64_t stopping_state_stop_dist;
+ // stop
+ float64_t stopped_state_entry_duration_time;
+ float64_t stopped_state_entry_vel;
+ float64_t stopped_state_entry_acc;
+ // emergency
+ float64_t emergency_state_overshoot_stop_dist;
+ float64_t emergency_state_traj_trans_dev;
+ float64_t emergency_state_traj_rot_dev;
+ };
+ StateTransitionParams m_state_transition_params;
+
+ // drive
+ trajectory_follower::PIDController m_pid_vel;
+ std::shared_ptr m_lpf_vel_error{nullptr};
+ float64_t m_current_vel_threshold_pid_integrate;
+ bool8_t m_enable_brake_keeping_before_stop;
+ float64_t m_brake_keeping_acc;
+
+ // smooth stop
+ trajectory_follower::SmoothStop m_smooth_stop;
+
+ // stop
+ struct StoppedStateParams
+ {
+ float64_t vel;
+ float64_t acc;
+ float64_t jerk;
+ };
+ StoppedStateParams m_stopped_state_params;
+
+ // emergency
+ struct EmergencyStateParams
+ {
+ float64_t vel;
+ float64_t acc;
+ float64_t jerk;
+ };
+ EmergencyStateParams m_emergency_state_params;
+
+ // acceleration limit
+ float64_t m_max_acc;
+ float64_t m_min_acc;
+
+ // jerk limit
+ float64_t m_max_jerk;
+ float64_t m_min_jerk;
+
+ // slope compensation
+ bool8_t m_use_traj_for_pitch;
+ std::shared_ptr m_lpf_pitch{nullptr};
+ float64_t m_max_pitch_rad;
+ float64_t m_min_pitch_rad;
+
+ // 1st order lowpass filter for acceleration
+ std::shared_ptr m_lpf_acc{nullptr};
+
+ // buffer of send command
+ std::vector m_ctrl_cmd_vec;
+
+ // for calculating dt
+ std::shared_ptr m_prev_control_time{nullptr};
+
+ // shift mode
+ Shift m_prev_shift{Shift::Forward};
+
+ // diff limit
+ Motion m_prev_ctrl_cmd{}; // with slope compensation
+ Motion m_prev_raw_ctrl_cmd{}; // without slope compensation
+ std::vector> m_vel_hist;
+
+ // debug values
+ trajectory_follower::DebugValues m_debug_values;
+
+ std::shared_ptr m_last_running_time{
+ std::make_shared(rclcpp::Clock{RCL_ROS_TIME}.now())};
+
+ /**
+ * @brief set current and previous velocity with received message
+ * @param [in] msg current state message
+ */
+ void callbackCurrentVelocity(const nav_msgs::msg::Odometry::ConstSharedPtr msg);
+
+ /**
+ * @brief set reference trajectory with received message
+ * @param [in] msg trajectory message
+ */
+ void callbackTrajectory(const autoware_auto_planning_msgs::msg::Trajectory::ConstSharedPtr msg);
+
+ /**
+ * @brief compute control command, and publish periodically
+ */
+ // void callbackTimerControl();
+ LongitudinalOutput run() override;
+
+ /**
+ * @brief calculate data for controllers whose type is ControlData
+ * @param [in] current_pose current ego pose
+ */
+ ControlData getControlData(const geometry_msgs::msg::Pose & current_pose);
+
+ /**
+ * @brief calculate control command in emergency state
+ * @param [in] dt time between previous and current one
+ */
+ Motion calcEmergencyCtrlCmd(const float64_t dt) const;
+
+ /**
+ * @brief update control state according to the current situation
+ * @param [in] current_control_state current control state
+ * @param [in] control_data control data
+ */
+ ControlState updateControlState(
+ const ControlState current_control_state, const ControlData & control_data);
+
+ /**
+ * @brief calculate control command based on the current control state
+ * @param [in] current_control_state current control state
+ * @param [in] current_pose current ego pose
+ * @param [in] control_data control data
+ */
+ Motion calcCtrlCmd(
+ const ControlState & current_control_state, const geometry_msgs::msg::Pose & current_pose,
+ const ControlData & control_data);
+
+ /**
+ * @brief publish control command
+ * @param [in] ctrl_cmd calculated control command to control velocity
+ * @param [in] current_vel current velocity of the vehicle
+ */
+ autoware_auto_control_msgs::msg::LongitudinalCommand createCtrlCmdMsg(
+ const Motion & ctrl_cmd, const float64_t current_vel);
+
+ /**
+ * @brief publish debug data
+ * @param [in] ctrl_cmd calculated control command to control velocity
+ * @param [in] control_data data for control calculation
+ */
+ void publishDebugData(const Motion & ctrl_cmd, const ControlData & control_data);
+
+ /**
+ * @brief calculate time between current and previous one
+ */
+ float64_t getDt();
+
+ /**
+ * @brief calculate current velocity and acceleration
+ */
+ Motion getCurrentMotion() const;
+
+ /**
+ * @brief calculate direction (forward or backward) that vehicle moves
+ * @param [in] nearest_idx nearest index on trajectory to vehicle
+ */
+ enum Shift getCurrentShift(const size_t nearest_idx) const;
+
+ /**
+ * @brief filter acceleration command with limitation of acceleration and jerk, and slope
+ * compensation
+ * @param [in] raw_acc acceleration before filtered
+ * @param [in] control_data data for control calculation
+ */
+ float64_t calcFilteredAcc(const float64_t raw_acc, const ControlData & control_data);
+
+ /**
+ * @brief store acceleration command before slope compensation
+ * @param [in] accel command before slope compensation
+ */
+ void storeAccelCmd(const float64_t accel);
+
+ /**
+ * @brief add acceleration to compensate for slope
+ * @param [in] acc acceleration before slope compensation
+ * @param [in] pitch pitch angle (upward is negative)
+ * @param [in] shift direction that vehicle move (forward or backward)
+ */
+ float64_t applySlopeCompensation(
+ const float64_t acc, const float64_t pitch, const Shift shift) const;
+
+ /**
+ * @brief keep target motion acceleration negative before stop
+ * @param [in] traj reference trajectory
+ * @param [in] motion delay compensated target motion
+ */
+ Motion keepBrakeBeforeStop(
+ const autoware_auto_planning_msgs::msg::Trajectory & traj, const Motion & target_motion,
+ const size_t nearest_idx) const;
+
+ /**
+ * @brief interpolate trajectory point that is nearest to vehicle
+ * @param [in] traj reference trajectory
+ * @param [in] point vehicle position
+ * @param [in] nearest_idx index of the trajectory point nearest to the vehicle position
+ */
+ autoware_auto_planning_msgs::msg::TrajectoryPoint calcInterpolatedTargetValue(
+ const autoware_auto_planning_msgs::msg::Trajectory & traj,
+ const geometry_msgs::msg::Point & point, const size_t nearest_idx) const;
+
+ /**
+ * @brief calculate predicted velocity after time delay based on past control commands
+ * @param [in] current_motion current velocity and acceleration of the vehicle
+ * @param [in] delay_compensation_time predicted time delay
+ */
+ float64_t predictedVelocityInTargetPoint(
+ const Motion current_motion, const float64_t delay_compensation_time) const;
+
+ /**
+ * @brief calculate velocity feedback with feed forward and pid controller
+ * @param [in] target_motion reference velocity and acceleration. This acceleration will be used
+ * as feed forward.
+ * @param [in] dt time step to use
+ * @param [in] current_vel current velocity of the vehicle
+ */
+ float64_t applyVelocityFeedback(
+ const Motion target_motion, const float64_t dt, const float64_t current_vel);
+
+ /**
+ * @brief update variables for debugging about pitch
+ * @param [in] pitch current pitch of the vehicle (filtered)
+ * @param [in] traj_pitch current trajectory pitch
+ * @param [in] raw_pitch current raw pitch of the vehicle (unfiltered)
+ */
+ void updatePitchDebugValues(
+ const float64_t pitch, const float64_t traj_pitch, const float64_t raw_pitch);
+
+ /**
+ * @brief update variables for velocity and acceleration
+ * @param [in] ctrl_cmd latest calculated control command
+ * @param [in] current_pose current pose of the vehicle
+ * @param [in] control_data data for control calculation
+ */
+ void updateDebugVelAcc(
+ const Motion & ctrl_cmd, const geometry_msgs::msg::Pose & current_pose,
+ const ControlData & control_data);
+};
+} // namespace trajectory_follower
+} // namespace control
+} // namespace motion
+} // namespace autoware
+
+#endif // TRAJECTORY_FOLLOWER__PID_LONGITUDINAL_CONTROLLER_HPP_
diff --git a/control/trajectory_follower/include/trajectory_follower/sync_data.hpp b/control/trajectory_follower/include/trajectory_follower/sync_data.hpp
new file mode 100644
index 0000000000000..48224a5498a9c
--- /dev/null
+++ b/control/trajectory_follower/include/trajectory_follower/sync_data.hpp
@@ -0,0 +1,41 @@
+// Copyright 2022 The Autoware Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef TRAJECTORY_FOLLOWER__SYNC_DATA_HPP_
+#define TRAJECTORY_FOLLOWER__SYNC_DATA_HPP_
+
+namespace autoware
+{
+namespace motion
+{
+namespace control
+{
+namespace trajectory_follower
+{
+struct LateralSyncData
+{
+ bool is_steer_converged{false};
+};
+
+struct LongitudinalSyncData
+{
+ bool is_velocity_converged{false};
+};
+
+} // namespace trajectory_follower
+} // namespace control
+} // namespace motion
+} // namespace autoware
+
+#endif // TRAJECTORY_FOLLOWER__SYNC_DATA_HPP_
diff --git a/control/trajectory_follower/package.xml b/control/trajectory_follower/package.xml
index 4bc005335f4a9..c68b1013ab252 100644
--- a/control/trajectory_follower/package.xml
+++ b/control/trajectory_follower/package.xml
@@ -27,8 +27,9 @@
std_msgs
tf2
tf2_ros
+ vehicle_info_util
- ament_cmake_gtest
+ ament_cmake_ros
ament_lint_auto
autoware_lint_common
eigen
diff --git a/control/trajectory_follower/src/mpc_lateral_controller.cpp b/control/trajectory_follower/src/mpc_lateral_controller.cpp
new file mode 100644
index 0000000000000..6df6ad577fb92
--- /dev/null
+++ b/control/trajectory_follower/src/mpc_lateral_controller.cpp
@@ -0,0 +1,549 @@
+// Copyright 2021 The Autoware Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "trajectory_follower/mpc_lateral_controller.hpp"
+
+#include "tf2_ros/create_timer_ros.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace autoware
+{
+namespace motion
+{
+namespace control
+{
+namespace trajectory_follower
+{
+namespace
+{
+using namespace std::literals::chrono_literals;
+
+template
+void update_param(
+ const std::vector & parameters, const std::string & name, T & value)
+{
+ auto it = std::find_if(
+ parameters.cbegin(), parameters.cend(),
+ [&name](const rclcpp::Parameter & parameter) { return parameter.get_name() == name; });
+ if (it != parameters.cend()) {
+ value = static_cast(it->template get_value());
+ }
+}
+} // namespace
+
+MpcLateralController::MpcLateralController(rclcpp::Node * node) : node_{node}
+{
+ using std::placeholders::_1;
+
+ m_mpc.m_ctrl_period = node_->get_parameter("ctrl_period").as_double();
+ m_enable_path_smoothing = node_->declare_parameter("enable_path_smoothing");
+ m_path_filter_moving_ave_num = node_->declare_parameter("path_filter_moving_ave_num");
+ m_curvature_smoothing_num_traj =
+ node_->declare_parameter("curvature_smoothing_num_traj");
+ m_curvature_smoothing_num_ref_steer =
+ node_->declare_parameter("curvature_smoothing_num_ref_steer");
+ m_traj_resample_dist = node_->declare_parameter("traj_resample_dist");
+ m_mpc.m_admissible_position_error =
+ node_->declare_parameter("admissible_position_error");
+ m_mpc.m_admissible_yaw_error_rad =
+ node_->declare_parameter("admissible_yaw_error_rad");
+ m_mpc.m_use_steer_prediction = node_->declare_parameter("use_steer_prediction");
+ m_mpc.m_param.steer_tau = node_->declare_parameter("vehicle_model_steer_tau");
+
+ /* stop state parameters */
+ m_stop_state_entry_ego_speed = node_->declare_parameter("stop_state_entry_ego_speed");
+ m_stop_state_entry_target_speed =
+ node_->declare_parameter("stop_state_entry_target_speed");
+ m_converged_steer_rad = node_->declare_parameter("converged_steer_rad");
+ m_check_steer_converged_for_stopped_state =
+ node_->declare_parameter("check_steer_converged_for_stopped_state");
+
+ /* mpc parameters */
+ const float64_t steer_lim_deg = node_->declare_parameter("steer_lim_deg");
+ const float64_t steer_rate_lim_dps = node_->declare_parameter("steer_rate_lim_dps");
+ constexpr float64_t deg2rad = static_cast(autoware::common::types::PI) / 180.0;
+ m_mpc.m_steer_lim = steer_lim_deg * deg2rad;
+ m_mpc.m_steer_rate_lim = steer_rate_lim_dps * deg2rad;
+ const float64_t wheelbase =
+ vehicle_info_util::VehicleInfoUtil(*node_).getVehicleInfo().wheel_base_m;
+
+ /* vehicle model setup */
+ const std::string vehicle_model_type =
+ node_->declare_parameter("vehicle_model_type");
+ std::shared_ptr vehicle_model_ptr;
+ if (vehicle_model_type == "kinematics") {
+ vehicle_model_ptr = std::make_shared(
+ wheelbase, m_mpc.m_steer_lim, m_mpc.m_param.steer_tau);
+ } else if (vehicle_model_type == "kinematics_no_delay") {
+ vehicle_model_ptr = std::make_shared(
+ wheelbase, m_mpc.m_steer_lim);
+ } else if (vehicle_model_type == "dynamics") {
+ const float64_t mass_fl = node_->declare_parameter("vehicle.mass_fl");
+ const float64_t mass_fr = node_->declare_parameter("vehicle.mass_fr");
+ const float64_t mass_rl = node_->declare_parameter("vehicle.mass_rl");
+ const float64_t mass_rr = node_->declare_parameter("vehicle.mass_rr");
+ const float64_t cf = node_->declare_parameter("vehicle.cf");
+ const float64_t cr = node_->declare_parameter("vehicle.cr");
+
+ // vehicle_model_ptr is only assigned in ctor, so parameter value have to be passed at init time
+ // // NOLINT
+ vehicle_model_ptr = std::make_shared(
+ wheelbase, mass_fl, mass_fr, mass_rl, mass_rr, cf, cr);
+ } else {
+ RCLCPP_ERROR(node_->get_logger(), "vehicle_model_type is undefined");
+ }
+
+ /* QP solver setup */
+ const std::string qp_solver_type = node_->declare_parameter("qp_solver_type");
+ std::shared_ptr qpsolver_ptr;
+ if (qp_solver_type == "unconstraint_fast") {
+ qpsolver_ptr = std::make_shared();
+ } else if (qp_solver_type == "osqp") {
+ qpsolver_ptr = std::make_shared(node_->get_logger());
+ } else {
+ RCLCPP_ERROR(node_->get_logger(), "qp_solver_type is undefined");
+ }
+
+ /* delay compensation */
+ {
+ const float64_t delay_tmp = node_->declare_parameter("input_delay");
+ const float64_t delay_step = std::round(delay_tmp / m_mpc.m_ctrl_period);
+ m_mpc.m_param.input_delay = delay_step * m_mpc.m_ctrl_period;
+ m_mpc.m_input_buffer = std::deque(static_cast(delay_step), 0.0);
+ }
+
+ /* initialize lowpass filter */
+ {
+ const float64_t steering_lpf_cutoff_hz =
+ node_->declare_parameter("steering_lpf_cutoff_hz");
+ const float64_t error_deriv_lpf_cutoff_hz =
+ node_->declare_parameter("error_deriv_lpf_cutoff_hz");
+ m_mpc.initializeLowPassFilters(steering_lpf_cutoff_hz, error_deriv_lpf_cutoff_hz);
+ }
+
+ /* set up ros system */
+ // initTimer(m_mpc.m_ctrl_period);
+
+ m_pub_ctrl_cmd =
+ node_->create_publisher(
+ "~/output/lateral_control_cmd", 1);
+ m_pub_predicted_traj = node_->create_publisher(
+ "~/output/predicted_trajectory", 1);
+ m_pub_diagnostic =
+ node_->create_publisher(
+ "~/output/lateral_diagnostic", 1);
+ m_sub_ref_path = node_->create_subscription(
+ "~/input/current_trajectory", rclcpp::QoS{1},
+ std::bind(&MpcLateralController::onTrajectory, this, _1));
+ m_sub_steering = node_->create_subscription(
+ "~/input/current_steering", rclcpp::QoS{1},
+ std::bind(&MpcLateralController::onSteering, this, _1));
+ m_sub_odometry = node_->create_subscription(
+ "~/input/current_odometry", rclcpp::QoS{1},
+ std::bind(&MpcLateralController::onOdometry, this, _1));
+
+ // TODO(Frederik.Beaujean) ctor is too long, should factor out parameter declarations
+ declareMPCparameters();
+
+ /* get parameter updates */
+ m_set_param_res = node_->add_on_set_parameters_callback(
+ std::bind(&MpcLateralController::paramCallback, this, _1));
+
+ m_mpc.setQPSolver(qpsolver_ptr);
+ m_mpc.setVehicleModel(vehicle_model_ptr, vehicle_model_type);
+
+ m_mpc.setLogger(node_->get_logger());
+ m_mpc.setClock(node_->get_clock());
+}
+
+MpcLateralController::~MpcLateralController()
+{
+ autoware_auto_control_msgs::msg::AckermannLateralCommand stop_cmd = getStopControlCommand();
+ createCtrlCmdMsg(stop_cmd); // todo
+}
+
+LateralOutput MpcLateralController::run()
+{
+ if (!checkData() || !updateCurrentPose()) {
+ LateralOutput output;
+ return output; // todo
+ }
+
+ autoware_auto_control_msgs::msg::AckermannLateralCommand ctrl_cmd;
+ autoware_auto_planning_msgs::msg::Trajectory predicted_traj;
+ autoware_auto_system_msgs::msg::Float32MultiArrayDiagnostic diagnostic;
+
+ if (!m_is_ctrl_cmd_prev_initialized) {
+ m_ctrl_cmd_prev = getInitialControlCommand();
+ m_is_ctrl_cmd_prev_initialized = true;
+ }
+
+ const bool8_t is_mpc_solved = m_mpc.calculateMPC(
+ *m_current_steering_ptr, m_current_odometry_ptr->twist.twist.linear.x, m_current_pose_ptr->pose,
+ ctrl_cmd, predicted_traj, diagnostic);
+
+ if (isStoppedState()) {
+ // Reset input buffer
+ for (auto & value : m_mpc.m_input_buffer) {
+ value = m_ctrl_cmd_prev.steering_tire_angle;
+ }
+ // Use previous command value as previous raw steer command
+ m_mpc.m_raw_steer_cmd_prev = m_ctrl_cmd_prev.steering_tire_angle;
+
+ const auto cmd_msg = createCtrlCmdMsg(m_ctrl_cmd_prev);
+ publishPredictedTraj(predicted_traj);
+ publishDiagnostic(diagnostic);
+ LateralOutput output;
+ output.control_cmd = cmd_msg;
+ output.sync_data.is_steer_converged =
+ std::abs(cmd_msg.steering_tire_angle - m_current_steering_ptr->steering_tire_angle) <
+ m_converged_steer_rad;
+ return output;
+ }
+
+ if (!is_mpc_solved) {
+ RCLCPP_WARN_SKIPFIRST_THROTTLE(
+ node_->get_logger(), *node_->get_clock(), 5000 /*ms*/,
+ "MPC is not solved. publish 0 velocity.");
+ ctrl_cmd = getStopControlCommand();
+ }
+
+ m_ctrl_cmd_prev = ctrl_cmd;
+ const auto cmd_msg = createCtrlCmdMsg(ctrl_cmd);
+ publishPredictedTraj(predicted_traj);
+ publishDiagnostic(diagnostic);
+ LateralOutput output;
+ output.control_cmd = cmd_msg;
+ output.sync_data.is_steer_converged =
+ std::abs(cmd_msg.steering_tire_angle - m_current_steering_ptr->steering_tire_angle) <
+ m_converged_steer_rad;
+ return output;
+}
+
+bool8_t MpcLateralController::checkData() const
+{
+ if (!m_mpc.hasVehicleModel()) {
+ RCLCPP_DEBUG(node_->get_logger(), "MPC does not have a vehicle model");
+ return false;
+ }
+ if (!m_mpc.hasQPSolver()) {
+ RCLCPP_DEBUG(node_->get_logger(), "MPC does not have a QP solver");
+ return false;
+ }
+
+ if (!m_current_odometry_ptr) {
+ RCLCPP_DEBUG(
+ node_->get_logger(), "waiting data. current_velocity = %d",
+ m_current_odometry_ptr != nullptr);
+ return false;
+ }
+
+ if (!m_current_steering_ptr) {
+ RCLCPP_DEBUG(
+ node_->get_logger(), "waiting data. current_steering = %d",
+ m_current_steering_ptr != nullptr);
+ return false;
+ }
+
+ if (m_mpc.m_ref_traj.size() == 0) {
+ RCLCPP_DEBUG(node_->get_logger(), "trajectory size is zero.");
+ return false;
+ }
+
+ return true;
+}
+
+void MpcLateralController::onTrajectory(
+ const autoware_auto_planning_msgs::msg::Trajectory::SharedPtr msg)
+{
+ m_current_trajectory_ptr = msg;
+
+ if (!m_current_pose_ptr && !updateCurrentPose()) {
+ RCLCPP_DEBUG(node_->get_logger(), "Current pose is not received yet.");
+ return;
+ }
+
+ if (msg->points.size() < 3) {
+ RCLCPP_DEBUG(node_->get_logger(), "received path size is < 3, not enough.");
+ return;
+ }
+
+ if (!isValidTrajectory(*msg)) {
+ RCLCPP_ERROR(node_->get_logger(), "Trajectory is invalid!! stop computing.");
+ return;
+ }
+
+ m_mpc.setReferenceTrajectory(
+ *msg, m_traj_resample_dist, m_enable_path_smoothing, m_path_filter_moving_ave_num,
+ m_curvature_smoothing_num_traj, m_curvature_smoothing_num_ref_steer, m_current_pose_ptr);
+}
+
+bool8_t MpcLateralController::updateCurrentPose()
+{
+ geometry_msgs::msg::TransformStamped transform;
+ try {
+ transform = m_tf_buffer.lookupTransform(
+ m_current_trajectory_ptr->header.frame_id, "base_link", tf2::TimePointZero);
+ } catch (tf2::TransformException & ex) {
+ RCLCPP_WARN_SKIPFIRST_THROTTLE(
+ node_->get_logger(), *node_->get_clock(), 5000 /*ms*/, ex.what());
+ RCLCPP_WARN_SKIPFIRST_THROTTLE(
+ node_->get_logger(), *node_->get_clock(), 5000 /*ms*/,
+ m_tf_buffer.allFramesAsString().c_str());
+ return false;
+ }
+
+ geometry_msgs::msg::PoseStamped ps;
+ ps.header = transform.header;
+ ps.pose.position.x = transform.transform.translation.x;
+ ps.pose.position.y = transform.transform.translation.y;
+ ps.pose.position.z = transform.transform.translation.z;
+ ps.pose.orientation = transform.transform.rotation;
+ m_current_pose_ptr = std::make_shared(ps);
+ return true;
+}
+
+void MpcLateralController::onOdometry(const nav_msgs::msg::Odometry::SharedPtr msg)
+{
+ m_current_odometry_ptr = msg;
+}
+
+void MpcLateralController::onSteering(
+ const autoware_auto_vehicle_msgs::msg::SteeringReport::SharedPtr msg)
+{
+ m_current_steering_ptr = msg;
+}
+
+autoware_auto_control_msgs::msg::AckermannLateralCommand
+MpcLateralController::getStopControlCommand() const
+{
+ autoware_auto_control_msgs::msg::AckermannLateralCommand cmd;
+ cmd.steering_tire_angle = static_cast(m_steer_cmd_prev);
+ cmd.steering_tire_rotation_rate = 0.0;
+ return cmd;
+}
+
+autoware_auto_control_msgs::msg::AckermannLateralCommand
+MpcLateralController::getInitialControlCommand() const
+{
+ autoware_auto_control_msgs::msg::AckermannLateralCommand cmd;
+ cmd.steering_tire_angle = m_current_steering_ptr->steering_tire_angle;
+ cmd.steering_tire_rotation_rate = 0.0;
+ return cmd;
+}
+
+bool8_t MpcLateralController::isStoppedState() const
+{
+ // Note: This function used to take into account the distance to the stop line
+ // for the stop state judgement. However, it has been removed since the steering
+ // control was turned off when approaching/exceeding the stop line on a curve or
+ // emergency stop situation and it caused large tracking error.
+ const int64_t nearest = trajectory_follower::MPCUtils::calcNearestIndex(
+ *m_current_trajectory_ptr, m_current_pose_ptr->pose);
+
+ // If the nearest index is not found, return false
+ if (nearest < 0) {
+ return false;
+ }
+
+ const float64_t current_vel = m_current_odometry_ptr->twist.twist.linear.x;
+ const float64_t target_vel =
+ m_current_trajectory_ptr->points.at(static_cast(nearest)).longitudinal_velocity_mps;
+ if (
+ std::fabs(current_vel) < m_stop_state_entry_ego_speed &&
+ std::fabs(target_vel) < m_stop_state_entry_target_speed &&
+ (!m_check_steer_converged_for_stopped_state ||
+ std::abs(m_ctrl_cmd_prev.steering_tire_angle - m_current_steering_ptr->steering_tire_angle) <
+ m_converged_steer_rad)) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+autoware_auto_control_msgs::msg::AckermannLateralCommand MpcLateralController::createCtrlCmdMsg(
+ autoware_auto_control_msgs::msg::AckermannLateralCommand ctrl_cmd)
+{
+ ctrl_cmd.stamp = node_->now();
+ // m_pub_ctrl_cmd->publish(ctrl_cmd);
+ m_steer_cmd_prev = ctrl_cmd.steering_tire_angle;
+ return ctrl_cmd;
+}
+
+void MpcLateralController::publishPredictedTraj(
+ autoware_auto_planning_msgs::msg::Trajectory & predicted_traj) const
+{
+ predicted_traj.header.stamp = node_->now();
+ predicted_traj.header.frame_id = m_current_trajectory_ptr->header.frame_id;
+ m_pub_predicted_traj->publish(predicted_traj);
+}
+
+void MpcLateralController::publishDiagnostic(
+ autoware_auto_system_msgs::msg::Float32MultiArrayDiagnostic & diagnostic) const
+{
+ diagnostic.diag_header.data_stamp = node_->now();
+ diagnostic.diag_header.name = std::string("linear-MPC lateral controller");
+ m_pub_diagnostic->publish(diagnostic);
+}
+
+// void MpcLateralController::initTimer(float64_t period_s)
+// {
+// const auto period_ns = std::chrono::duration_cast(
+// std::chrono::duration(period_s));
+// m_timer = rclcpp::create_timer(
+// this, node_->get_clock(), period_ns, std::bind(&MpcLateralController::onTimer, this));
+// }
+
+void MpcLateralController::declareMPCparameters()
+{
+ m_mpc.m_param.prediction_horizon = node_->declare_parameter("mpc_prediction_horizon");
+ m_mpc.m_param.prediction_dt = node_->declare_parameter("mpc_prediction_dt");
+ m_mpc.m_param.weight_lat_error = node_->declare_parameter("mpc_weight_lat_error");
+ m_mpc.m_param.weight_heading_error =
+ node_->declare_parameter("mpc_weight_heading_error");
+ m_mpc.m_param.weight_heading_error_squared_vel =
+ node_->declare_parameter("mpc_weight_heading_error_squared_vel");
+ m_mpc.m_param.weight_steering_input =
+ node_->declare_parameter("mpc_weight_steering_input");
+ m_mpc.m_param.weight_steering_input_squared_vel =
+ node_->declare_parameter("mpc_weight_steering_input_squared_vel");
+ m_mpc.m_param.weight_lat_jerk = node_->declare_parameter("mpc_weight_lat_jerk");
+ m_mpc.m_param.weight_steer_rate = node_->declare_parameter("mpc_weight_steer_rate");
+ m_mpc.m_param.weight_steer_acc = node_->declare_parameter("mpc_weight_steer_acc");
+ m_mpc.m_param.low_curvature_weight_lat_error =
+ node_->declare_parameter("mpc_low_curvature_weight_lat_error");
+ m_mpc.m_param.low_curvature_weight_heading_error =
+ node_->declare_parameter("mpc_low_curvature_weight_heading_error");
+ m_mpc.m_param.low_curvature_weight_heading_error_squared_vel =
+ node_->declare_parameter("mpc_low_curvature_weight_heading_error_squared_vel");
+ m_mpc.m_param.low_curvature_weight_steering_input =
+ node_->declare_parameter("mpc_low_curvature_weight_steering_input");
+ m_mpc.m_param.low_curvature_weight_steering_input_squared_vel =
+ node_->declare_parameter("mpc_low_curvature_weight_steering_input_squared_vel");
+ m_mpc.m_param.low_curvature_weight_lat_jerk =
+ node_->declare_parameter("mpc_low_curvature_weight_lat_jerk");
+ m_mpc.m_param.low_curvature_weight_steer_rate =
+ node_->declare_parameter("mpc_low_curvature_weight_steer_rate");
+ m_mpc.m_param.low_curvature_weight_steer_acc =
+ node_->declare_parameter("mpc_low_curvature_weight_steer_acc");
+ m_mpc.m_param.low_curvature_thresh_curvature =
+ node_->declare_parameter("mpc_low_curvature_thresh_curvature");
+ m_mpc.m_param.weight_terminal_lat_error =
+ node_->declare_parameter("mpc_weight_terminal_lat_error");
+ m_mpc.m_param.weight_terminal_heading_error =
+ node_->declare_parameter("mpc_weight_terminal_heading_error");
+ m_mpc.m_param.zero_ff_steer_deg = node_->declare_parameter("mpc_zero_ff_steer_deg");
+ m_mpc.m_param.acceleration_limit = node_->declare_parameter("mpc_acceleration_limit");
+ m_mpc.m_param.velocity_time_constant =
+ node_->declare_parameter("mpc_velocity_time_constant");
+}
+
+rcl_interfaces::msg::SetParametersResult MpcLateralController::paramCallback(
+ const std::vector & parameters)
+{
+ rcl_interfaces::msg::SetParametersResult result;
+ result.successful = true;
+ result.reason = "success";
+
+ // strong exception safety wrt MPCParam
+ trajectory_follower::MPCParam param = m_mpc.m_param;
+ try {
+ update_param(parameters, "mpc_prediction_horizon", param.prediction_horizon);
+ update_param(parameters, "mpc_prediction_dt", param.prediction_dt);
+ update_param(parameters, "mpc_weight_lat_error", param.weight_lat_error);
+ update_param(parameters, "mpc_weight_heading_error", param.weight_heading_error);
+ update_param(
+ parameters, "mpc_weight_heading_error_squared_vel", param.weight_heading_error_squared_vel);
+ update_param(parameters, "mpc_weight_steering_input", param.weight_steering_input);
+ update_param(
+ parameters, "mpc_weight_steering_input_squared_vel", param.weight_steering_input_squared_vel);
+ update_param(parameters, "mpc_weight_lat_jerk", param.weight_lat_jerk);
+ update_param(parameters, "mpc_weight_steer_rate", param.weight_steer_rate);
+ update_param(parameters, "mpc_weight_steer_acc", param.weight_steer_acc);
+ update_param(
+ parameters, "mpc_low_curvature_weight_lat_error", param.low_curvature_weight_lat_error);
+ update_param(
+ parameters, "mpc_low_curvature_weight_heading_error",
+ param.low_curvature_weight_heading_error);
+ update_param(
+ parameters, "mpc_low_curvature_weight_heading_error_squared_vel",
+ param.low_curvature_weight_heading_error_squared_vel);
+ update_param(
+ parameters, "mpc_low_curvature_weight_steering_input",
+ param.low_curvature_weight_steering_input);
+ update_param(
+ parameters, "mpc_low_curvature_weight_steering_input_squared_vel",
+ param.low_curvature_weight_steering_input_squared_vel);
+ update_param(
+ parameters, "mpc_low_curvature_weight_lat_jerk", param.low_curvature_weight_lat_jerk);
+ update_param(
+ parameters, "mpc_low_curvature_weight_steer_rate", param.low_curvature_weight_steer_rate);
+ update_param(
+ parameters, "mpc_low_curvature_weight_steer_acc", param.low_curvature_weight_steer_acc);
+ update_param(
+ parameters, "mpc_low_curvature_thresh_curvature", param.low_curvature_thresh_curvature);
+ update_param(parameters, "mpc_weight_terminal_lat_error", param.weight_terminal_lat_error);
+ update_param(
+ parameters, "mpc_weight_terminal_heading_error", param.weight_terminal_heading_error);
+ update_param(parameters, "mpc_zero_ff_steer_deg", param.zero_ff_steer_deg);
+ update_param(parameters, "mpc_acceleration_limit", param.acceleration_limit);
+ update_param(parameters, "mpc_velocity_time_constant", param.velocity_time_constant);
+
+ // initialize input buffer
+ update_param(parameters, "input_delay", param.input_delay);
+ const float64_t delay_step = std::round(param.input_delay / m_mpc.m_ctrl_period);
+ const float64_t delay = delay_step * m_mpc.m_ctrl_period;
+ if (param.input_delay != delay) {
+ param.input_delay = delay;
+ m_mpc.m_input_buffer = std::deque(static_cast(delay_step), 0.0);
+ }
+
+ // transaction succeeds, now assign values
+ m_mpc.m_param = param;
+ } catch (const rclcpp::exceptions::InvalidParameterTypeException & e) {
+ result.successful = false;
+ result.reason = e.what();
+ }
+
+ return result;
+}
+
+bool8_t MpcLateralController::isValidTrajectory(
+ const autoware_auto_planning_msgs::msg::Trajectory & traj) const
+{
+ for (const auto & p : traj.points) {
+ if (
+ !isfinite(p.pose.position.x) || !isfinite(p.pose.position.y) ||
+ !isfinite(p.pose.orientation.w) || !isfinite(p.pose.orientation.x) ||
+ !isfinite(p.pose.orientation.y) || !isfinite(p.pose.orientation.z) ||
+ !isfinite(p.longitudinal_velocity_mps) || !isfinite(p.lateral_velocity_mps) ||
+ !isfinite(p.lateral_velocity_mps) || !isfinite(p.heading_rate_rps) ||
+ !isfinite(p.front_wheel_angle_rad) || !isfinite(p.rear_wheel_angle_rad)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+} // namespace trajectory_follower
+} // namespace control
+} // namespace motion
+} // namespace autoware
diff --git a/control/trajectory_follower/src/pid_longitudinal_controller.cpp b/control/trajectory_follower/src/pid_longitudinal_controller.cpp
new file mode 100644
index 0000000000000..80c84475b5552
--- /dev/null
+++ b/control/trajectory_follower/src/pid_longitudinal_controller.cpp
@@ -0,0 +1,963 @@
+// Copyright 2021 Tier IV, Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "trajectory_follower/pid_longitudinal_controller.hpp"
+
+#include "motion_common/motion_common.hpp"
+#include "motion_common/trajectory_common.hpp"
+#include "time_utils/time_utils.hpp"
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace autoware
+{
+namespace motion
+{
+namespace control
+{
+namespace trajectory_follower
+{
+PidLongitudinalController::PidLongitudinalController(rclcpp::Node * node)
+: node_{node}, logger_{node->get_logger()}, clock_{node->get_clock()}
+{
+ using std::placeholders::_1;
+
+ // parameters timer
+ m_longitudinal_ctrl_period = node_->get_parameter("ctrl_period").as_double();
+
+ m_wheel_base = vehicle_info_util::VehicleInfoUtil(*node_).getVehicleInfo().wheel_base_m;
+
+ // parameters for delay compensation
+ m_delay_compensation_time =
+ node_->declare_parameter("delay_compensation_time"); // [s]
+
+ // parameters to enable functions
+ m_enable_smooth_stop = node_->declare_parameter("enable_smooth_stop");
+ m_enable_overshoot_emergency = node_->declare_parameter("enable_overshoot_emergency");
+ m_enable_slope_compensation = node_->declare_parameter("enable_slope_compensation");
+ m_enable_keep_stopped_until_steer_convergence =
+ node_->declare_parameter("enable_keep_stopped_until_steer_convergence");
+
+ // parameters for state transition
+ {
+ auto & p = m_state_transition_params;
+ // drive
+ p.drive_state_stop_dist = node_->declare_parameter("drive_state_stop_dist"); // [m]
+ p.drive_state_offset_stop_dist =
+ node_->declare_parameter("drive_state_offset_stop_dist"); // [m]
+ // stopping
+ p.stopping_state_stop_dist =
+ node_->declare_parameter("stopping_state_stop_dist"); // [m]
+ p.stopped_state_entry_duration_time =
+ node_->declare_parameter("stopped_state_entry_duration_time"); // [s]
+ // stop
+ p.stopped_state_entry_vel =
+ node_->declare_parameter("stopped_state_entry_vel"); // [m/s]
+ p.stopped_state_entry_acc =
+ node_->declare_parameter("stopped_state_entry_acc"); // [m/s²]
+ // emergency
+ p.emergency_state_overshoot_stop_dist =
+ node_->declare_parameter("emergency_state_overshoot_stop_dist"); // [m]
+ p.emergency_state_traj_trans_dev =
+ node_->declare_parameter("emergency_state_traj_trans_dev"); // [m]
+ p.emergency_state_traj_rot_dev =
+ node_->declare_parameter("emergency_state_traj_rot_dev"); // [m]
+ }
+
+ // parameters for drive state
+ {
+ // initialize PID gain
+ const float64_t kp{node_->declare_parameter("kp")};
+ const float64_t ki{node_->declare_parameter("ki")};
+ const float64_t kd{node_->declare_parameter("kd")};
+ m_pid_vel.setGains(kp, ki, kd);
+
+ // initialize PID limits
+ const float64_t max_pid{node_->declare_parameter("max_out")}; // [m/s^2]
+ const float64_t min_pid{node_->declare_parameter("min_out")}; // [m/s^2]
+ const float64_t max_p{node_->declare_parameter("max_p_effort")}; // [m/s^2]
+ const float64_t min_p{node_->declare_parameter("min_p_effort")}; // [m/s^2]
+ const float64_t max_i{node_->declare_parameter("max_i_effort")}; // [m/s^2]
+ const float64_t min_i{node_->declare_parameter("min_i_effort")}; // [m/s^2]
+ const float64_t max_d{node_->declare_parameter("max_d_effort")}; // [m/s^2]
+ const float64_t min_d{node_->declare_parameter("min_d_effort")}; // [m/s^2]
+ m_pid_vel.setLimits(max_pid, min_pid, max_p, min_p, max_i, min_i, max_d, min_d);
+
+ // set lowpass filter for vel error and pitch
+ const float64_t lpf_vel_error_gain{node_->declare_parameter("lpf_vel_error_gain")};
+ m_lpf_vel_error =
+ std::make_shared(0.0, lpf_vel_error_gain);
+
+ m_current_vel_threshold_pid_integrate =
+ node_->declare_parameter("current_vel_threshold_pid_integration"); // [m/s]
+
+ m_enable_brake_keeping_before_stop =
+ node_->declare_parameter("enable_brake_keeping_before_stop"); // [-]
+ m_brake_keeping_acc = node_->declare_parameter("brake_keeping_acc"); // [m/s^2]
+ }
+
+ // parameters for smooth stop state
+ {
+ const float64_t max_strong_acc{
+ node_->declare_parameter("smooth_stop_max_strong_acc")}; // [m/s^2]
+ const float64_t min_strong_acc{
+ node_->declare_parameter("smooth_stop_min_strong_acc")}; // [m/s^2]
+ const float64_t weak_acc{
+ node_->declare_parameter("smooth_stop_weak_acc")}; // [m/s^2]
+ const float64_t weak_stop_acc{
+ node_->declare_parameter("smooth_stop_weak_stop_acc")}; // [m/s^2]
+ const float64_t strong_stop_acc{
+ node_->declare_parameter("smooth_stop_strong_stop_acc")}; // [m/s^2]
+
+ const float64_t max_fast_vel{
+ node_->declare_parameter("smooth_stop_max_fast_vel")}; // [m/s]
+ const float64_t min_running_vel{
+ node_->declare_parameter("smooth_stop_min_running_vel")}; // [m/s]
+ const float64_t min_running_acc{
+ node_->declare_parameter("smooth_stop_min_running_acc")}; // [m/s^2]
+ const float64_t weak_stop_time{
+ node_->declare_parameter("smooth_stop_weak_stop_time")}; // [s]
+
+ const float64_t weak_stop_dist{
+ node_->declare_parameter("smooth_stop_weak_stop_dist")}; // [m]
+ const float64_t strong_stop_dist{
+ node_->declare_parameter("smooth_stop_strong_stop_dist")}; // [m]
+
+ m_smooth_stop.setParams(
+ max_strong_acc, min_strong_acc, weak_acc, weak_stop_acc, strong_stop_acc, max_fast_vel,
+ min_running_vel, min_running_acc, weak_stop_time, weak_stop_dist, strong_stop_dist);
+ }
+
+ // parameters for stop state
+ {
+ auto & p = m_stopped_state_params;
+ p.vel = node_->declare_parameter("stopped_vel"); // [m/s]
+ p.acc = node_->declare_parameter("stopped_acc"); // [m/s^2]
+ p.jerk = node_->declare_parameter("stopped_jerk"); // [m/s^3]
+ }
+
+ // parameters for emergency state
+ {
+ auto & p = m_emergency_state_params;
+ p.vel = node_->declare_parameter("emergency_vel"); // [m/s]
+ p.acc = node_->declare_parameter("emergency_acc"); // [m/s^2]
+ p.jerk = node_->declare_parameter("emergency_jerk"); // [m/s^3]
+ }
+
+ // parameters for acceleration limit
+ m_max_acc = node_->declare_parameter("max_acc"); // [m/s^2]
+ m_min_acc = node_->declare_parameter("min_acc"); // [m/s^2]
+
+ // parameters for jerk limit
+ m_max_jerk = node_->declare_parameter("max_jerk"); // [m/s^3]
+ m_min_jerk = node_->declare_parameter("min_jerk"); // [m/s^3]
+
+ // parameters for slope compensation
+ m_use_traj_for_pitch = node_->declare_parameter("use_trajectory_for_pitch_calculation");
+ const float64_t lpf_pitch_gain{node_->declare_parameter("lpf_pitch_gain")};
+ m_lpf_pitch = std::make_shared(0.0, lpf_pitch_gain);
+ m_max_pitch_rad = node_->declare_parameter("max_pitch_rad"); // [rad]
+ m_min_pitch_rad = node_->declare_parameter("min_pitch_rad"); // [rad]
+
+ // subscriber, publisher
+ m_sub_current_velocity = node_->create_subscription(
+ "~/input/current_odometry", rclcpp::QoS{1},
+ std::bind(&PidLongitudinalController::callbackCurrentVelocity, this, _1));
+ m_sub_trajectory = node_->create_subscription(
+ "~/input/current_trajectory", rclcpp::QoS{1},
+ std::bind(&PidLongitudinalController::callbackTrajectory, this, _1));
+ m_pub_control_cmd = node_->create_publisher(
+ "~/output/longitudinal_control_cmd", rclcpp::QoS{1});
+ m_pub_slope =
+ node_->create_publisher(
+ "~/output/slope_angle", rclcpp::QoS{1});
+ m_pub_debug =
+ node_->create_publisher(
+ "~/output/longitudinal_diagnostic", rclcpp::QoS{1});
+
+ // Timer
+ // {
+ // const auto period_ns = std::chrono::duration_cast(
+ // std::chrono::duration(m_longitudinal_ctrl_period));
+ // m_timer_control = rclcpp::create_timer(
+ // this, get_clock(), period_ns, std::bind(&PidLongitudinalController::callbackTimerControl,
+ // this));
+ // }
+
+ // set parameter callback
+ m_set_param_res = node_->add_on_set_parameters_callback(
+ std::bind(&PidLongitudinalController::paramCallback, this, _1));
+
+ // set lowpass filter for acc
+ m_lpf_acc = std::make_shared(0.0, 0.2);
+}
+
+void PidLongitudinalController::callbackCurrentVelocity(
+ const nav_msgs::msg::Odometry::ConstSharedPtr msg)
+{
+ if (m_current_velocity_ptr) {
+ m_prev_velocity_ptr = m_current_velocity_ptr;
+ }
+ m_current_velocity_ptr = std::make_shared(*msg);
+}
+
+void PidLongitudinalController::callbackTrajectory(
+ const autoware_auto_planning_msgs::msg::Trajectory::ConstSharedPtr msg)
+{
+ if (!trajectory_follower::longitudinal_utils::isValidTrajectory(*msg)) {
+ RCLCPP_ERROR_THROTTLE(logger_, *clock_, 3000, "received invalid trajectory. ignore.");
+ return;
+ }
+
+ if (msg->points.size() < 2) {
+ RCLCPP_WARN_THROTTLE(logger_, *clock_, 3000, "Unexpected trajectory size < 2. Ignored.");
+ return;
+ }
+
+ m_trajectory_ptr = std::make_shared(*msg);
+}
+
+rcl_interfaces::msg::SetParametersResult PidLongitudinalController::paramCallback(
+ const std::vector & parameters)
+{
+ auto update_param = [&](const std::string & name, float64_t & v) {
+ auto it = std::find_if(
+ parameters.cbegin(), parameters.cend(),
+ [&name](const rclcpp::Parameter & parameter) { return parameter.get_name() == name; });
+ if (it != parameters.cend()) {
+ v = it->as_double();
+ return true;
+ }
+ return false;
+ };
+
+ // delay compensation
+ update_param("delay_compensation_time", m_delay_compensation_time);
+
+ // state transition
+ {
+ auto & p = m_state_transition_params;
+ update_param("drive_state_stop_dist", p.drive_state_stop_dist);
+ update_param("stopping_state_stop_dist", p.stopping_state_stop_dist);
+ update_param("stopped_state_entry_duration_time", p.stopped_state_entry_duration_time);
+ update_param("stopped_state_entry_vel", p.stopped_state_entry_vel);
+ update_param("stopped_state_entry_acc", p.stopped_state_entry_acc);
+ update_param("emergency_state_overshoot_stop_dist", p.emergency_state_overshoot_stop_dist);
+ update_param("emergency_state_traj_trans_dev", p.emergency_state_traj_trans_dev);
+ update_param("emergency_state_traj_rot_dev", p.emergency_state_traj_rot_dev);
+ }
+
+ // drive state
+ {
+ float64_t kp{node_->get_parameter("kp").as_double()};
+ float64_t ki{node_->get_parameter("ki").as_double()};
+ float64_t kd{node_->get_parameter("kd").as_double()};
+ update_param("kp", kp);
+ update_param("ki", ki);
+ update_param("kd", kd);
+ m_pid_vel.setGains(kp, ki, kd);
+
+ float64_t max_pid{node_->get_parameter("max_out").as_double()};
+ float64_t min_pid{node_->get_parameter("min_out").as_double()};
+ float64_t max_p{node_->get_parameter("max_p_effort").as_double()};
+ float64_t min_p{node_->get_parameter("min_p_effort").as_double()};
+ float64_t max_i{node_->get_parameter("max_i_effort").as_double()};
+ float64_t min_i{node_->get_parameter("min_i_effort").as_double()};
+ float64_t max_d{node_->get_parameter("max_d_effort").as_double()};
+ float64_t min_d{node_->get_parameter("min_d_effort").as_double()};
+ update_param("max_out", max_pid);
+ update_param("min_out", min_pid);
+ update_param("max_p_effort", max_p);
+ update_param("min_p_effort", min_p);
+ update_param("max_i_effort", max_i);
+ update_param("min_i_effort", min_i);
+ update_param("max_d_effort", max_d);
+ update_param("min_d_effort", min_d);
+ m_pid_vel.setLimits(max_pid, min_pid, max_p, min_p, max_i, min_i, max_d, min_d);
+
+ update_param("current_vel_threshold_pid_integration", m_current_vel_threshold_pid_integrate);
+ }
+
+ // stopping state
+ {
+ float64_t max_strong_acc{node_->get_parameter("smooth_stop_max_strong_acc").as_double()};
+ float64_t min_strong_acc{node_->get_parameter("smooth_stop_min_strong_acc").as_double()};
+ float64_t weak_acc{node_->get_parameter("smooth_stop_weak_acc").as_double()};
+ float64_t weak_stop_acc{node_->get_parameter("smooth_stop_weak_stop_acc").as_double()};
+ float64_t strong_stop_acc{node_->get_parameter("smooth_stop_strong_stop_acc").as_double()};
+ float64_t max_fast_vel{node_->get_parameter("smooth_stop_max_fast_vel").as_double()};
+ float64_t min_running_vel{node_->get_parameter("smooth_stop_min_running_vel").as_double()};
+ float64_t min_running_acc{node_->get_parameter("smooth_stop_min_running_acc").as_double()};
+ float64_t weak_stop_time{node_->get_parameter("smooth_stop_weak_stop_time").as_double()};
+ float64_t weak_stop_dist{node_->get_parameter("smooth_stop_weak_stop_dist").as_double()};
+ float64_t strong_stop_dist{node_->get_parameter("smooth_stop_strong_stop_dist").as_double()};
+ update_param("smooth_stop_max_strong_acc", max_strong_acc);
+ update_param("smooth_stop_min_strong_acc", min_strong_acc);
+ update_param("smooth_stop_weak_acc", weak_acc);
+ update_param("smooth_stop_weak_stop_acc", weak_stop_acc);
+ update_param("smooth_stop_strong_stop_acc", strong_stop_acc);
+ update_param("smooth_stop_max_fast_vel", max_fast_vel);
+ update_param("smooth_stop_min_running_vel", min_running_vel);
+ update_param("smooth_stop_min_running_acc", min_running_acc);
+ update_param("smooth_stop_weak_stop_time", weak_stop_time);
+ update_param("smooth_stop_weak_stop_dist", weak_stop_dist);
+ update_param("smooth_stop_strong_stop_dist", strong_stop_dist);
+ m_smooth_stop.setParams(
+ max_strong_acc, min_strong_acc, weak_acc, weak_stop_acc, strong_stop_acc, max_fast_vel,
+ min_running_vel, min_running_acc, weak_stop_time, weak_stop_dist, strong_stop_dist);
+ }
+
+ // stop state
+ {
+ auto & p = m_stopped_state_params;
+ update_param("stopped_vel", p.vel);
+ update_param("stopped_acc", p.acc);
+ update_param("stopped_jerk", p.jerk);
+ }
+
+ // emergency state
+ {
+ auto & p = m_emergency_state_params;
+ update_param("emergency_vel", p.vel);
+ update_param("emergency_acc", p.acc);
+ update_param("emergency_jerk", p.jerk);
+ }
+
+ // acceleration limit
+ update_param("min_acc", m_min_acc);
+
+ // jerk limit
+ update_param("max_jerk", m_max_jerk);
+ update_param("min_jerk", m_min_jerk);
+
+ // slope compensation
+ update_param("max_pitch_rad", m_max_pitch_rad);
+ update_param("min_pitch_rad", m_min_pitch_rad);
+
+ rcl_interfaces::msg::SetParametersResult result;
+ result.successful = true;
+ result.reason = "success";
+ return result;
+}
+
+LongitudinalOutput PidLongitudinalController::run()
+{
+ // wait for initial pointers
+ if (
+ !m_current_velocity_ptr || !m_prev_velocity_ptr || !m_trajectory_ptr ||
+ !m_tf_buffer.canTransform(m_trajectory_ptr->header.frame_id, "base_link", tf2::TimePointZero)) {
+ LongitudinalOutput output;
+ return output; // todo
+ }
+
+ // get current ego pose
+ geometry_msgs::msg::TransformStamped tf =
+ m_tf_buffer.lookupTransform(m_trajectory_ptr->header.frame_id, "base_link", tf2::TimePointZero);
+
+ // calculate current pose and control data
+ geometry_msgs::msg::Pose current_pose;
+ current_pose.position.x = tf.transform.translation.x;
+ current_pose.position.y = tf.transform.translation.y;
+ current_pose.position.z = tf.transform.translation.z;
+ current_pose.orientation = tf.transform.rotation;
+
+ const auto control_data = getControlData(current_pose);
+
+ // self pose is far from trajectory
+ if (control_data.is_far_from_trajectory) {
+ m_control_state = ControlState::EMERGENCY; // update control state
+ const Motion raw_ctrl_cmd = calcEmergencyCtrlCmd(control_data.dt); // calculate control command
+ m_prev_raw_ctrl_cmd = raw_ctrl_cmd;
+ const auto cmd_msg =
+ createCtrlCmdMsg(raw_ctrl_cmd, control_data.current_motion.vel); // create control command
+ publishDebugData(raw_ctrl_cmd, control_data); // publish debug data
+ LongitudinalOutput output;
+ output.control_cmd = cmd_msg;
+ return output;
+ }
+
+ // update control state
+ m_control_state = updateControlState(m_control_state, control_data);
+
+ // calculate control command
+ const Motion ctrl_cmd = calcCtrlCmd(m_control_state, current_pose, control_data);
+
+ // publish control command
+ const auto cmd_msg = createCtrlCmdMsg(ctrl_cmd, control_data.current_motion.vel);
+ LongitudinalOutput output;
+ output.control_cmd = cmd_msg;
+
+ // publish debug data
+ publishDebugData(ctrl_cmd, control_data);
+
+ return output;
+}
+
+PidLongitudinalController::ControlData PidLongitudinalController::getControlData(
+ const geometry_msgs::msg::Pose & current_pose)
+{
+ ControlData control_data{};
+
+ // dt
+ control_data.dt = getDt();
+
+ // current velocity and acceleration
+ control_data.current_motion = getCurrentMotion();
+
+ // nearest idx
+ const float64_t max_dist = m_state_transition_params.emergency_state_traj_trans_dev;
+ const float64_t max_yaw = m_state_transition_params.emergency_state_traj_rot_dev;
+ const auto nearest_idx_opt =
+ motion_common::findNearestIndex(m_trajectory_ptr->points, current_pose, max_dist, max_yaw);
+
+ // return here if nearest index is not found
+ if (!nearest_idx_opt) {
+ control_data.is_far_from_trajectory = true;
+ return control_data;
+ }
+ control_data.nearest_idx = *nearest_idx_opt;
+
+ // shift
+ control_data.shift = getCurrentShift(control_data.nearest_idx);
+ if (control_data.shift != m_prev_shift) {
+ m_pid_vel.reset();
+ }
+ m_prev_shift = control_data.shift;
+
+ // distance to stopline
+ control_data.stop_dist = trajectory_follower::longitudinal_utils::calcStopDistance(
+ current_pose.position, *m_trajectory_ptr);
+
+ // pitch
+ const float64_t raw_pitch =
+ trajectory_follower::longitudinal_utils::getPitchByPose(current_pose.orientation);
+ const float64_t traj_pitch = trajectory_follower::longitudinal_utils::getPitchByTraj(
+ *m_trajectory_ptr, control_data.nearest_idx, m_wheel_base);
+ control_data.slope_angle = m_use_traj_for_pitch ? traj_pitch : m_lpf_pitch->filter(raw_pitch);
+ updatePitchDebugValues(control_data.slope_angle, traj_pitch, raw_pitch);
+
+ return control_data;
+}
+
+PidLongitudinalController::Motion PidLongitudinalController::calcEmergencyCtrlCmd(
+ const float64_t dt) const
+{
+ // These accelerations are without slope compensation
+ const auto & p = m_emergency_state_params;
+ const float64_t vel = trajectory_follower::longitudinal_utils::applyDiffLimitFilter(
+ p.vel, m_prev_raw_ctrl_cmd.vel, dt, p.acc);
+ const float64_t acc = trajectory_follower::longitudinal_utils::applyDiffLimitFilter(
+ p.acc, m_prev_raw_ctrl_cmd.acc, dt, p.jerk);
+
+ auto clock = rclcpp::Clock{RCL_ROS_TIME};
+ RCLCPP_ERROR_THROTTLE(logger_, clock, 3000, "[Emergency stop] vel: %3.3f, acc: %3.3f", vel, acc);
+
+ return Motion{vel, acc};
+}
+
+PidLongitudinalController::ControlState PidLongitudinalController::updateControlState(
+ const ControlState current_control_state, const ControlData & control_data)
+{
+ const float64_t current_vel = control_data.current_motion.vel;
+ const float64_t current_acc = control_data.current_motion.acc;
+ const float64_t stop_dist = control_data.stop_dist;
+
+ // flags for state transition
+ const auto & p = m_state_transition_params;
+
+ const bool8_t departure_condition_from_stopping =
+ stop_dist > p.drive_state_stop_dist + p.drive_state_offset_stop_dist;
+ const bool8_t departure_condition_from_stopped = stop_dist > p.drive_state_stop_dist;
+ const bool8_t keep_stopped_condition = !lateral_sync_data_.is_steer_converged;
+
+ const bool8_t stopping_condition = stop_dist < p.stopping_state_stop_dist;
+ if (
+ std::fabs(current_vel) > p.stopped_state_entry_vel ||
+ std::fabs(current_acc) > p.stopped_state_entry_acc) {
+ m_last_running_time = std::make_shared(rclcpp::Clock{RCL_ROS_TIME}.now());
+ }
+ const bool8_t stopped_condition =
+ m_last_running_time ? (rclcpp::Clock{RCL_ROS_TIME}.now() - *m_last_running_time).seconds() >
+ p.stopped_state_entry_duration_time
+ : false;
+
+ const bool8_t emergency_condition =
+ m_enable_overshoot_emergency && stop_dist < -p.emergency_state_overshoot_stop_dist;
+
+ // transit state
+ if (current_control_state == ControlState::DRIVE) {
+ if (emergency_condition) {
+ return ControlState::EMERGENCY;
+ }
+
+ if (m_enable_smooth_stop) {
+ if (stopping_condition) {
+ // predictions after input time delay
+ const float64_t pred_vel_in_target =
+ predictedVelocityInTargetPoint(control_data.current_motion, m_delay_compensation_time);
+ const float64_t pred_stop_dist =
+ control_data.stop_dist -
+ 0.5 * (pred_vel_in_target + current_vel) * m_delay_compensation_time;
+ m_smooth_stop.init(pred_vel_in_target, pred_stop_dist);
+ return ControlState::STOPPING;
+ }
+ } else {
+ if (stopped_condition && !departure_condition_from_stopped) {
+ return ControlState::STOPPED;
+ }
+ }
+ } else if (current_control_state == ControlState::STOPPING) {
+ if (emergency_condition) {
+ return ControlState::EMERGENCY;
+ }
+
+ if (stopped_condition) {
+ return ControlState::STOPPED;
+ }
+
+ if (departure_condition_from_stopping) {
+ m_pid_vel.reset();
+ m_lpf_vel_error->reset(0.0);
+ // prevent the car from taking a long time to start to move
+ m_prev_ctrl_cmd.acc = std::max(0.0, m_prev_ctrl_cmd.acc);
+ return ControlState::DRIVE;
+ }
+ } else if (current_control_state == ControlState::STOPPED) {
+ if (
+ departure_condition_from_stopped &&
+ (!m_enable_keep_stopped_until_steer_convergence || !keep_stopped_condition)) {
+ m_pid_vel.reset();
+ m_lpf_vel_error->reset(0.0);
+ // prevent the car from taking a long time to start to move
+ m_prev_ctrl_cmd.acc = std::max(0.0, m_prev_ctrl_cmd.acc);
+ return ControlState::DRIVE;
+ }
+ } else if (m_control_state == ControlState::EMERGENCY) {
+ if (stopped_condition && !emergency_condition) {
+ return ControlState::STOPPED;
+ }
+ }
+
+ return current_control_state;
+}
+
+PidLongitudinalController::Motion PidLongitudinalController::calcCtrlCmd(
+ const ControlState & current_control_state, const geometry_msgs::msg::Pose & current_pose,
+ const ControlData & control_data)
+{
+ const size_t nearest_idx = control_data.nearest_idx;
+ const float64_t current_vel = control_data.current_motion.vel;
+ const float64_t current_acc = control_data.current_motion.acc;
+
+ // velocity and acceleration command
+ Motion raw_ctrl_cmd{};
+ Motion target_motion{};
+ if (current_control_state == ControlState::DRIVE) {
+ const auto target_pose = trajectory_follower::longitudinal_utils::calcPoseAfterTimeDelay(
+ current_pose, m_delay_compensation_time, current_vel);
+ const auto target_interpolated_point =
+ calcInterpolatedTargetValue(*m_trajectory_ptr, target_pose.position, nearest_idx);
+ target_motion = Motion{
+ target_interpolated_point.longitudinal_velocity_mps,
+ target_interpolated_point.acceleration_mps2};
+
+ target_motion = keepBrakeBeforeStop(*m_trajectory_ptr, target_motion, nearest_idx);
+
+ const float64_t pred_vel_in_target =
+ predictedVelocityInTargetPoint(control_data.current_motion, m_delay_compensation_time);
+ m_debug_values.setValues(
+ trajectory_follower::DebugValues::TYPE::PREDICTED_VEL, pred_vel_in_target);
+
+ raw_ctrl_cmd.vel = target_motion.vel;
+ raw_ctrl_cmd.acc = applyVelocityFeedback(target_motion, control_data.dt, pred_vel_in_target);
+ RCLCPP_DEBUG(
+ logger_,
+ "[feedback control] vel: %3.3f, acc: %3.3f, dt: %3.3f, v_curr: %3.3f, v_ref: %3.3f "
+ "feedback_ctrl_cmd.ac: %3.3f",
+ raw_ctrl_cmd.vel, raw_ctrl_cmd.acc, control_data.dt, current_vel, target_motion.vel,
+ raw_ctrl_cmd.acc);
+ } else if (current_control_state == ControlState::STOPPING) {
+ raw_ctrl_cmd.acc = m_smooth_stop.calculate(
+ control_data.stop_dist, current_vel, current_acc, m_vel_hist, m_delay_compensation_time);
+ raw_ctrl_cmd.vel = m_stopped_state_params.vel;
+
+ RCLCPP_DEBUG(
+ logger_, "[smooth stop]: Smooth stopping. vel: %3.3f, acc: %3.3f", raw_ctrl_cmd.vel,
+ raw_ctrl_cmd.acc);
+ } else if (current_control_state == ControlState::STOPPED) {
+ // This acceleration is without slope compensation
+ const auto & p = m_stopped_state_params;
+ raw_ctrl_cmd.vel = p.vel;
+ raw_ctrl_cmd.acc = trajectory_follower::longitudinal_utils::applyDiffLimitFilter(
+ p.acc, m_prev_raw_ctrl_cmd.acc, control_data.dt, p.jerk);
+
+ RCLCPP_DEBUG(logger_, "[Stopped]. vel: %3.3f, acc: %3.3f", raw_ctrl_cmd.vel, raw_ctrl_cmd.acc);
+ } else if (current_control_state == ControlState::EMERGENCY) {
+ raw_ctrl_cmd = calcEmergencyCtrlCmd(control_data.dt);
+ }
+
+ // store acceleration without slope compensation
+ m_prev_raw_ctrl_cmd = raw_ctrl_cmd;
+
+ // apply slope compensation and filter acceleration and jerk
+ const float64_t filtered_acc_cmd = calcFilteredAcc(raw_ctrl_cmd.acc, control_data);
+ const Motion filtered_ctrl_cmd{raw_ctrl_cmd.vel, filtered_acc_cmd};
+
+ // update debug visualization
+ updateDebugVelAcc(target_motion, current_pose, control_data);
+
+ return filtered_ctrl_cmd;
+}
+
+// Do not use nearest_idx here
+autoware_auto_control_msgs::msg::LongitudinalCommand PidLongitudinalController::createCtrlCmdMsg(
+ const Motion & ctrl_cmd, float64_t current_vel)
+{
+ // publish control command
+ autoware_auto_control_msgs::msg::LongitudinalCommand cmd{};
+ cmd.stamp = rclcpp::Clock{RCL_ROS_TIME}.now();
+ cmd.speed = static_cast(ctrl_cmd.vel);
+ cmd.acceleration = static_cast(ctrl_cmd.acc);
+ // m_pub_control_cmd->publish(cmd);
+
+ // store current velocity history
+ m_vel_hist.push_back({rclcpp::Clock{RCL_ROS_TIME}.now(), current_vel});
+ while (m_vel_hist.size() > static_cast(0.5 / m_longitudinal_ctrl_period)) {
+ m_vel_hist.erase(m_vel_hist.begin());
+ }
+
+ m_prev_ctrl_cmd = ctrl_cmd;
+
+ return cmd;
+}
+
+void PidLongitudinalController::publishDebugData(
+ const Motion & ctrl_cmd, const ControlData & control_data)
+{
+ using trajectory_follower::DebugValues;
+ // set debug values
+ m_debug_values.setValues(DebugValues::TYPE::DT, control_data.dt);
+ m_debug_values.setValues(DebugValues::TYPE::CALCULATED_ACC, control_data.current_motion.acc);
+ m_debug_values.setValues(DebugValues::TYPE::SHIFT, static_cast(control_data.shift));
+ m_debug_values.setValues(DebugValues::TYPE::STOP_DIST, control_data.stop_dist);
+ m_debug_values.setValues(
+ DebugValues::TYPE::CONTROL_STATE, static_cast(m_control_state));
+ m_debug_values.setValues(DebugValues::TYPE::ACC_CMD_PUBLISHED, ctrl_cmd.acc);
+
+ // publish debug values
+ autoware_auto_system_msgs::msg::Float32MultiArrayDiagnostic debug_msg{};
+ debug_msg.diag_header.data_stamp = rclcpp::Clock{RCL_ROS_TIME}.now();
+ for (const auto & v : m_debug_values.getValues()) {
+ debug_msg.diag_array.data.push_back(
+ static_cast(v));
+ }
+ m_pub_debug->publish(debug_msg);
+
+ // slope angle
+ autoware_auto_system_msgs::msg::Float32MultiArrayDiagnostic slope_msg{};
+ slope_msg.diag_header.data_stamp = rclcpp::Clock{RCL_ROS_TIME}.now();
+ slope_msg.diag_array.data.push_back(
+ static_cast(control_data.slope_angle));
+ m_pub_slope->publish(slope_msg);
+}
+
+float64_t PidLongitudinalController::getDt()
+{
+ float64_t dt;
+ if (!m_prev_control_time) {
+ dt = m_longitudinal_ctrl_period;
+ m_prev_control_time = std::make_shared(rclcpp::Clock{RCL_ROS_TIME}.now());
+ } else {
+ dt = (rclcpp::Clock{RCL_ROS_TIME}.now() - *m_prev_control_time).seconds();
+ *m_prev_control_time = rclcpp::Clock{RCL_ROS_TIME}.now();
+ }
+ const float64_t max_dt = m_longitudinal_ctrl_period * 2.0;
+ const float64_t min_dt = m_longitudinal_ctrl_period * 0.5;
+ return std::max(std::min(dt, max_dt), min_dt);
+}
+
+PidLongitudinalController::Motion PidLongitudinalController::getCurrentMotion() const
+{
+ const float64_t dv =
+ m_current_velocity_ptr->twist.twist.linear.x - m_prev_velocity_ptr->twist.twist.linear.x;
+ const float64_t dt = std::max(
+ (rclcpp::Time(m_current_velocity_ptr->header.stamp) -
+ rclcpp::Time(m_prev_velocity_ptr->header.stamp))
+ .seconds(),
+ 1e-03);
+ const float64_t accel = dv / dt;
+
+ const float64_t current_vel = m_current_velocity_ptr->twist.twist.linear.x;
+ const float64_t current_acc = m_lpf_acc->filter(accel);
+
+ return Motion{current_vel, current_acc};
+}
+
+enum PidLongitudinalController::Shift PidLongitudinalController::getCurrentShift(
+ const size_t nearest_idx) const
+{
+ constexpr float64_t epsilon = 1e-5;
+
+ const float64_t target_vel = m_trajectory_ptr->points.at(nearest_idx).longitudinal_velocity_mps;
+
+ if (target_vel > epsilon) {
+ return Shift::Forward;
+ } else if (target_vel < -epsilon) {
+ return Shift::Reverse;
+ }
+
+ return m_prev_shift;
+}
+
+float64_t PidLongitudinalController::calcFilteredAcc(
+ const float64_t raw_acc, const ControlData & control_data)
+{
+ using trajectory_follower::DebugValues;
+ const float64_t acc_max_filtered = ::motion::motion_common::clamp(raw_acc, m_min_acc, m_max_acc);
+ m_debug_values.setValues(DebugValues::TYPE::ACC_CMD_ACC_LIMITED, acc_max_filtered);
+
+ // store ctrl cmd without slope filter
+ storeAccelCmd(acc_max_filtered);
+
+ const float64_t acc_slope_filtered =
+ applySlopeCompensation(acc_max_filtered, control_data.slope_angle, control_data.shift);
+ m_debug_values.setValues(DebugValues::TYPE::ACC_CMD_SLOPE_APPLIED, acc_slope_filtered);
+
+ // This jerk filter must be applied after slope compensation
+ const float64_t acc_jerk_filtered = trajectory_follower::longitudinal_utils::applyDiffLimitFilter(
+ acc_slope_filtered, m_prev_ctrl_cmd.acc, control_data.dt, m_max_jerk, m_min_jerk);
+ m_debug_values.setValues(DebugValues::TYPE::ACC_CMD_JERK_LIMITED, acc_jerk_filtered);
+
+ return acc_jerk_filtered;
+}
+
+void PidLongitudinalController::storeAccelCmd(const float64_t accel)
+{
+ if (m_control_state == ControlState::DRIVE) {
+ // convert format
+ autoware_auto_control_msgs::msg::LongitudinalCommand cmd;
+ cmd.stamp = rclcpp::Clock{RCL_ROS_TIME}.now();
+ cmd.acceleration = static_cast(accel);
+
+ // store published ctrl cmd
+ m_ctrl_cmd_vec.emplace_back(cmd);
+ } else {
+ // reset command
+ m_ctrl_cmd_vec.clear();
+ }
+
+ // remove unused ctrl cmd
+ if (m_ctrl_cmd_vec.size() <= 2) {
+ return;
+ }
+ if (
+ (rclcpp::Clock{RCL_ROS_TIME}.now() - m_ctrl_cmd_vec.at(1).stamp).seconds() >
+ m_delay_compensation_time) {
+ m_ctrl_cmd_vec.erase(m_ctrl_cmd_vec.begin());
+ }
+}
+
+float64_t PidLongitudinalController::applySlopeCompensation(
+ const float64_t input_acc, const float64_t pitch, const Shift shift) const
+{
+ if (!m_enable_slope_compensation) {
+ return input_acc;
+ }
+ const float64_t pitch_limited = std::min(std::max(pitch, m_min_pitch_rad), m_max_pitch_rad);
+
+ // Acceleration command is always positive independent of direction (= shift) when car is running
+ float64_t sign = (shift == Shift::Forward) ? -1 : (shift == Shift::Reverse ? 1 : 0);
+ float64_t compensated_acc = input_acc + sign * 9.81 * std::sin(pitch_limited);
+ return compensated_acc;
+}
+
+PidLongitudinalController::Motion PidLongitudinalController::keepBrakeBeforeStop(
+ const autoware_auto_planning_msgs::msg::Trajectory & traj, const Motion & target_motion,
+ const size_t nearest_idx) const
+{
+ Motion output_motion = target_motion;
+
+ if (m_enable_brake_keeping_before_stop == false) {
+ return output_motion;
+ }
+ // const auto stop_idx = tier4_autoware_utils::searchZeroVelocityIndex(traj.points);
+ const auto stop_idx = motion_common::searchZeroVelocityIndex(traj.points);
+ if (!stop_idx) {
+ return output_motion;
+ }
+
+ float64_t min_acc_before_stop = std::numeric_limits::max();
+ size_t min_acc_idx = std::numeric_limits::max();
+ for (int i = static_cast(*stop_idx); i >= 0; --i) {
+ const auto ui = static_cast(i);
+ if (traj.points.at(ui).acceleration_mps2 > static_cast(min_acc_before_stop)) {
+ break;
+ }
+ min_acc_before_stop = traj.points.at(ui).acceleration_mps2;
+ min_acc_idx = ui;
+ }
+
+ const float64_t brake_keeping_acc = std::max(m_brake_keeping_acc, min_acc_before_stop);
+ if (nearest_idx >= min_acc_idx && target_motion.acc > brake_keeping_acc) {
+ output_motion.acc = brake_keeping_acc;
+ }
+
+ return output_motion;
+}
+
+autoware_auto_planning_msgs::msg::TrajectoryPoint
+PidLongitudinalController::calcInterpolatedTargetValue(
+ const autoware_auto_planning_msgs::msg::Trajectory & traj,
+ const geometry_msgs::msg::Point & point, const size_t nearest_idx) const
+{
+ if (traj.points.size() == 1) {
+ return traj.points.at(0);
+ }
+
+ // If the current position is not within the reference trajectory, enable the edge value.
+ // Else, apply linear interpolation
+ if (nearest_idx == 0) {
+ if (motion_common::calcSignedArcLength(traj.points, point, 0) > 0) {
+ return traj.points.at(0);
+ }
+ }
+ if (nearest_idx == traj.points.size() - 1) {
+ if (motion_common::calcSignedArcLength(traj.points, point, traj.points.size() - 1) < 0) {
+ return traj.points.at(traj.points.size() - 1);
+ }
+ }
+
+ // apply linear interpolation
+ return trajectory_follower::longitudinal_utils::lerpTrajectoryPoint(traj.points, point);
+}
+
+float64_t PidLongitudinalController::predictedVelocityInTargetPoint(
+ const Motion current_motion, const float64_t delay_compensation_time) const
+{
+ const float64_t current_vel = current_motion.vel;
+ const float64_t current_acc = current_motion.acc;
+
+ if (std::fabs(current_vel) < 1e-01) { // when velocity is low, no prediction
+ return current_vel;
+ }
+
+ const float64_t current_vel_abs = std::fabs(current_vel);
+ if (m_ctrl_cmd_vec.size() == 0) {
+ const float64_t pred_vel = current_vel + current_acc * delay_compensation_time;
+ // avoid to change sign of current_vel and pred_vel
+ return pred_vel > 0 ? std::copysign(pred_vel, current_vel) : 0.0;
+ }
+
+ float64_t pred_vel = current_vel_abs;
+
+ const auto past_delay_time =
+ rclcpp::Clock{RCL_ROS_TIME}.now() - rclcpp::Duration::from_seconds(delay_compensation_time);
+ for (std::size_t i = 0; i < m_ctrl_cmd_vec.size(); ++i) {
+ if (
+ (rclcpp::Clock{RCL_ROS_TIME}.now() - m_ctrl_cmd_vec.at(i).stamp).seconds() <
+ m_delay_compensation_time) {
+ if (i == 0) {
+ // size of m_ctrl_cmd_vec is less than m_delay_compensation_time
+ pred_vel = current_vel_abs + static_cast(m_ctrl_cmd_vec.at(i).acceleration) *
+ delay_compensation_time;
+ return pred_vel > 0 ? std::copysign(pred_vel, current_vel) : 0.0;
+ }
+ // add velocity to accel * dt
+ const float64_t acc = m_ctrl_cmd_vec.at(i - 1).acceleration;
+ const auto curr_time_i = rclcpp::Time(m_ctrl_cmd_vec.at(i).stamp);
+ const float64_t time_to_next_acc = std::min(
+ (curr_time_i - rclcpp::Time(m_ctrl_cmd_vec.at(i - 1).stamp)).seconds(),
+ (curr_time_i - past_delay_time).seconds());
+ pred_vel += acc * time_to_next_acc;
+ }
+ }
+
+ const float64_t last_acc = m_ctrl_cmd_vec.at(m_ctrl_cmd_vec.size() - 1).acceleration;
+ const float64_t time_to_current =
+ (rclcpp::Clock{RCL_ROS_TIME}.now() - m_ctrl_cmd_vec.at(m_ctrl_cmd_vec.size() - 1).stamp)
+ .seconds();
+ pred_vel += last_acc * time_to_current;
+
+ // avoid to change sign of current_vel and pred_vel
+ return pred_vel > 0 ? std::copysign(pred_vel, current_vel) : 0.0;
+}
+
+float64_t PidLongitudinalController::applyVelocityFeedback(
+ const Motion target_motion, const float64_t dt, const float64_t current_vel)
+{
+ using trajectory_follower::DebugValues;
+ const float64_t current_vel_abs = std::fabs(current_vel);
+ const float64_t target_vel_abs = std::fabs(target_motion.vel);
+ const bool8_t enable_integration = (current_vel_abs > m_current_vel_threshold_pid_integrate);
+ const float64_t error_vel_filtered = m_lpf_vel_error->filter(target_vel_abs - current_vel_abs);
+
+ std::vector pid_contributions(3);
+ const float64_t pid_acc =
+ m_pid_vel.calculate(error_vel_filtered, dt, enable_integration, pid_contributions);
+ const float64_t feedback_acc = target_motion.acc + pid_acc;
+
+ m_debug_values.setValues(DebugValues::TYPE::ACC_CMD_PID_APPLIED, feedback_acc);
+ m_debug_values.setValues(DebugValues::TYPE::ERROR_VEL_FILTERED, error_vel_filtered);
+ m_debug_values.setValues(
+ DebugValues::TYPE::ACC_CMD_FB_P_CONTRIBUTION, pid_contributions.at(0)); // P
+ m_debug_values.setValues(
+ DebugValues::TYPE::ACC_CMD_FB_I_CONTRIBUTION, pid_contributions.at(1)); // I
+ m_debug_values.setValues(
+ DebugValues::TYPE::ACC_CMD_FB_D_CONTRIBUTION, pid_contributions.at(2)); // D
+
+ return feedback_acc;
+}
+
+void PidLongitudinalController::updatePitchDebugValues(
+ const float64_t pitch, const float64_t traj_pitch, const float64_t raw_pitch)
+{
+ using trajectory_follower::DebugValues;
+ const float64_t to_degrees = (180.0 / static_cast(autoware::common::types::PI));
+ m_debug_values.setValues(DebugValues::TYPE::PITCH_LPF_RAD, pitch);
+ m_debug_values.setValues(DebugValues::TYPE::PITCH_LPF_DEG, pitch * to_degrees);
+ m_debug_values.setValues(DebugValues::TYPE::PITCH_RAW_RAD, raw_pitch);
+ m_debug_values.setValues(DebugValues::TYPE::PITCH_RAW_DEG, raw_pitch * to_degrees);
+ m_debug_values.setValues(DebugValues::TYPE::PITCH_RAW_TRAJ_RAD, traj_pitch);
+ m_debug_values.setValues(DebugValues::TYPE::PITCH_RAW_TRAJ_DEG, traj_pitch * to_degrees);
+}
+
+void PidLongitudinalController::updateDebugVelAcc(
+ const Motion & target_motion, const geometry_msgs::msg::Pose & current_pose,
+ const ControlData & control_data)
+{
+ using trajectory_follower::DebugValues;
+ const float64_t current_vel = control_data.current_motion.vel;
+ const size_t nearest_idx = control_data.nearest_idx;
+
+ const auto interpolated_point =
+ calcInterpolatedTargetValue(*m_trajectory_ptr, current_pose.position, nearest_idx);
+
+ m_debug_values.setValues(DebugValues::TYPE::CURRENT_VEL, current_vel);
+ m_debug_values.setValues(DebugValues::TYPE::TARGET_VEL, target_motion.vel);
+ m_debug_values.setValues(DebugValues::TYPE::TARGET_ACC, target_motion.acc);
+ m_debug_values.setValues(
+ DebugValues::TYPE::NEAREST_VEL, interpolated_point.longitudinal_velocity_mps);
+ m_debug_values.setValues(DebugValues::TYPE::NEAREST_ACC, interpolated_point.acceleration_mps2);
+ m_debug_values.setValues(DebugValues::TYPE::ERROR_VEL, target_motion.vel - current_vel);
+}
+
+} // namespace trajectory_follower
+} // namespace control
+} // namespace motion
+} // namespace autoware
diff --git a/control/trajectory_follower_nodes/CMakeLists.txt b/control/trajectory_follower_nodes/CMakeLists.txt
index 7996ac0713107..1275072cb86e4 100644
--- a/control/trajectory_follower_nodes/CMakeLists.txt
+++ b/control/trajectory_follower_nodes/CMakeLists.txt
@@ -46,6 +46,18 @@ rclcpp_components_register_node(${LATLON_MUXER_NODE}
EXECUTABLE ${LATLON_MUXER_NODE}_exe
)
+set(CONTROLLER_NODE controller_node)
+ament_auto_add_library(${CONTROLLER_NODE} SHARED
+include/trajectory_follower_nodes/controller_node.hpp
+ src/controller_node.cpp
+)
+
+target_compile_options(${CONTROLLER_NODE} PRIVATE -Wno-error=old-style-cast)
+rclcpp_components_register_node(${CONTROLLER_NODE}
+ PLUGIN "autoware::motion::control::trajectory_follower_nodes::Controller"
+ EXECUTABLE ${CONTROLLER_NODE}_exe
+)
+
if(BUILD_TESTING)
set(TRAJECTORY_FOLLOWER_NODES_TEST test_trajectory_follower_nodes)
ament_add_ros_isolated_gtest(${TRAJECTORY_FOLLOWER_NODES_TEST}
@@ -57,10 +69,16 @@ if(BUILD_TESTING)
ament_target_dependencies(${TRAJECTORY_FOLLOWER_NODES_TEST} fake_test_node)
target_link_libraries(${TRAJECTORY_FOLLOWER_NODES_TEST} ${LATLON_MUXER_NODE} ${LATERAL_CONTROLLER_NODE} ${LONGITUDINAL_CONTROLLER_NODE})
- #find_package(autoware_testing REQUIRED)
- #add_smoke_test(${PROJECT_NAME} ${LATLON_MUXER_NODE}_exe PARAM_FILENAME latlon_muxer_defaults.param.yaml)
- #add_smoke_test(${PROJECT_NAME} ${LATERAL_CONTROLLER_NODE}_exe PARAM_FILENAME lateral_controller_defaults.param.yaml)
- #add_smoke_test(${PROJECT_NAME} ${LONGITUDINAL_CONTROLLER_NODE}_exe PARAM_FILENAME longitudinal_controller_defaults.param.yaml)
+ find_package(autoware_testing REQUIRED)
+ add_smoke_test(${PROJECT_NAME} ${LATLON_MUXER_NODE}_exe
+ PARAM_FILENAMES "latlon_muxer_defaults.param.yaml"
+ )
+ add_smoke_test(${PROJECT_NAME} ${LATERAL_CONTROLLER_NODE}_exe
+ PARAM_FILENAMES "lateral_controller_defaults.param.yaml test_vehicle_info.param.yaml"
+ )
+ add_smoke_test(${PROJECT_NAME} ${LONGITUDINAL_CONTROLLER_NODE}_exe
+ PARAM_FILENAMES "longitudinal_controller_defaults.param.yaml test_vehicle_info.param.yaml"
+ )
endif()
ament_auto_package(
diff --git a/control/trajectory_follower_nodes/include/trajectory_follower_nodes/controller_node.hpp b/control/trajectory_follower_nodes/include/trajectory_follower_nodes/controller_node.hpp
new file mode 100644
index 0000000000000..73ead9b57266f
--- /dev/null
+++ b/control/trajectory_follower_nodes/include/trajectory_follower_nodes/controller_node.hpp
@@ -0,0 +1,89 @@
+// Copyright 2021 Tier IV, Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef TRAJECTORY_FOLLOWER_NODES__CONTROLLER_NODE_HPP_
+#define TRAJECTORY_FOLLOWER_NODES__CONTROLLER_NODE_HPP_
+
+#include "eigen3/Eigen/Core"
+#include "eigen3/Eigen/Geometry"
+#include "motion_common/motion_common.hpp"
+#include "motion_common/trajectory_common.hpp"
+#include "rclcpp/rclcpp.hpp"
+#include "tf2/utils.h"
+#include "tf2_ros/buffer.h"
+#include "tf2_ros/transform_listener.h"
+#include "trajectory_follower/debug_values.hpp"
+#include "trajectory_follower/lateral_controller_base.hpp"
+#include "trajectory_follower/longitudinal_controller_base.hpp"
+#include "trajectory_follower/longitudinal_controller_utils.hpp"
+#include "trajectory_follower/lowpass_filter.hpp"
+#include "trajectory_follower/pid.hpp"
+#include "trajectory_follower/smooth_stop.hpp"
+#include "vehicle_info_util/vehicle_info_util.hpp"
+
+#include "autoware_auto_control_msgs/msg/ackermann_control_command.hpp"
+#include "autoware_auto_control_msgs/msg/longitudinal_command.hpp"
+#include "autoware_auto_planning_msgs/msg/trajectory.hpp"
+#include "autoware_auto_system_msgs/msg/float32_multi_array_diagnostic.hpp"
+#include "autoware_auto_vehicle_msgs/msg/vehicle_odometry.hpp"
+#include "geometry_msgs/msg/pose_stamped.hpp"
+#include "nav_msgs/msg/odometry.hpp"
+#include "tf2_msgs/msg/tf_message.hpp"
+
+#include
+#include
+#include
+#include
+
+namespace autoware
+{
+namespace motion
+{
+namespace control
+{
+namespace trajectory_follower_nodes
+{
+using autoware::common::types::bool8_t;
+using autoware::common::types::float64_t;
+namespace trajectory_follower = ::autoware::motion::control::trajectory_follower;
+namespace motion_common = ::autoware::motion::motion_common;
+
+/// \classController
+/// \brief The node class used for generating longitudinal control commands (velocity/acceleration)
+class TRAJECTORY_FOLLOWER_PUBLIC Controller : public rclcpp::Node
+{
+public:
+ explicit Controller(const rclcpp::NodeOptions & node_options);
+
+private:
+ // ros variables
+ rclcpp::TimerBase::SharedPtr m_timer_control_;
+
+ std::shared_ptr longitudinal_controller_;
+ std::shared_ptr lateral_controller_;
+
+ rclcpp::Publisher::SharedPtr
+ m_control_cmd_pub_;
+
+ /**
+ * @brief compute control command, and publish periodically
+ */
+ void callbackTimerControl();
+};
+} // namespace trajectory_follower_nodes
+} // namespace control
+} // namespace motion
+} // namespace autoware
+
+#endif // TRAJECTORY_FOLLOWER_NODES__CONTROLLER_NODE_HPP_
diff --git a/control/trajectory_follower_nodes/param/lateral_controller_defaults.param.yaml b/control/trajectory_follower_nodes/param/lateral_controller_defaults.param.yaml
index e692fa8e14811..911af5291e3c5 100644
--- a/control/trajectory_follower_nodes/param/lateral_controller_defaults.param.yaml
+++ b/control/trajectory_follower_nodes/param/lateral_controller_defaults.param.yaml
@@ -1,7 +1,6 @@
/**:
ros__parameters:
# -- system --
- ctrl_period: 0.03 # control period [s]
traj_resample_dist: 0.1 # path resampling interval [m]
use_steer_prediction: false # flag for using steer prediction (do not use steer measurement)
admissible_position_error: 5.0 # stop mpc calculation when error is larger than the following value
@@ -56,6 +55,8 @@
# stop state: steering command is kept in the previous value in the stop state.
stop_state_entry_ego_speed: 0.001
stop_state_entry_target_speed: 0.001
+ converged_steer_rad: 0.1
+ check_steer_converged_for_stopped_state: true
# vehicle parameters
mass_kg: 2400.0
diff --git a/control/trajectory_follower_nodes/param/longitudinal_controller_defaults.param.yaml b/control/trajectory_follower_nodes/param/longitudinal_controller_defaults.param.yaml
index 129abd2680509..ee625c99de083 100644
--- a/control/trajectory_follower_nodes/param/longitudinal_controller_defaults.param.yaml
+++ b/control/trajectory_follower_nodes/param/longitudinal_controller_defaults.param.yaml
@@ -1,11 +1,11 @@
/**:
ros__parameters:
- longitudinal_ctrl_period: 0.03 # control period [s]
delay_compensation_time: 0.17
enable_smooth_stop: true
enable_overshoot_emergency: true
enable_slope_compensation: false
+ enable_keep_stopped_until_steer_convergence: true
# state transition
drive_state_stop_dist: 0.5
diff --git a/control/trajectory_follower_nodes/param/test_vehicle_info.param.yaml b/control/trajectory_follower_nodes/param/test_vehicle_info.param.yaml
index b1279b50ef04a..8941b92b4e78e 100644
--- a/control/trajectory_follower_nodes/param/test_vehicle_info.param.yaml
+++ b/control/trajectory_follower_nodes/param/test_vehicle_info.param.yaml
@@ -9,3 +9,4 @@
left_overhang: 0.1 # between left wheel center and vehicle left
right_overhang: 0.1 # between right wheel center and vehicle right
vehicle_height: 2.5
+ max_steer_angle: 0.70 # [rad]
diff --git a/control/trajectory_follower_nodes/src/controller_node.cpp b/control/trajectory_follower_nodes/src/controller_node.cpp
new file mode 100644
index 0000000000000..6061074489b16
--- /dev/null
+++ b/control/trajectory_follower_nodes/src/controller_node.cpp
@@ -0,0 +1,80 @@
+// Copyright 2021 Tier IV, Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "trajectory_follower_nodes/controller_node.hpp"
+
+#include "motion_common/motion_common.hpp"
+#include "motion_common/trajectory_common.hpp"
+#include "time_utils/time_utils.hpp"
+#include "trajectory_follower/mpc_lateral_controller.hpp"
+#include "trajectory_follower/pid_longitudinal_controller.hpp"
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace autoware
+{
+namespace motion
+{
+namespace control
+{
+namespace trajectory_follower_nodes
+{
+Controller::Controller(const rclcpp::NodeOptions & node_options) : Node("controller", node_options)
+{
+ using std::placeholders::_1;
+
+ const double m_ctrl_period = declare_parameter("ctrl_period", 0.015);
+
+ lateral_controller_ = std::make_shared(this);
+ longitudinal_controller_ = std::make_shared(this);
+
+ m_control_cmd_pub_ = create_publisher(
+ "~/output/control_cmd", rclcpp::QoS{1}.transient_local());
+
+ // Timer
+ {
+ const auto period_ns = std::chrono::duration_cast(
+ std::chrono::duration(m_ctrl_period));
+ m_timer_control_ = rclcpp::create_timer(
+ this, get_clock(), period_ns, std::bind(&Controller::callbackTimerControl, this));
+ }
+}
+
+void Controller::callbackTimerControl()
+{
+ const auto longitudinal_output = longitudinal_controller_->run();
+ const auto lateral_output = lateral_controller_->run();
+
+ longitudinal_controller_->sync(lateral_output.sync_data);
+ lateral_controller_->sync(longitudinal_output.sync_data);
+
+ autoware_auto_control_msgs::msg::AckermannControlCommand out;
+ out.stamp = this->now();
+ out.lateral = lateral_output.control_cmd;
+ out.longitudinal = longitudinal_output.control_cmd;
+ m_control_cmd_pub_->publish(out);
+}
+
+} // namespace trajectory_follower_nodes
+} // namespace control
+} // namespace motion
+} // namespace autoware
+
+#include "rclcpp_components/register_node_macro.hpp"
+RCLCPP_COMPONENTS_REGISTER_NODE(autoware::motion::control::trajectory_follower_nodes::Controller)
diff --git a/control/vehicle_cmd_gate/CMakeLists.txt b/control/vehicle_cmd_gate/CMakeLists.txt
index 886842aa7f634..309a296acc9db 100644
--- a/control/vehicle_cmd_gate/CMakeLists.txt
+++ b/control/vehicle_cmd_gate/CMakeLists.txt
@@ -15,7 +15,7 @@ rclcpp_components_register_node(vehicle_cmd_gate_node
)
if(BUILD_TESTING)
- ament_add_gtest(test_vehicle_cmd_gate
+ ament_add_ros_isolated_gtest(test_vehicle_cmd_gate
test/src/test_main.cpp
test/src/test_vehicle_cmd_filter.cpp
)
diff --git a/control/vehicle_cmd_gate/package.xml b/control/vehicle_cmd_gate/package.xml
index cb30c913ad766..7cb8b18244d18 100644
--- a/control/vehicle_cmd_gate/package.xml
+++ b/control/vehicle_cmd_gate/package.xml
@@ -26,7 +26,7 @@
tier4_vehicle_msgs
vehicle_info_util
- ament_cmake_gtest
+ ament_cmake_ros
ament_lint_auto
autoware_lint_common
diff --git a/launch/tier4_control_launch/config/trajectory_follower/lateral_controller.param.yaml b/launch/tier4_control_launch/config/trajectory_follower/lateral_controller.param.yaml
index f8a129af4d2a4..75bd287291f2a 100644
--- a/launch/tier4_control_launch/config/trajectory_follower/lateral_controller.param.yaml
+++ b/launch/tier4_control_launch/config/trajectory_follower/lateral_controller.param.yaml
@@ -2,7 +2,6 @@
ros__parameters:
# -- system --
- ctrl_period: 0.03 # control period [s]
traj_resample_dist: 0.1 # path resampling interval [m]
use_steer_prediction: false # flag for using steer prediction (do not use steer measurement)
admissible_position_error: 5.0 # stop mpc calculation when error is larger than the following value
@@ -57,6 +56,8 @@
# stop state: steering command is kept in the previous value in the stop state.
stop_state_entry_ego_speed: 0.001
stop_state_entry_target_speed: 0.001
+ converged_steer_rad: 0.1
+ check_steer_converged_for_stopped_state: true
# vehicle parameters
vehicle:
diff --git a/launch/tier4_control_launch/config/trajectory_follower/longitudinal_controller.param.yaml b/launch/tier4_control_launch/config/trajectory_follower/longitudinal_controller.param.yaml
index b3af131b2e778..31a5974333d67 100644
--- a/launch/tier4_control_launch/config/trajectory_follower/longitudinal_controller.param.yaml
+++ b/launch/tier4_control_launch/config/trajectory_follower/longitudinal_controller.param.yaml
@@ -1,11 +1,11 @@
/**:
ros__parameters:
- longitudinal_ctrl_period: 0.03 # control period [s]
delay_compensation_time: 0.17
enable_smooth_stop: true
enable_overshoot_emergency: true
enable_slope_compensation: false
+ enable_keep_stopped_until_steer_convergence: true
# state transition
drive_state_stop_dist: 0.5
diff --git a/launch/tier4_perception_launch/launch/object_recognition/prediction/prediction.launch.xml b/launch/tier4_perception_launch/launch/object_recognition/prediction/prediction.launch.xml
index 4749bd45d3e3e..fd9d1ba6f3cda 100644
--- a/launch/tier4_perception_launch/launch/object_recognition/prediction/prediction.launch.xml
+++ b/launch/tier4_perception_launch/launch/object_recognition/prediction/prediction.launch.xml
@@ -9,6 +9,6 @@
-
+
diff --git a/launch/tier4_planning_launch/launch/scenario_planning/lane_driving/motion_planning/motion_planning.launch.py b/launch/tier4_planning_launch/launch/scenario_planning/lane_driving/motion_planning/motion_planning.launch.py
index e8661322215fe..89d04bc5b3a00 100644
--- a/launch/tier4_planning_launch/launch/scenario_planning/lane_driving/motion_planning/motion_planning.launch.py
+++ b/launch/tier4_planning_launch/launch/scenario_planning/lane_driving/motion_planning/motion_planning.launch.py
@@ -92,20 +92,23 @@ def launch_setup(context, *args, **kwargs):
surround_obstacle_checker_param = yaml.safe_load(f)["/**"]["ros__parameters"]
surround_obstacle_checker_component = ComposableNode(
package="surround_obstacle_checker",
- plugin="SurroundObstacleCheckerNode",
+ plugin="surround_obstacle_checker::SurroundObstacleCheckerNode",
name="surround_obstacle_checker",
namespace="",
remappings=[
("~/output/no_start_reason", "/planning/scenario_planning/status/no_start_reason"),
("~/output/stop_reasons", "/planning/scenario_planning/status/stop_reasons"),
- ("~/output/trajectory", "surround_obstacle_checker/trajectory"),
+ ("~/output/max_velocity", "/planning/scenario_planning/max_velocity_candidates"),
+ (
+ "~/output/velocity_limit_clear_command",
+ "/planning/scenario_planning/clear_velocity_limit",
+ ),
(
"~/input/pointcloud",
"/perception/obstacle_segmentation/pointcloud",
),
("~/input/objects", "/perception/object_recognition/objects"),
("~/input/odometry", "/localization/kinematic_state"),
- ("~/input/trajectory", "obstacle_avoidance_planner/trajectory"),
],
parameters=[
surround_obstacle_checker_param,
@@ -114,22 +117,6 @@ def launch_setup(context, *args, **kwargs):
extra_arguments=[{"use_intra_process_comms": LaunchConfiguration("use_intra_process")}],
)
- # relay
- relay_component = ComposableNode(
- package="topic_tools",
- plugin="topic_tools::RelayNode",
- name="skip_surround_obstacle_check_relay",
- namespace="",
- parameters=[
- {
- "input_topic": "obstacle_avoidance_planner/trajectory",
- "output_topic": "surround_obstacle_checker/trajectory",
- "type": "autoware_auto_planning_msgs/msg/Trajectory",
- }
- ],
- extra_arguments=[{"use_intra_process_comms": LaunchConfiguration("use_intra_process")}],
- )
-
# obstacle stop planner
obstacle_stop_planner_param_path = os.path.join(
get_package_share_directory("tier4_planning_launch"),
@@ -173,7 +160,7 @@ def launch_setup(context, *args, **kwargs):
),
("~/input/objects", "/perception/object_recognition/objects"),
("~/input/odometry", "/localization/kinematic_state"),
- ("~/input/trajectory", "surround_obstacle_checker/trajectory"),
+ ("~/input/trajectory", "obstacle_avoidance_planner/trajectory"),
],
parameters=[
common_param,
@@ -202,13 +189,7 @@ def launch_setup(context, *args, **kwargs):
condition=IfCondition(LaunchConfiguration("use_surround_obstacle_check")),
)
- relay_loader = LoadComposableNodes(
- composable_node_descriptions=[relay_component],
- target_container=container,
- condition=UnlessCondition(LaunchConfiguration("use_surround_obstacle_check")),
- )
-
- group = GroupAction([container, surround_obstacle_checker_loader, relay_loader])
+ group = GroupAction([container, surround_obstacle_checker_loader])
return [group]
diff --git a/launch/tier4_planning_launch/launch/scenario_planning/lane_driving/motion_planning/motion_planning.launch.xml b/launch/tier4_planning_launch/launch/scenario_planning/lane_driving/motion_planning/motion_planning.launch.xml
index 0fa8707e4fda9..3d195185d9bd6 100644
--- a/launch/tier4_planning_launch/launch/scenario_planning/lane_driving/motion_planning/motion_planning.launch.xml
+++ b/launch/tier4_planning_launch/launch/scenario_planning/lane_driving/motion_planning/motion_planning.launch.xml
@@ -19,22 +19,11 @@
-
-
-
-
-
-
-
-
-
-
-
@@ -45,7 +34,7 @@
-
+
diff --git a/localization/ekf_localizer/CMakeLists.txt b/localization/ekf_localizer/CMakeLists.txt
index fa894c8a7b1a5..3a3edd5338a58 100644
--- a/localization/ekf_localizer/CMakeLists.txt
+++ b/localization/ekf_localizer/CMakeLists.txt
@@ -13,8 +13,8 @@ ament_auto_add_executable(ekf_localizer
ament_target_dependencies(ekf_localizer kalman_filter)
# if(BUILD_TESTING)
-# find_package(ament_cmake_gtest REQUIRED)
-# ament_add_gtest(ekf_localizer-test test/test_ekf_localizer.test
+# find_package(ament_cmake_ros REQUIRED)
+# ament_add_ros_isolated_gtest(ekf_localizer-test test/test_ekf_localizer.test
# test/src/test_ekf_localizer.cpp
# src/ekf_localizer.cpp
# src/kalman_filter/kalman_filter.cpp
diff --git a/localization/ekf_localizer/package.xml b/localization/ekf_localizer/package.xml
index c67cfaa400a0d..3e9d9735ae3bd 100644
--- a/localization/ekf_localizer/package.xml
+++ b/localization/ekf_localizer/package.xml
@@ -24,7 +24,7 @@
tier4_autoware_utils
tier4_debug_msgs
- ament_cmake_gtest
+ ament_cmake_ros
ament_lint_auto
autoware_lint_common
diff --git a/localization/stop_filter/package.xml b/localization/stop_filter/package.xml
index b4b948c236af4..47fcf3282efea 100644
--- a/localization/stop_filter/package.xml
+++ b/localization/stop_filter/package.xml
@@ -17,7 +17,7 @@
tf2
tier4_debug_msgs
- ament_cmake_gtest
+ ament_cmake_ros
ament_lint_auto
autoware_lint_common
diff --git a/map/lanelet2_extension/CMakeLists.txt b/map/lanelet2_extension/CMakeLists.txt
index d256029e4041a..709c7bdaa6858 100644
--- a/map/lanelet2_extension/CMakeLists.txt
+++ b/map/lanelet2_extension/CMakeLists.txt
@@ -62,15 +62,15 @@ target_link_libraries(autoware_lanelet2_validation
)
if(BUILD_TESTING)
- ament_add_gtest(message_conversion-test test/src/test_message_conversion.cpp)
+ ament_add_ros_isolated_gtest(message_conversion-test test/src/test_message_conversion.cpp)
target_link_libraries(message_conversion-test lanelet2_extension_lib)
- ament_add_gtest(projector-test test/src/test_projector.cpp)
+ ament_add_ros_isolated_gtest(projector-test test/src/test_projector.cpp)
target_link_libraries(projector-test lanelet2_extension_lib)
- ament_add_gtest(query-test test/src/test_query.cpp)
+ ament_add_ros_isolated_gtest(query-test test/src/test_query.cpp)
target_link_libraries(query-test lanelet2_extension_lib)
- ament_add_gtest(regulatory_elements-test test/src/test_regulatory_elements.cpp)
+ ament_add_ros_isolated_gtest(regulatory_elements-test test/src/test_regulatory_elements.cpp)
target_link_libraries(regulatory_elements-test lanelet2_extension_lib)
- ament_add_gtest(utilities-test test/src/test_utilities.cpp)
+ ament_add_ros_isolated_gtest(utilities-test test/src/test_utilities.cpp)
target_link_libraries(utilities-test lanelet2_extension_lib)
endif()
diff --git a/map/lanelet2_extension/package.xml b/map/lanelet2_extension/package.xml
index e817b06f1be86..d46d05a7f3064 100644
--- a/map/lanelet2_extension/package.xml
+++ b/map/lanelet2_extension/package.xml
@@ -27,7 +27,7 @@
tier4_autoware_utils
visualization_msgs
- ament_cmake_gtest
+ ament_cmake_ros
ament_lint_auto
autoware_lint_common
diff --git a/mkdocs.yaml b/mkdocs.yaml
index 2bd16349b24bb..02c3bb42383e8 100644
--- a/mkdocs.yaml
+++ b/mkdocs.yaml
@@ -66,7 +66,6 @@ markdown_extensions:
- mdx_math
- mdx_truly_sane_lists:
nested_indent: 2
- - mdx_unimoji
- plantuml_markdown:
server: http://www.plantuml.com/plantuml
format: svg
diff --git a/perception/detected_object_feature_remover/package.xml b/perception/detected_object_feature_remover/package.xml
index 686c01621c546..b609ff0257f1e 100644
--- a/perception/detected_object_feature_remover/package.xml
+++ b/perception/detected_object_feature_remover/package.xml
@@ -16,7 +16,7 @@
rclcpp_components
tier4_perception_msgs
- ament_cmake_gtest
+ ament_cmake_ros
ament_lint_auto
autoware_lint_common
diff --git a/perception/image_projection_based_fusion/include/image_projection_based_fusion/debugger.hpp b/perception/image_projection_based_fusion/include/image_projection_based_fusion/debugger.hpp
index ff790894658ec..9ecd336818b59 100644
--- a/perception/image_projection_based_fusion/include/image_projection_based_fusion/debugger.hpp
+++ b/perception/image_projection_based_fusion/include/image_projection_based_fusion/debugger.hpp
@@ -38,7 +38,8 @@ using sensor_msgs::msg::RegionOfInterest;
class Debugger
{
public:
- explicit Debugger(rclcpp::Node * node_ptr, const std::size_t image_num);
+ explicit Debugger(
+ rclcpp::Node * node_ptr, const std::size_t image_num, const std::size_t image_buffer_size);
void publishImage(const std::size_t image_id, const rclcpp::Time & stamp);
@@ -57,7 +58,7 @@ class Debugger
std::vector image_subs_;
std::vector image_pubs_;
std::vector> image_buffers_;
- std::size_t image_buffer_size{5};
+ std::size_t image_buffer_size_;
};
} // namespace image_projection_based_fusion
diff --git a/perception/image_projection_based_fusion/launch/roi_cluster_fusion.launch.xml b/perception/image_projection_based_fusion/launch/roi_cluster_fusion.launch.xml
index 8fe94963ff8ca..e5824dfcff97f 100644
--- a/perception/image_projection_based_fusion/launch/roi_cluster_fusion.launch.xml
+++ b/perception/image_projection_based_fusion/launch/roi_cluster_fusion.launch.xml
@@ -24,6 +24,7 @@
+
@@ -70,6 +71,7 @@
+
diff --git a/perception/image_projection_based_fusion/launch/roi_detected_object_fusion.launch.xml b/perception/image_projection_based_fusion/launch/roi_detected_object_fusion.launch.xml
index f6466e6512a09..be981478e78a2 100644
--- a/perception/image_projection_based_fusion/launch/roi_detected_object_fusion.launch.xml
+++ b/perception/image_projection_based_fusion/launch/roi_detected_object_fusion.launch.xml
@@ -24,6 +24,7 @@
+
@@ -70,6 +71,7 @@
+
diff --git a/perception/image_projection_based_fusion/src/debugger.cpp b/perception/image_projection_based_fusion/src/debugger.cpp
index e1254fc136304..0bcfb019d93df 100644
--- a/perception/image_projection_based_fusion/src/debugger.cpp
+++ b/perception/image_projection_based_fusion/src/debugger.cpp
@@ -34,9 +34,12 @@ void drawRoiOnImage(
namespace image_projection_based_fusion
{
-Debugger::Debugger(rclcpp::Node * node_ptr, const std::size_t image_num) : node_ptr_(node_ptr)
+Debugger::Debugger(
+ rclcpp::Node * node_ptr, const std::size_t image_num, const std::size_t image_buffer_size)
+: node_ptr_(node_ptr)
{
image_buffers_.resize(image_num);
+ image_buffer_size_ = image_buffer_size;
for (std::size_t img_i = 0; img_i < image_num; ++img_i) {
auto sub = image_transport::create_subscription(
node_ptr, "input/image_raw" + std::to_string(img_i),
@@ -54,7 +57,7 @@ Debugger::Debugger(rclcpp::Node * node_ptr, const std::size_t image_num) : node_
auto pub =
image_transport::create_publisher(node_ptr, "output/image_raw" + std::to_string(img_i));
image_pubs_.push_back(pub);
- image_buffers_.at(img_i).set_capacity(image_buffer_size);
+ image_buffers_.at(img_i).set_capacity(image_buffer_size_);
}
}
diff --git a/perception/image_projection_based_fusion/src/fusion_node.cpp b/perception/image_projection_based_fusion/src/fusion_node.cpp
index 57ed245f67bd7..5d33303ca1bf9 100644
--- a/perception/image_projection_based_fusion/src/fusion_node.cpp
+++ b/perception/image_projection_based_fusion/src/fusion_node.cpp
@@ -127,7 +127,9 @@ FusionNode::FusionNode(const std::string & node_name, const rclcpp::NodeOpt
// debugger
if (declare_parameter("debug_mode", false)) {
- debugger_ = std::make_shared(this, rois_number_);
+ std::size_t image_buffer_size =
+ static_cast(declare_parameter("image_buffer_size", 15));
+ debugger_ = std::make_shared(this, rois_number_, image_buffer_size);
}
}
diff --git a/perception/lidar_apollo_instance_segmentation/CMakeLists.txt b/perception/lidar_apollo_instance_segmentation/CMakeLists.txt
index 4fee2ecdd2f3b..433999051097d 100644
--- a/perception/lidar_apollo_instance_segmentation/CMakeLists.txt
+++ b/perception/lidar_apollo_instance_segmentation/CMakeLists.txt
@@ -4,9 +4,6 @@ project(lidar_apollo_instance_segmentation)
find_package(autoware_cmake REQUIRED)
autoware_package()
-# TODO: remove (https://github.com/autowarefoundation/autoware.universe/issues/850)
-add_compile_options(-Wno-deprecated-declarations)
-
option(CUDA_VERBOSE "Verbose output of CUDA modules" OFF)
# set flags for CUDA availability
diff --git a/perception/lidar_apollo_instance_segmentation/lib/include/TrtNet.hpp b/perception/lidar_apollo_instance_segmentation/lib/include/TrtNet.hpp
index 30d560135cb4f..14c1ff6d44c63 100644
--- a/perception/lidar_apollo_instance_segmentation/lib/include/TrtNet.hpp
+++ b/perception/lidar_apollo_instance_segmentation/lib/include/TrtNet.hpp
@@ -56,13 +56,13 @@ class trtNet
}
if (!mTrtRunTime) {
- mTrtRunTime->destroy();
+ delete mTrtRunTime;
}
if (!mTrtContext) {
- mTrtContext->destroy();
+ delete mTrtContext;
}
if (!mTrtEngine) {
- mTrtEngine->destroy();
+ delete mTrtEngine;
}
}
diff --git a/perception/lidar_apollo_instance_segmentation/lib/src/TrtNet.cpp b/perception/lidar_apollo_instance_segmentation/lib/src/TrtNet.cpp
index c51adc83e07c1..0f1da4bdac8a6 100644
--- a/perception/lidar_apollo_instance_segmentation/lib/src/TrtNet.cpp
+++ b/perception/lidar_apollo_instance_segmentation/lib/src/TrtNet.cpp
@@ -100,7 +100,7 @@ trtNet::trtNet(const std::string & engineFile)
mTrtRunTime = createInferRuntime(gLogger);
assert(mTrtRunTime != nullptr);
- mTrtEngine = mTrtRunTime->deserializeCudaEngine(data.get(), length, nullptr);
+ mTrtEngine = mTrtRunTime->deserializeCudaEngine(data.get(), length);
assert(mTrtEngine != nullptr);
InitEngine();
diff --git a/perception/lidar_apollo_instance_segmentation/src/detector.cpp b/perception/lidar_apollo_instance_segmentation/src/detector.cpp
index 7d628173b2e4c..af8b29f55f340 100644
--- a/perception/lidar_apollo_instance_segmentation/src/detector.cpp
+++ b/perception/lidar_apollo_instance_segmentation/src/detector.cpp
@@ -63,17 +63,27 @@ LidarApolloInstanceSegmentation::LidarApolloInstanceSegmentation(rclcpp::Node *
const int batch_size = 1;
builder->setMaxBatchSize(batch_size);
config->setMaxWorkspaceSize(1 << 30);
- nvinfer1::ICudaEngine * engine = builder->buildEngineWithConfig(*network, *config);
- nvinfer1::IHostMemory * trt_model_stream = engine->serialize();
- assert(trt_model_stream != nullptr);
+ nvinfer1::IHostMemory * plan = builder->buildSerializedNetwork(*network, *config);
+ assert(plan != nullptr);
std::ofstream outfile(engine_file, std::ofstream::binary);
assert(!outfile.fail());
- outfile.write(reinterpret_cast(trt_model_stream->data()), trt_model_stream->size());
+ outfile.write(reinterpret_cast(plan->data()), plan->size());
outfile.close();
- network->destroy();
- parser->destroy();
- builder->destroy();
- config->destroy();
+ if (network) {
+ delete network;
+ }
+ if (parser) {
+ delete parser;
+ }
+ if (builder) {
+ delete builder;
+ }
+ if (config) {
+ delete config;
+ }
+ if (plan) {
+ delete plan;
+ }
}
net_ptr_.reset(new Tn::trtNet(engine_file));
diff --git a/perception/lidar_centerpoint/CMakeLists.txt b/perception/lidar_centerpoint/CMakeLists.txt
index 1f5c869136eb0..4f15575181348 100644
--- a/perception/lidar_centerpoint/CMakeLists.txt
+++ b/perception/lidar_centerpoint/CMakeLists.txt
@@ -4,9 +4,6 @@ project(lidar_centerpoint)
find_package(autoware_cmake REQUIRED)
autoware_package()
-# TODO: remove (https://github.com/autowarefoundation/autoware.universe/issues/850)
-add_compile_options(-Wno-deprecated-declarations -Wno-unknown-pragmas)
-
option(CUDA_VERBOSE "Verbose output of CUDA modules" OFF)
# set flags for CUDA availability
@@ -89,13 +86,13 @@ if(TRT_AVAIL AND CUDA_AVAIL AND CUDNN_AVAIL)
message(STATUS "File already exists.")
else()
message(STATUS "File hash changes. Downloading now ...")
- execute_process(COMMAND gdown --quiet https://drive.google.com//uc?id=${GFILE_ID} -O ${FILE_PATH})
+ execute_process(COMMAND gdown --quiet https://drive.google.com/uc?id=${GFILE_ID} -O ${FILE_PATH})
# file(MD5 ${FILE_PATH} DOWNLOADED_FILE_HASH) # disable to pass ci
message(STATUS "Downloaded file hash: ${DOWNLOADED_FILE_HASH}")
endif()
else()
message(STATUS "File doesn't exists. Downloading now ...")
- execute_process(COMMAND gdown --quiet https://drive.google.com//uc?id=${GFILE_ID} -O ${FILE_PATH})
+ execute_process(COMMAND gdown --quiet https://drive.google.com/uc?id=${GFILE_ID} -O ${FILE_PATH})
# file(MD5 ${FILE_PATH} DOWNLOADED_FILE_HASH) # disable to pass ci
message(STATUS "Downloaded file hash: ${DOWNLOADED_FILE_HASH}")
endif()
@@ -144,6 +141,13 @@ if(TRT_AVAIL AND CUDA_AVAIL AND CUDNN_AVAIL)
centerpoint_cuda_libraries
)
+ # To suppress unknown-pragmas error. The root-cause is CUB library in CUDA 11.6.
+ # This issue was fixed by https://github.com/NVIDIA/cub/commit/7d608bf1dc14553e2fb219eabeed80b76621b6fe
+ target_include_directories(centerpoint
+ SYSTEM PUBLIC
+ ${CUDA_INCLUDE_DIRS}
+ )
+
## node ##
ament_auto_add_library(lidar_centerpoint_component SHARED
src/node.cpp
diff --git a/perception/lidar_centerpoint/lib/include/tensorrt_wrapper.hpp b/perception/lidar_centerpoint/lib/include/tensorrt_wrapper.hpp
index dd49723a5265c..b334be9e2230b 100644
--- a/perception/lidar_centerpoint/lib/include/tensorrt_wrapper.hpp
+++ b/perception/lidar_centerpoint/lib/include/tensorrt_wrapper.hpp
@@ -29,7 +29,7 @@ struct Deleter
void operator()(T * obj) const
{
if (obj) {
- obj->destroy();
+ delete obj;
}
}
};
@@ -82,6 +82,7 @@ class TensorRTWrapper
bool createContext();
unique_ptr runtime_ = nullptr;
+ unique_ptr