moveit2
The MoveIt Motion Planning Framework for ROS 2.
Loading...
Searching...
No Matches
test_acceleration_filter.cpp
Go to the documentation of this file.
1/*********************************************************************
2 * Software License Agreement (BSD License)
3 *
4 * Copyright (c) 2024, PickNik Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
17 * * Neither the name of PickNik Inc. nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
33 *********************************************************************/
34
35#include <gtest/gtest.h>
38
39constexpr std::string_view PLANNING_GROUP_NAME = "panda_arm";
40constexpr size_t PANDA_NUM_JOINTS = 7u;
41constexpr std::string_view ROBOT_MODEL = "panda";
42
43class AccelerationFilterTest : public testing::Test
44{
45protected:
46 void SetUp() override
47 {
49 };
50
51 void setLimits(std::optional<Eigen::VectorXd> acceleration_limits)
52 {
53 const std::vector<moveit::core::JointModel*> joint_models = robot_model_->getJointModels();
54 auto joint_model_group = robot_model_->getJointModelGroup(PLANNING_GROUP_NAME.data());
55 size_t ind = 0;
56 for (auto& joint_model : joint_models)
57 {
58 if (!joint_model_group->hasJointModel(joint_model->getName()))
59 {
60 continue;
61 }
62 std::vector<moveit_msgs::msg::JointLimits> joint_bounds_msg(joint_model->getVariableBoundsMsg());
63 for (auto& joint_bound : joint_bounds_msg)
64 {
65 joint_bound.has_acceleration_limits = acceleration_limits.has_value();
66 if (joint_bound.has_acceleration_limits)
67 {
68 joint_bound.max_acceleration = acceleration_limits.value()[ind];
69 }
70 }
71 joint_model->setVariableBounds(joint_bounds_msg);
72 ind++;
73 }
74 }
75
76protected:
77 moveit::core::RobotModelPtr robot_model_;
78};
79
81{
83 rclcpp::Node::SharedPtr node = std::make_shared<rclcpp::Node>("AccelerationFilterTest");
84
85 // fail because the update_period parameter is not set
86 EXPECT_THROW(filter.initialize(node, robot_model_, PANDA_NUM_JOINTS),
87 rclcpp::exceptions::ParameterUninitializedException);
88
89 node = std::make_shared<rclcpp::Node>("AccelerationFilterTest");
90 node->declare_parameter<std::string>("planning_group_name", PLANNING_GROUP_NAME.data());
91 node->declare_parameter("update_period", 0.01);
92
93 // fail because the number of joints is wrong
94 EXPECT_FALSE(filter.initialize(node, robot_model_, 3u));
95
96 // fail because the robot does not have acceleration limits
97 setLimits({});
98 EXPECT_FALSE(filter.initialize(node, robot_model_, PANDA_NUM_JOINTS));
99
100 // succeed with acceleration limits
101 Eigen::VectorXd acceleration_limits = 1.2 * Eigen::VectorXd::Ones(PANDA_NUM_JOINTS);
102 setLimits(acceleration_limits);
103 EXPECT_TRUE(filter.initialize(node, robot_model_, PANDA_NUM_JOINTS));
104}
105
107{
109
110 rclcpp::Node::SharedPtr node = std::make_shared<rclcpp::Node>("AccelerationFilterTest");
111 node->declare_parameter<std::string>("planning_group_name", PLANNING_GROUP_NAME.data());
112 const double update_period = 1.0;
113 node->declare_parameter<double>("update_period", update_period);
114 Eigen::VectorXd acceleration_limits = 1.2 * Eigen::VectorXd::Ones(PANDA_NUM_JOINTS);
115 setLimits(acceleration_limits);
116
117 EXPECT_TRUE(filter.initialize(node, robot_model_, PANDA_NUM_JOINTS));
118
119 // fail when called with the wrong number of joints
120 Eigen::VectorXd position = Eigen::VectorXd::Zero(5);
121 Eigen::VectorXd velocity = Eigen::VectorXd::Zero(5);
122 Eigen::VectorXd acceleration = Eigen::VectorXd::Zero(5);
123 EXPECT_FALSE(filter.doSmoothing(position, velocity, acceleration));
124
125 // fail because reset was not called
126 position = Eigen::VectorXd::Zero(PANDA_NUM_JOINTS);
127 velocity = Eigen::VectorXd::Zero(PANDA_NUM_JOINTS);
128 acceleration = Eigen::VectorXd::Zero(PANDA_NUM_JOINTS);
129 EXPECT_FALSE(filter.doSmoothing(position, velocity, acceleration));
130
131 // succeed
132 filter.reset(Eigen::VectorXd::Zero(PANDA_NUM_JOINTS), Eigen::VectorXd::Zero(PANDA_NUM_JOINTS),
133 Eigen::VectorXd::Zero(PANDA_NUM_JOINTS));
134 EXPECT_TRUE(filter.doSmoothing(position, velocity, acceleration));
135
136 // succeed: apply acceleration limits
137 filter.reset(Eigen::VectorXd::Zero(PANDA_NUM_JOINTS), Eigen::VectorXd::Zero(PANDA_NUM_JOINTS),
138 Eigen::VectorXd::Zero(PANDA_NUM_JOINTS));
139 position.array() = 3.0;
140 EXPECT_TRUE(filter.doSmoothing(position, velocity, acceleration));
141 EXPECT_TRUE((position.array() - update_period * update_period * acceleration_limits.array()).matrix().norm() < 1E-3);
142
143 // succeed: apply acceleration limits
144 position.array() = 0.9;
145 filter.reset(position * 0, velocity * 0, acceleration * 0);
146 EXPECT_TRUE(filter.doSmoothing(position, velocity, acceleration));
147 EXPECT_TRUE((position.array() - 0.9).matrix().norm() < 1E-3);
148
149 // succeed: slow down
150 velocity = 10 * Eigen::VectorXd::Ones(PANDA_NUM_JOINTS);
151 filter.reset(Eigen::VectorXd::Zero(PANDA_NUM_JOINTS), velocity, Eigen::VectorXd::Zero(PANDA_NUM_JOINTS));
152 position.array() = 0.01;
153 Eigen::VectorXd expected_offset =
154 velocity.array() * update_period - update_period * update_period * acceleration_limits.array();
155 EXPECT_TRUE(filter.doSmoothing(position, velocity, acceleration));
156 EXPECT_TRUE((velocity * update_period - expected_offset).norm() < 1E-3);
157}
158
159TEST_F(AccelerationFilterTest, FilterBadAccelerationConfig)
160{
162
163 rclcpp::Node::SharedPtr node = std::make_shared<rclcpp::Node>("AccelerationFilterTest");
164 node->declare_parameter<std::string>("planning_group_name", PLANNING_GROUP_NAME.data());
165 const double update_period = 0.1;
166 node->declare_parameter<double>("update_period", update_period);
167 Eigen::VectorXd acceleration_limits = -1.0 * Eigen::VectorXd::Ones(PANDA_NUM_JOINTS);
168 setLimits(acceleration_limits);
169 EXPECT_TRUE(filter.initialize(node, robot_model_, PANDA_NUM_JOINTS));
170 Eigen::VectorXd position = Eigen::VectorXd::Zero(PANDA_NUM_JOINTS);
171 Eigen::VectorXd velocity = Eigen::VectorXd::Zero(PANDA_NUM_JOINTS);
172 Eigen::VectorXd acceleration = Eigen::VectorXd::Zero(PANDA_NUM_JOINTS);
173 EXPECT_TRUE(filter.reset(position, velocity, acceleration));
174 EXPECT_FALSE(filter.doSmoothing(position, velocity, acceleration));
175}
176
177TEST_F(AccelerationFilterTest, FilterDoSmoothRandomized)
178{
180 rclcpp::Node::SharedPtr node = std::make_shared<rclcpp::Node>("AccelerationFilterTest");
181 const double update_period = 0.1;
182 node->declare_parameter<std::string>("planning_group_name", PLANNING_GROUP_NAME.data());
183 node->declare_parameter<double>("update_period", update_period);
184 Eigen::VectorXd acceleration_limits = 1.2 * (1.0 + Eigen::VectorXd::Random(PANDA_NUM_JOINTS).array());
185 setLimits(acceleration_limits);
186 EXPECT_TRUE(filter.initialize(node, robot_model_, PANDA_NUM_JOINTS));
187
188 for (size_t iter = 0; iter < 64; ++iter)
189 {
190 acceleration_limits = 1.2 * (1.0 + Eigen::VectorXd::Random(PANDA_NUM_JOINTS).array());
191 setLimits(acceleration_limits);
192 EXPECT_TRUE(filter.initialize(node, robot_model_, PANDA_NUM_JOINTS));
193 filter.reset(Eigen::VectorXd::Zero(PANDA_NUM_JOINTS), Eigen::VectorXd::Zero(PANDA_NUM_JOINTS),
194 Eigen::VectorXd::Zero(PANDA_NUM_JOINTS));
195 Eigen::VectorXd position = Eigen::VectorXd::Random(PANDA_NUM_JOINTS);
196 Eigen::VectorXd velocity = Eigen::VectorXd::Random(PANDA_NUM_JOINTS);
197 Eigen::VectorXd acceleration = Eigen::VectorXd::Random(PANDA_NUM_JOINTS);
198 EXPECT_TRUE(filter.doSmoothing(position, velocity, acceleration));
199 }
200}
201
202int main(int argc, char** argv)
203{
204 testing::InitGoogleTest(&argc, argv);
205 rclcpp::init(argc, argv);
206 return RUN_ALL_TESTS();
207}
moveit::core::RobotModelPtr robot_model_
void setLimits(std::optional< Eigen::VectorXd > acceleration_limits)
bool initialize(rclcpp::Node::SharedPtr node, moveit::core::RobotModelConstPtr robot_model, size_t num_joints) override
bool reset(const Eigen::VectorXd &positions, const Eigen::VectorXd &velocities, const Eigen::VectorXd &accelerations) override
bool doSmoothing(Eigen::VectorXd &positions, Eigen::VectorXd &velocities, Eigen::VectorXd &accelerations) override
moveit::core::RobotModelPtr loadTestingRobotModel(const std::string &package_name, const std::string &urdf_relative_path, const std::string &srdf_relative_path)
Loads a robot model given a URDF and SRDF file in a package.
constexpr size_t PANDA_NUM_JOINTS
constexpr std::string_view ROBOT_MODEL
int main(int argc, char **argv)
TEST_F(AccelerationFilterTest, FilterInitialize)
constexpr std::string_view PLANNING_GROUP_NAME