moveit2
The MoveIt Motion Planning Framework for ROS 2.
test_servo_interface.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2020, 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 /* Author: Dave Coleman and Tyler Weaver
36  Desc: Test for the C++ interface to moveit_servo
37 */
38 
40 
41 using namespace std::chrono_literals;
42 
43 namespace moveit_servo
44 {
45 TEST_F(ServoFixture, SendTwistStampedTest)
46 {
47  auto log_time_start = node_->now();
48  ASSERT_TRUE(setupStartClient());
49  ASSERT_TRUE(setupCommandSub(servo_parameters_->command_out_type));
50  auto log_time_end = node_->now();
51  RCLCPP_INFO_STREAM(LOGGER, "Setup time: " << (log_time_end - log_time_start).seconds());
52 
53  // Start Servo
54  ASSERT_TRUE(start());
55  EXPECT_EQ(latest_status_, moveit_servo::StatusCode::NO_WARNING);
56 
57  // We want to count the number of commands Servo publishes, we need timing
58  auto time_start = node_->now();
59 
60  // Publish N messages with some time between, ensure it's less than the timeout for Servo
61  rclcpp::WallRate publish_loop_rate(test_parameters_->publish_hz);
62  size_t num_commands = 30;
63  resetNumCommands();
64  for (size_t i = 0; i < num_commands && rclcpp::ok(); ++i)
65  {
66  auto msg = std::make_unique<geometry_msgs::msg::TwistStamped>();
67  msg->header.stamp = node_->now();
68  msg->twist.linear.x = 0.1;
69  msg->twist.angular.z = 0.5;
70  pub_twist_cmd_->publish(std::move(msg));
71  publish_loop_rate.sleep();
72  }
73 
74  // Capture the time and number of received messages
75  auto time_end = node_->now();
76  auto num_received = getNumCommands();
77 
78  // Compare actual number received to expected number
79  auto num_expected = (time_end - time_start).seconds() / servo_parameters_->publish_period;
80  RCLCPP_INFO_STREAM(LOGGER, "Wait publish messages: " << (time_end - time_start).seconds());
81 
82  EXPECT_GT(num_received, 0.5 * num_expected);
83  EXPECT_LT(num_received, 1.5 * num_expected);
84 }
85 
86 TEST_F(ServoFixture, SendJointServoTest)
87 {
88  auto log_time_start = node_->now();
89  ASSERT_TRUE(setupStartClient());
90  ASSERT_TRUE(setupCommandSub(servo_parameters_->command_out_type));
91  auto log_time_end = node_->now();
92  RCLCPP_INFO_STREAM(LOGGER, "Setup time: " << (log_time_end - log_time_start).seconds());
93 
94  // Start Servo
95  ASSERT_TRUE(start());
96  EXPECT_EQ(latest_status_, moveit_servo::StatusCode::NO_WARNING);
97 
98  // We want to count the number of commands Servo publishes, we need timing
99  auto time_start = node_->now();
100 
101  // Publish N messages with some time between, ensure it's less than the timeout for Servo
102  rclcpp::WallRate publish_loop_rate(test_parameters_->publish_hz);
103  size_t num_commands = 30;
104  resetNumCommands();
105  for (size_t i = 0; i < num_commands && rclcpp::ok(); ++i)
106  {
107  auto msg = std::make_unique<control_msgs::msg::JointJog>();
108  msg->header.stamp = node_->now();
109  msg->header.frame_id = "panda_link3";
110  msg->joint_names.push_back("panda_joint1");
111  msg->velocities.push_back(0.1);
112  pub_joint_cmd_->publish(std::move(msg));
113  publish_loop_rate.sleep();
114  }
115 
116  // Capture the time and number of received messages
117  auto time_end = node_->now();
118  auto num_received = getNumCommands();
119 
120  // Compare actual number received to expected number
121  auto num_expected = (time_end - time_start).seconds() / servo_parameters_->publish_period;
122  log_time_end = node_->now();
123  RCLCPP_INFO_STREAM(LOGGER, "Wait publish messages: " << (time_end - time_start).seconds());
124 
125  EXPECT_GT(num_received, 0.5 * num_expected);
126  EXPECT_LT(num_received, 1.5 * num_expected);
127 
128  // Now let's test the Servo input going stale
129  // We expect the command we were publishing above to continue for a while, then
130  // to continually receive Servo output, but with 0 velocity/delta_position
131  log_time_start = node_->now();
132 
133  // Allow the last command to go stale and measure the output position
134  const int sleep_time = 1.5 * 1000 * servo_parameters_->incoming_command_timeout;
135  rclcpp::sleep_for(std::chrono::milliseconds(sleep_time));
136  double joint_position_first = getLatestTrajCommand().points[0].positions[0];
137 
138  // Now if we sleep a bit longer and check again, it should be the same
139  rclcpp::sleep_for(std::chrono::milliseconds(sleep_time));
140  double joint_position_later = getLatestTrajCommand().points[0].positions[0];
141  EXPECT_NEAR(joint_position_first, joint_position_later, 0.001);
142 
143  log_time_end = node_->now();
144  RCLCPP_INFO_STREAM(LOGGER, "Wait stale command: " << (log_time_end - log_time_start).seconds());
145 }
146 
147 TEST_F(ServoFixture, DynamicParameterTest)
148 {
149  ASSERT_TRUE(setupStartClient());
150 
151  // Start Servo
152  ASSERT_TRUE(start());
153  EXPECT_EQ(latest_status_, moveit_servo::StatusCode::NO_WARNING);
154 
155  auto set_parameters_client =
156  node_->create_client<rcl_interfaces::srv::SetParameters>(test_parameters_->servo_node_name + "/set_parameters");
157 
158  while (!set_parameters_client->service_is_ready())
159  {
160  if (!rclcpp::ok())
161  {
162  ASSERT_TRUE(false) << "Interrupted while waiting for the service. Exiting.";
163  }
164  RCLCPP_INFO(LOGGER, "set_parameters_client service not yet available, waiting again...");
165  rclcpp::sleep_for(500ms);
166  }
167 
168  // Test changing dynamic parameter
169  auto request = std::make_shared<rcl_interfaces::srv::SetParameters::Request>();
170 
171  // This is a dynamic parameter
172  request->parameters.push_back(
173  rclcpp::Parameter("moveit_servo.robot_link_command_frame", "panda_link4").to_parameter_msg());
174 
175  // This is not even a parameter that is declared (it should fail)
176  request->parameters.push_back(rclcpp::Parameter("moveit_servo.not_set_parameter", 1.0).to_parameter_msg());
177 
178  auto set_parameter_response = set_parameters_client->async_send_request(request).get();
179 
180  // The first one should have succeeded
181  ASSERT_TRUE(set_parameter_response->results[0].successful) << set_parameter_response->results[0].reason;
182 
183  // This parameter should fail to set.
184  ASSERT_FALSE(set_parameter_response->results[1].successful)
185  << "`not_set_parameter` is not a parameter and should fail to be set";
186 }
187 } // namespace moveit_servo
188 
189 int main(int argc, char** argv)
190 {
191  rclcpp::init(argc, argv);
192  ::testing::InitGoogleTest(&argc, argv);
193 
194  int ret = RUN_ALL_TESTS();
195  rclcpp::shutdown();
196  return ret;
197 }
TEST_F(ServoFixture, DynamicParameterTest)
int main(int argc, char **argv)