moveit2
The MoveIt Motion Planning Framework for ROS 2.
Loading...
Searching...
No Matches
test_utils.cpp
Go to the documentation of this file.
1// Copyright 2024 Intrinsic Innovation LLC.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
19#include <gtest/gtest.h>
20#include <rclcpp/version.h>
21
22#include <geometry_msgs/msg/point.hpp>
24#include <moveit_msgs/msg/joint_constraint.hpp>
25#include <moveit_msgs/msg/orientation_constraint.hpp>
26#include <moveit_msgs/msg/position_constraint.hpp>
27
28#include <tf2_ros/buffer.h>
29
30#include "../fixtures/warehouse_fixture.hpp"
31
32namespace
33{
34
35using ::testing::TestParamInfo;
36using ::testing::ValuesIn;
37
38using ::warehouse_ros::MessageCollection;
39using ::warehouse_ros::Metadata;
40using ::warehouse_ros::Query;
41
42// This test throws an exception on Humble. It is not clear why. Excluding it for now.
43#if RCLCPP_VERSION_GTE(28, 3, 3)
44TEST_F(WarehouseFixture, QueryAppendCenterWithToleranceWorks)
45{
46 MessageCollection<geometry_msgs::msg::Point> coll =
47 db_->openCollection<geometry_msgs::msg::Point>("test_db", "test_collection");
48
49 Metadata::Ptr metadata = coll.createMetadata();
50 metadata->append("test_metadata", 5.0);
51 coll.insert(geometry_msgs::msg::Point(), metadata);
52
53 Query::Ptr unrelated_query = coll.createQuery();
54 moveit_ros::trajectory_cache::queryAppendCenterWithTolerance(*unrelated_query, "unrelated_metadata", 1.0, 10.0);
55 EXPECT_TRUE(coll.queryList(unrelated_query).empty());
56
57 Query::Ptr related_query_too_low = coll.createQuery();
58 moveit_ros::trajectory_cache::queryAppendCenterWithTolerance(*related_query_too_low, "test_metadata", 4.45, 1.0);
59 EXPECT_TRUE(coll.queryList(related_query_too_low).empty());
60
61 Query::Ptr related_query_too_high = coll.createQuery();
62 moveit_ros::trajectory_cache::queryAppendCenterWithTolerance(*related_query_too_high, "test_metadata", 5.55, 1.0);
63 EXPECT_TRUE(coll.queryList(related_query_too_high).empty());
64
65 Query::Ptr related_query_in_range = coll.createQuery();
66 moveit_ros::trajectory_cache::queryAppendCenterWithTolerance(*related_query_in_range, "test_metadata", 5.0, 1.0);
67 EXPECT_EQ(coll.queryList(related_query_in_range).size(), 1);
68}
69#endif
70
71// restateInNewFrame.
72
73TEST(RestateInNewFrameTest, NoopOnNullTranslationAndRotation)
74{
75 auto tf_buffer = std::make_shared<tf2_ros::Buffer>(std::make_shared<rclcpp::Clock>(RCL_ROS_TIME));
76
78 tf_buffer, "frame_a", "frame_b", nullptr, nullptr, tf2::TimePointZero);
79
80 EXPECT_EQ(result, moveit::core::MoveItErrorCode::SUCCESS);
81}
82
83TEST(RestateInNewFrameTest, NoopOnSameFrame)
84{
85 auto tf_buffer = std::make_shared<tf2_ros::Buffer>(std::make_shared<rclcpp::Clock>(RCL_ROS_TIME));
86 geometry_msgs::msg::Point translation;
87 translation.x = 1;
88 translation.y = 2;
89 translation.z = 3;
90 geometry_msgs::msg::Quaternion rotation;
91 rotation.x = 0;
92 rotation.y = 0;
93 rotation.z = 0;
94 rotation.w = 1;
95
97 tf_buffer, "frame_a", "frame_a", &translation, &rotation, tf2::TimePointZero);
98
99 EXPECT_EQ(result, moveit::core::MoveItErrorCode::SUCCESS);
100 EXPECT_EQ(translation.x, 1);
101 EXPECT_EQ(translation.y, 2);
102 EXPECT_EQ(translation.z, 3);
103 EXPECT_EQ(rotation.x, 0);
104 EXPECT_EQ(rotation.y, 0);
105 EXPECT_EQ(rotation.z, 0);
106 EXPECT_EQ(rotation.w, 1);
107}
108
109TEST(RestateInNewFrameTest, FailsOnMissingTransform)
110{
111 auto tf_buffer = std::make_shared<tf2_ros::Buffer>(std::make_shared<rclcpp::Clock>(RCL_ROS_TIME));
112 geometry_msgs::msg::Point translation;
113 geometry_msgs::msg::Quaternion rotation;
114
116 tf_buffer, "frame_a", "frame_c", &translation, &rotation, tf2::TimePointZero);
117
118 EXPECT_NE(result, moveit::core::MoveItErrorCode::SUCCESS);
119}
120
121struct RestateInNewFrameTestCase
122{
123 std::string test_name;
124 bool translate;
125 bool rotate;
126 double expected_translation_x;
127 double expected_translation_y;
128 double expected_translation_z;
129 double expected_rotation_x;
130 double expected_rotation_y;
131 double expected_rotation_z;
132 double expected_rotation_w;
133};
134
135class RestateInNewFrameParameterizedTest : public testing::WithParamInterface<RestateInNewFrameTestCase>,
136 public testing::Test
137{
138};
139
140INSTANTIATE_TEST_SUITE_P(RestateInNewFrameParameterizedTests, RestateInNewFrameParameterizedTest,
141 ValuesIn<RestateInNewFrameTestCase>({ {
142 .test_name = "TranslateAndRotate",
143 .translate = true,
144 .rotate = true,
145 .expected_translation_x = 2,
146 .expected_translation_y = 4,
147 .expected_translation_z = 6,
148 .expected_rotation_x = 0,
149 .expected_rotation_y = 0,
150 .expected_rotation_z = 0.707,
151 .expected_rotation_w = 0.707,
152 },
153 {
154 .test_name = "NullTranslationIgnoresTranslation",
155 .translate = false,
156 .rotate = true,
157 .expected_translation_x = 1,
158 .expected_translation_y = 2,
159 .expected_translation_z = 3,
160 .expected_rotation_x = 0,
161 .expected_rotation_y = 0,
162 .expected_rotation_z = 0.707,
163 .expected_rotation_w = 0.707,
164 },
165 {
166 .test_name = "NullRotationIgnoresRotation",
167 .translate = true,
168 .rotate = false,
169 .expected_translation_x = 2,
170 .expected_translation_y = 4,
171 .expected_translation_z = 6,
172 .expected_rotation_x = 0,
173 .expected_rotation_y = 0,
174 .expected_rotation_z = 0,
175 .expected_rotation_w = 1,
176 } }),
177 [](const TestParamInfo<RestateInNewFrameParameterizedTest::ParamType>& info) {
178 return info.param.test_name;
179 });
180
181TEST_P(RestateInNewFrameParameterizedTest, RestateInNewFrame)
182{
183 auto tf_buffer = std::make_shared<tf2_ros::Buffer>(std::make_shared<rclcpp::Clock>(RCL_ROS_TIME));
184 geometry_msgs::msg::TransformStamped transform;
185 transform.header.frame_id = "frame_a";
186 transform.child_frame_id = "frame_b";
187 transform.transform.translation.x = 1;
188 transform.transform.translation.y = 2;
189 transform.transform.translation.z = 3;
190 transform.transform.rotation.x = 0;
191 transform.transform.rotation.y = 0;
192 transform.transform.rotation.z = 0.707; // 90 degree rotation about the z-axis.
193 transform.transform.rotation.w = 0.707;
194 tf_buffer->setTransform(transform, "test");
195
196 geometry_msgs::msg::Point translation;
197 translation.x = 1;
198 translation.y = 2;
199 translation.z = 3;
200
201 geometry_msgs::msg::Quaternion rotation;
202 rotation.x = 0;
203 rotation.y = 0;
204 rotation.z = 0;
205 rotation.w = 1;
206
207 RestateInNewFrameTestCase params = GetParam();
208
210 moveit_ros::trajectory_cache::restateInNewFrame(tf_buffer, /*target_frame=*/"frame_a", /*source_frame=*/"frame_b",
211 params.translate ? &translation : nullptr,
212 params.rotate ? &rotation : nullptr, tf2::TimePointZero);
213
214 EXPECT_EQ(result, moveit::core::MoveItErrorCode::SUCCESS);
215
216 if (params.translate)
217 {
218 EXPECT_EQ(translation.x, params.expected_translation_x);
219 EXPECT_EQ(translation.y, params.expected_translation_y);
220 EXPECT_EQ(translation.z, params.expected_translation_z);
221 }
222 else
223 {
224 EXPECT_EQ(translation.x, 1);
225 EXPECT_EQ(translation.y, 2);
226 EXPECT_EQ(translation.z, 3);
227 }
228
229 if (params.rotate)
230 {
231 EXPECT_NEAR(rotation.x, params.expected_rotation_x, 1e-3);
232 EXPECT_NEAR(rotation.y, params.expected_rotation_y, 1e-3);
233 EXPECT_NEAR(rotation.z, params.expected_rotation_z, 1e-3);
234 EXPECT_NEAR(rotation.w, params.expected_rotation_w, 1e-3);
235 }
236 else
237 {
238 EXPECT_EQ(rotation.x, 0);
239 EXPECT_EQ(rotation.y, 0);
240 EXPECT_EQ(rotation.z, 0);
241 EXPECT_EQ(rotation.w, 1);
242 }
243}
244
245// Other utils.
246
247TEST(TestUtils, GetExecutionTimeWorks)
248{
249 moveit_msgs::msg::RobotTrajectory trajectory;
250 trajectory.joint_trajectory.points.resize(2);
251 trajectory.joint_trajectory.points[0].time_from_start = rclcpp::Duration::from_seconds(1.0);
252 trajectory.joint_trajectory.points[1].time_from_start = rclcpp::Duration::from_seconds(2.0);
253
254 EXPECT_EQ(moveit_ros::trajectory_cache::getExecutionTime(trajectory), 2.0);
255}
256
257TEST(TestUtils, ConstraintSortingWorks)
258{
259 // Joint constraints.
260 {
261 moveit_msgs::msg::JointConstraint jc1;
262 jc1.joint_name = "joint2";
263 moveit_msgs::msg::JointConstraint jc2;
264 jc2.joint_name = "joint1";
265 std::vector<moveit_msgs::msg::JointConstraint> joint_constraints = { jc1, jc2 };
267
268 EXPECT_EQ(joint_constraints[0].joint_name, "joint1");
269 EXPECT_EQ(joint_constraints[1].joint_name, "joint2");
270 }
271
272 // Position constraints.
273 {
274 moveit_msgs::msg::PositionConstraint pc1;
275 pc1.link_name = "link2";
276 moveit_msgs::msg::PositionConstraint pc2;
277 pc2.link_name = "link1";
278 std::vector<moveit_msgs::msg::PositionConstraint> position_constraints = { pc1, pc2 };
280 EXPECT_EQ(position_constraints[0].link_name, "link1");
281 EXPECT_EQ(position_constraints[1].link_name, "link2");
282 }
283
284 // Orientation constraints.
285 {
286 moveit_msgs::msg::OrientationConstraint oc1;
287 oc1.link_name = "link2";
288 moveit_msgs::msg::OrientationConstraint oc2;
289 oc2.link_name = "link1";
290 std::vector<moveit_msgs::msg::OrientationConstraint> orientation_constraints = { oc1, oc2 };
292 EXPECT_EQ(orientation_constraints[0].link_name, "link1");
293 EXPECT_EQ(orientation_constraints[1].link_name, "link2");
294 }
295}
296
297} // namespace
298
299int main(int argc, char** argv)
300{
301 rclcpp::init(argc, argv);
302 ::testing::InitGoogleTest(&argc, argv);
303 int result = RUN_ALL_TESTS();
304 rclcpp::shutdown();
305 return result;
306}
Test fixture to spin up a node to start a warehouse_ros connection with.
a wrapper around moveit_msgs::MoveItErrorCodes to make it easier to return an error code message from...
int main(int argc, char **argv)
Utilities used by the trajectory_cache package.
void sortJointConstraints(std::vector< moveit_msgs::msg::JointConstraint > &joint_constraints)
Sorts a vector of joint constraints in-place by joint name.
Definition utils.cpp:187
double getExecutionTime(const moveit_msgs::msg::RobotTrajectory &trajectory)
Returns the execution time of the trajectory in double seconds.
Definition utils.cpp:146
moveit::core::MoveItErrorCode restateInNewFrame(const std::shared_ptr< tf2_ros::Buffer > &tf, const std::string &target_frame, const std::string &source_frame, geometry_msgs::msg::Point *translation, geometry_msgs::msg::Quaternion *rotation, const tf2::TimePoint &lookup_time=tf2::TimePointZero)
Restates a translation and rotation in a new frame.
Definition utils.cpp:88
void sortOrientationConstraints(std::vector< moveit_msgs::msg::OrientationConstraint > &orientation_constraints)
Sorts a vector of orientation constraints in-place by link name.
Definition utils.cpp:203
void sortPositionConstraints(std::vector< moveit_msgs::msg::PositionConstraint > &position_constraints)
Sorts a vector of position constraints in-place by link name.
Definition utils.cpp:195
void queryAppendCenterWithTolerance(warehouse_ros::Query &query, const std::string &name, double center, double tolerance)
Appends a range inclusive query with some tolerance about some center value.
TEST(AllValid, Instantiate)
TEST_F(BulletCollisionDetectionTester, DISABLED_ContinuousCollisionSelf)
Continuous self collision checks are not supported yet by the bullet integration.
#define INSTANTIATE_TEST_SUITE_P(...)
TEST_P(CollisionDetectorTests, Threaded)
Tests the collision detector in multiple threads.