moveit2
The MoveIt Motion Planning Framework for ROS 2.
Loading...
Searching...
No Matches
current_state_monitor_tests.cpp
Go to the documentation of this file.
1/*********************************************************************
2 * Software License Agreement (BSD License)
3 *
4 * Copyright (c) 2021, 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 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/* Author: Tyler Weaver */
36
37#include <chrono>
38#include <memory>
39#include <string>
40
41#include <gmock/gmock.h>
42#include <gtest/gtest.h>
45#include <rclcpp/rclcpp.hpp>
46#include <rclcpp/version.h>
47// For Rolling, Kilted, and newer
48#if RCLCPP_VERSION_GTE(29, 6, 0)
49#include <tf2_ros/buffer.hpp>
50// For Jazzy and older
51#else
52#include <tf2_ros/buffer.h>
53#endif
54
56{
57 MOCK_METHOD(rclcpp::Time, now, (), (const, override));
59 (const std::string& topic, planning_scene_monitor::JointStateUpdateCallback callback), (override));
61 MOCK_METHOD(std::string, getJointStateTopicName, (), (const, override));
62 MOCK_METHOD(bool, sleepFor, (const std::chrono::nanoseconds& nanoseconds), (const, override));
63 MOCK_METHOD(bool, ok, (), (const, override));
64 MOCK_METHOD(void, createStaticTfSubscription, (TfCallback callback), (override));
65 MOCK_METHOD(void, createDynamicTfSubscription, (TfCallback callback), (override));
66 MOCK_METHOD(std::string, getStaticTfTopicName, (), (const, override));
67 MOCK_METHOD(std::string, getDynamicTfTopicName, (), (const, override));
68 MOCK_METHOD(void, resetTfSubscriptions, (), (override));
69};
70
71TEST(CurrentStateMonitorTests, StartCreateSubscriptionTest)
72{
73 auto mock_middleware_handle = std::make_unique<MockMiddlewareHandle>();
74 // THEN we expect it to call createJointStateSubscription on the MiddlewareHandle
75 EXPECT_CALL(*mock_middleware_handle, createJointStateSubscription);
76
77 // GIVEN a CurrentStateMonitor
79 std::move(mock_middleware_handle), moveit::core::loadTestingRobotModel("panda"),
80 std::make_shared<tf2_ros::Buffer>(std::make_shared<rclcpp::Clock>()), false
81 };
82
83 // WHEN we start the current state monitor
84 current_state_monitor.startStateMonitor();
85}
86
87TEST(CurrentStateMonitorTests, StartActiveTest)
88{
89 // GIVEN a CurrentStateMonitor
91 std::make_unique<MockMiddlewareHandle>(), moveit::core::loadTestingRobotModel("panda"),
92 std::make_shared<tf2_ros::Buffer>(std::make_shared<rclcpp::Clock>()), false
93 };
94
95 // WHEN we start the current state monitor
96 current_state_monitor.startStateMonitor();
97
98 // THEN we expect it to be active
99 EXPECT_TRUE(current_state_monitor.isActive());
100}
101
102TEST(CurrentStateMonitorTests, StopResetSubscriptionTest)
103{
104 auto mock_middleware_handle = std::make_unique<MockMiddlewareHandle>();
105
106 // THEN we expect it to call now and resetJointStateSubscription on the MiddlewareHandle
107 EXPECT_CALL(*mock_middleware_handle, resetJointStateSubscription);
108 EXPECT_CALL(*mock_middleware_handle, now);
109
110 // GIVEN a CurrentStateMonitor that is started
112 std::move(mock_middleware_handle), moveit::core::loadTestingRobotModel("panda"),
113 std::make_shared<tf2_ros::Buffer>(std::make_shared<rclcpp::Clock>()), false
114 };
115 current_state_monitor.startStateMonitor();
116
117 // WHEN we stop the current state monitor
118 current_state_monitor.stopStateMonitor();
119}
120
121TEST(CurrentStateMonitorTests, StopNotActiveTest)
122{
123 auto mock_middleware_handle = std::make_unique<MockMiddlewareHandle>();
124
125 // GIVEN a CurrentStateMonitor that is started
127 std::move(mock_middleware_handle), moveit::core::loadTestingRobotModel("panda"),
128 std::make_shared<tf2_ros::Buffer>(std::make_shared<rclcpp::Clock>()), false
129 };
130 current_state_monitor.startStateMonitor();
131
132 // WHEN we stop the current state monitor
133 current_state_monitor.stopStateMonitor();
134
135 // THEN we expect it to not be active
136 EXPECT_FALSE(current_state_monitor.isActive());
137}
138
139TEST(CurrentStateMonitorTests, DestructStopTest)
140{
141 auto mock_middleware_handle = std::make_unique<MockMiddlewareHandle>();
142
143 // THEN we expect it to be stopped and resetJointStateSubscription and now to be called
144 EXPECT_CALL(*mock_middleware_handle, resetJointStateSubscription);
145 EXPECT_CALL(*mock_middleware_handle, now);
146
147 // GIVEN a CurrentStateMonitor that we started
148 {
150 std::move(mock_middleware_handle), moveit::core::loadTestingRobotModel("panda"),
151 std::make_shared<tf2_ros::Buffer>(std::make_shared<rclcpp::Clock>()), false
152 };
153 current_state_monitor.startStateMonitor();
154 EXPECT_TRUE(current_state_monitor.isActive());
155 }
156 // WHEN it is destructed
157}
158
159TEST(CurrentStateMonitorTests, NoModelTest)
160{
161 // GIVEN an uninitialized robot model
162 moveit::core::RobotModelPtr robot_model = nullptr;
163
164 // WHEN the CurrentStateMonitor is constructed with it
165 // THEN we expect the monitor to throw because of the invalid model
167 std::make_unique<MockMiddlewareHandle>(), robot_model,
168 std::make_shared<tf2_ros::Buffer>(std::make_shared<rclcpp::Clock>()), false),
169 std::invalid_argument);
170}
171
172TEST(CurrentStateMonitorTests, HaveCompleteStateConstructFalse)
173{
174 // GIVEN a CurrentStateMonitor
176 std::make_unique<MockMiddlewareHandle>(), moveit::core::loadTestingRobotModel("panda"),
177 std::make_shared<tf2_ros::Buffer>(std::make_shared<rclcpp::Clock>()), false
178 };
179
180 // WHEN it is constructed
181 // THEN we expect haveCompleteState to be false
182 EXPECT_FALSE(current_state_monitor.haveCompleteState());
183}
184
185TEST(CurrentStateMonitorTests, WaitForCompleteStateWaits)
186{
187 auto mock_middleware_handle = std::make_unique<MockMiddlewareHandle>();
188
189 auto nanoseconds_slept = std::chrono::nanoseconds(0);
190 ON_CALL(*mock_middleware_handle, sleepFor)
191 .WillByDefault(testing::Invoke([&](const std::chrono::nanoseconds& nanoseconds) {
192 nanoseconds_slept += nanoseconds;
193 return true;
194 }));
195
196 // GIVEN a CurrentStateMonitor
198 std::move(mock_middleware_handle), moveit::core::loadTestingRobotModel("panda"),
199 std::make_shared<tf2_ros::Buffer>(std::make_shared<rclcpp::Clock>()), false
200 };
201
202 // WHEN we wait for complete state for 1s
203 current_state_monitor.waitForCompleteState(1.0);
204
205 // THEN we expect it waited for near 1 seconds
206 EXPECT_NEAR(nanoseconds_slept.count(), 1e+9, 1e3);
207}
208
209int main(int argc, char** argv)
210{
211 ::testing::InitGoogleTest(&argc, argv);
212 return RUN_ALL_TESTS();
213}
Dependency injection class for testing the CurrentStateMonitor.
virtual std::string getJointStateTopicName() const =0
Get the joint state topic name.
virtual void createStaticTfSubscription(TfCallback callback)=0
Creates a static transform message subscription.
virtual void resetTfSubscriptions()=0
Reset the static & dynamic transform subscriptions.
virtual void resetJointStateSubscription()=0
Reset the joint state subscription.
virtual bool sleepFor(const std::chrono::nanoseconds &nanoseconds) const =0
Block for the specified amount of time.
virtual void createJointStateSubscription(const std::string &topic, JointStateUpdateCallback callback)=0
Creates a joint state subscription.
std::function< void(const tf2_msgs::msg::TFMessage::ConstSharedPtr)> TfCallback
virtual std::string getDynamicTfTopicName() const =0
Get the dynamic transform topic name.
virtual rclcpp::Time now() const =0
Get the current time.
virtual void createDynamicTfSubscription(TfCallback callback)=0
Creates a dynamic transform message subscription.
virtual bool ok() const =0
Uses rclcpp::ok to check the context status.
virtual std::string getStaticTfTopicName() const =0
Get the static transform topic name.
Monitors the joint_states topic and tf to maintain the current state of the robot.
void startStateMonitor(const std::string &joint_states_topic="joint_states")
Start monitoring joint states on a particular topic.
bool isActive() const
Check if the state monitor is started.
bool haveCompleteState() const
Query whether we have joint state information for all DOFs in the kinematic model.
void stopStateMonitor()
Stop monitoring the "joint_states" topic.
bool waitForCompleteState(double wait_time_s) const
Wait for at most wait_time_s seconds until the complete robot state is known.
int main(int argc, char **argv)
TEST(CurrentStateMonitorTests, StartCreateSubscriptionTest)
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.
std::function< void(sensor_msgs::msg::JointState::ConstSharedPtr)> JointStateUpdateCallback
MOCK_METHOD(void, resetTfSubscriptions,(),(override))
MOCK_METHOD(std::string, getDynamicTfTopicName,(),(const, override))
MOCK_METHOD(bool, ok,(),(const, override))
MOCK_METHOD(void, resetJointStateSubscription,(),(override))
MOCK_METHOD(rclcpp::Time, now,(),(const, override))
MOCK_METHOD(void, createJointStateSubscription,(const std::string &topic, planning_scene_monitor::JointStateUpdateCallback callback),(override))
MOCK_METHOD(bool, sleepFor,(const std::chrono::nanoseconds &nanoseconds),(const, override))
MOCK_METHOD(void, createStaticTfSubscription,(TfCallback callback),(override))
MOCK_METHOD(std::string, getJointStateTopicName,(),(const, override))
MOCK_METHOD(void, createDynamicTfSubscription,(TfCallback callback),(override))
MOCK_METHOD(std::string, getStaticTfTopicName,(),(const, override))