servo_cpp_interface_test.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2020, PickNik LLC
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 LLC 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 
39 // C++
40 #include <string>
41 
42 // ROS
43 #include <ros/ros.h>
44 
45 // Testing
46 #include <gtest/gtest.h>
47 
48 // Servo
50 #include <moveit_servo/servo.h>
51 
52 static const std::string LOGNAME = "servo_cpp_interface_test";
53 static constexpr double LARGEST_ALLOWABLE_PANDA_VEL = 2.8710; // to test joint velocity limit enforcement
54 
55 namespace moveit_servo
56 {
57 class ServoFixture : public ::testing::Test
58 {
59 public:
60  void SetUp() override
61  {
62  // Wait for several key topics / parameters
63  ros::topic::waitForMessage<sensor_msgs::JointState>("/joint_states");
64  while (!nh_.hasParam("/robot_description") && ros::ok())
65  {
66  ros::Duration(0.1).sleep();
67  }
68 
69  // Load the planning scene monitor
70  planning_scene_monitor_ = std::make_shared<planning_scene_monitor::PlanningSceneMonitor>("robot_description");
71  planning_scene_monitor_->startSceneMonitor();
72  planning_scene_monitor_->startStateMonitor();
73  planning_scene_monitor_->startWorldGeometryMonitor(
76  false /* skip octomap monitor */);
77 
78  // Create moveit_servo
79  servo_ = std::make_shared<Servo>(nh_, planning_scene_monitor_);
80  }
81  void TearDown() override
82  {
83  }
84 
86  {
87  auto msg = ros::topic::waitForMessage<std_msgs::Int8>(servo_->getParameters().status_topic, nh_, ros::Duration(1));
88  return static_cast<bool>(msg);
89  }
90 
91 protected:
92  ros::NodeHandle nh_{ "~" };
93  planning_scene_monitor::PlanningSceneMonitorPtr planning_scene_monitor_;
95 }; // class ServoFixture
96 
97 TEST_F(ServoFixture, StartStopTest)
98 {
99  servo_->start();
100  EXPECT_TRUE(waitForFirstStatus()) << "Timeout waiting for Status message";
101  servo_->setPaused(true);
102 
103  ros::Duration(1.0).sleep();
104 
105  // Start and stop again
106  servo_->setPaused(false);
107  EXPECT_TRUE(waitForFirstStatus()) << "Timeout waiting for Status message";
108  servo_->setPaused(true);
109 }
110 
111 TEST_F(ServoFixture, SendTwistStampedTest)
112 {
113  servo_->start();
114  EXPECT_TRUE(waitForFirstStatus()) << "Timeout waiting for Status message";
115 
116  auto parameters = servo_->getParameters();
117 
118  // count trajectory messages sent by servo
119  size_t received_count = 0;
120  boost::function<void(const trajectory_msgs::JointTrajectoryConstPtr&)> traj_callback =
121  [&received_count](const trajectory_msgs::JointTrajectoryConstPtr& /*msg*/) { ++received_count; };
122  auto traj_sub = nh_.subscribe(parameters.command_out_topic, 1, traj_callback);
123 
124  // Create publisher to send servo commands
125  auto twist_stamped_pub = nh_.advertise<geometry_msgs::TwistStamped>(parameters.cartesian_command_in_topic, 1);
126 
127  constexpr double test_duration = 1.0;
128  const double publish_period = parameters.publish_period;
129  const size_t num_commands = static_cast<size_t>(test_duration / publish_period);
130 
131  ros::Rate publish_rate(1. / publish_period);
132 
133  // Send a few Cartesian velocity commands
134  for (size_t i = 0; i < num_commands && ros::ok(); ++i)
135  {
136  auto msg = moveit::util::make_shared_from_pool<geometry_msgs::TwistStamped>();
137  msg->header.stamp = ros::Time::now();
138  msg->header.frame_id = "panda_link0";
139  msg->twist.angular.y = 1.0;
140 
141  // Send the message
142  twist_stamped_pub.publish(msg);
143  publish_rate.sleep();
144  }
145 
146  EXPECT_GT(received_count, num_commands - 20);
147  EXPECT_GT(received_count, (unsigned)0);
148  EXPECT_LT(received_count, num_commands + 20);
149  servo_->setPaused(true);
150 }
151 
152 TEST_F(ServoFixture, SendJointServoTest)
153 {
154  servo_->start();
155  EXPECT_TRUE(waitForFirstStatus()) << "Timeout waiting for Status message";
156 
157  auto parameters = servo_->getParameters();
158 
159  // count trajectory messages sent by servo
160  size_t received_count = 0;
161  boost::function<void(const trajectory_msgs::JointTrajectoryConstPtr&)> traj_callback =
162  [&received_count](const trajectory_msgs::JointTrajectoryConstPtr& /*msg*/) { ++received_count; };
163  auto traj_sub = nh_.subscribe(parameters.command_out_topic, 1, traj_callback);
164 
165  // Create publisher to send servo commands
166  auto joint_servo_pub = nh_.advertise<control_msgs::JointJog>(parameters.joint_command_in_topic, 1);
167 
168  constexpr double test_duration = 1.0;
169  const double publish_period = parameters.publish_period;
170  const size_t num_commands = static_cast<size_t>(test_duration / publish_period);
171 
172  ros::Rate publish_rate(1. / publish_period);
173 
174  // Send a few joint velocity commands
175  for (size_t i = 0; i < num_commands && ros::ok(); ++i)
176  {
177  auto msg = moveit::util::make_shared_from_pool<control_msgs::JointJog>();
178  msg->header.stamp = ros::Time::now();
179  msg->header.frame_id = "panda_link3";
180  msg->velocities.push_back(0.1);
181 
182  // Send the message
183  joint_servo_pub.publish(msg);
184  publish_rate.sleep();
185  }
186 
187  EXPECT_GT(received_count, num_commands - 20);
188  EXPECT_LT(received_count, num_commands + 20);
189  servo_->setPaused(true);
190 }
191 
192 TEST_F(ServoFixture, JointVelocityEnforcementTest)
193 {
194  servo_->start();
195  EXPECT_TRUE(waitForFirstStatus()) << "Timeout waiting for Status message";
196 
197  auto parameters = servo_->getParameters();
198  double publish_period = parameters.publish_period;
199 
200  // count trajectory messages sent by servo
201  size_t received_count = 0;
202  trajectory_msgs::JointTrajectory joint_command_from_servo;
203  trajectory_msgs::JointTrajectory prev_joint_command_from_servo;
204  boost::function<void(const trajectory_msgs::JointTrajectoryConstPtr&)> traj_callback =
205  [&](const trajectory_msgs::JointTrajectoryConstPtr& msg) {
206  ++received_count;
207  // Store a series of two commands so we can calculate velocities
208  // from positions
209  prev_joint_command_from_servo = joint_command_from_servo;
210  joint_command_from_servo = *msg;
211 
212  // Start running checks when we have at least two datapoints
213  if (received_count > 1)
214  {
215  // Need a sequence of two commands to calculate a velocity
216  EXPECT_GT(joint_command_from_servo.points.size(), (unsigned)0);
217  EXPECT_GT(prev_joint_command_from_servo.points.size(), (unsigned)0);
218  EXPECT_EQ(prev_joint_command_from_servo.points.size(), joint_command_from_servo.points.size());
219  // No velocities larger than the largest allowable Panda velocity
220  for (size_t joint_index = 0; joint_index < joint_command_from_servo.points[0].positions.size(); ++joint_index)
221  {
222  double joint_velocity = (joint_command_from_servo.points[0].positions[joint_index] -
223  prev_joint_command_from_servo.points[0].positions[joint_index]) /
224  publish_period;
225  EXPECT_LE(joint_velocity, LARGEST_ALLOWABLE_PANDA_VEL);
226  }
227  }
228  };
229  auto traj_sub = nh_.subscribe(parameters.command_out_topic, 1, traj_callback);
230 
231  // Create publisher to send servo commands
232  auto twist_stamped_pub = nh_.advertise<geometry_msgs::TwistStamped>(parameters.cartesian_command_in_topic, 1);
233 
234  constexpr double test_duration = 1.0;
235  const size_t num_commands = static_cast<size_t>(test_duration / publish_period);
236 
237  ros::Rate publish_rate(1. / publish_period);
238 
239  // Send a few Cartesian commands with very high velocity
240  for (size_t i = 0; i < num_commands && ros::ok(); ++i)
241  {
242  auto msg = moveit::util::make_shared_from_pool<geometry_msgs::TwistStamped>();
243  msg->header.stamp = ros::Time::now();
244  msg->header.frame_id = "panda_link0";
245  msg->twist.linear.x = 10.0;
246  msg->twist.angular.y = 5 * LARGEST_ALLOWABLE_PANDA_VEL;
247 
248  // Send the message
249  twist_stamped_pub.publish(msg);
250  publish_rate.sleep();
251  }
252 
253  EXPECT_GT(received_count, num_commands - 20);
254  EXPECT_LT(received_count, num_commands + 20);
255  servo_->setPaused(true);
256 }
257 } // namespace moveit_servo
258 
259 int main(int argc, char** argv)
260 {
261  ros::init(argc, argv, LOGNAME);
262  testing::InitGoogleTest(&argc, argv);
263 
265  spinner.start();
266 
267  int result = RUN_ALL_TESTS();
268  return result;
269 }
moveit_servo::ServoFixture::TearDown
void TearDown() override
Definition: servo_cpp_interface_test.cpp:81
LARGEST_ALLOWABLE_PANDA_VEL
static constexpr double LARGEST_ALLOWABLE_PANDA_VEL
Definition: servo_cpp_interface_test.cpp:53
servo.h
ros::init
ROSCPP_DECL void init(const M_string &remappings, const std::string &name, uint32_t options=0)
ros.h
main
int main(int argc, char **argv)
Definition: servo_cpp_interface_test.cpp:259
ros::AsyncSpinner
moveit_servo::ServoFixture
Definition: basic_servo_tests.cpp:56
moveit_servo::ServoFixture::planning_scene_monitor_
planning_scene_monitor::PlanningSceneMonitorPtr planning_scene_monitor_
Definition: basic_servo_tests.cpp:90
moveit_servo::ServoFixture::SetUp
void SetUp() override
Definition: servo_cpp_interface_test.cpp:60
LOGNAME
static const std::string LOGNAME
Definition: servo_cpp_interface_test.cpp:52
make_shared_from_pool.h
ros::ok
ROSCPP_DECL bool ok()
EXPECT_TRUE
#define EXPECT_TRUE(args)
moveit_servo::ServoFixture::waitForFirstStatus
bool waitForFirstStatus()
Definition: servo_cpp_interface_test.cpp:85
spinner
void spinner()
moveit_servo::ServoPtr
std::shared_ptr< Servo > ServoPtr
Definition: servo.h:153
planning_scene_monitor::PlanningSceneMonitor::DEFAULT_PLANNING_SCENE_WORLD_TOPIC
static const std::string DEFAULT_PLANNING_SCENE_WORLD_TOPIC
moveit_servo
Definition: collision_check.h:50
planning_scene_monitor::PlanningSceneMonitor::DEFAULT_COLLISION_OBJECT_TOPIC
static const std::string DEFAULT_COLLISION_OBJECT_TOPIC
ros::NodeHandle::hasParam
bool hasParam(const std::string &key) const
ros::Rate::sleep
bool sleep()
moveit_servo::ServoFixture::servo_
moveit_servo::ServoPtr servo_
Definition: basic_servo_tests.cpp:91
ros::Rate
ros::Duration::sleep
bool sleep() const
moveit_servo::TEST_F
TEST_F(ServoFixture, SendTwistStampedTest)
Definition: basic_servo_tests.cpp:94
moveit_servo::ServoFixture::nh_
ros::NodeHandle nh_
Definition: basic_servo_tests.cpp:89
ros::Duration
EXPECT_EQ
#define EXPECT_EQ(a, b)
ros::NodeHandle
ros::Time::now
static Time now()


moveit_servo
Author(s): Brian O'Neil, Andy Zelenak , Blake Anderson, Alexander Rössler , Tyler Weaver
autogenerated on Sat May 3 2025 02:27:56