basic_servo_tests.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: Tyler Weaver, Andy Zelenak
36  Desc: Basic functionality tests
37 */
38 
39 // System
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 = "basic_servo_tests";
53 
54 namespace moveit_servo
55 {
56 class ServoFixture : public ::testing::Test
57 {
58 public:
59  void SetUp() override
60  {
61  // Wait for several key topics / parameters
62  ros::topic::waitForMessage<sensor_msgs::JointState>("/joint_states");
63  while (!nh_.hasParam("/robot_description") && ros::ok())
64  {
65  ros::Duration(0.1).sleep();
66  }
67 
68  // Load the planning scene monitor
69  planning_scene_monitor_ = std::make_shared<planning_scene_monitor::PlanningSceneMonitor>("robot_description");
70  planning_scene_monitor_->startSceneMonitor();
71  planning_scene_monitor_->startStateMonitor();
72  planning_scene_monitor_->startWorldGeometryMonitor(
75  false /* skip octomap monitor */);
76 
77  // Create moveit_servo
78  servo_ = std::make_shared<Servo>(nh_, planning_scene_monitor_);
79  }
80  void TearDown() override
81  {
82  }
83 
84 protected:
85  void enforceVelLimits(Eigen::ArrayXd& delta_theta)
86  {
87  servo_->servo_calcs_->enforceVelLimits(delta_theta);
88  }
90  planning_scene_monitor::PlanningSceneMonitorPtr planning_scene_monitor_;
92 }; // class ServoFixture
93 
94 TEST_F(ServoFixture, SendTwistStampedTest)
95 {
96  servo_->start();
97 
98  auto parameters = servo_->getParameters();
99 
100  // count trajectory messages sent by servo
101  size_t received_count = 0;
102  boost::function<void(const trajectory_msgs::JointTrajectoryConstPtr&)> traj_callback =
103  [&received_count](const trajectory_msgs::JointTrajectoryConstPtr& /*msg*/) { ++received_count; };
104  auto traj_sub = nh_.subscribe(parameters.command_out_topic, 1, traj_callback);
105 
106  // Create publisher to send servo commands
107  auto twist_stamped_pub = nh_.advertise<geometry_msgs::TwistStamped>(parameters.cartesian_command_in_topic, 1);
108 
109  constexpr double test_duration = 1.0;
110  const double publish_period = parameters.publish_period;
111  const size_t num_commands = static_cast<size_t>(test_duration / publish_period);
112 
113  // Set the rate differently from the publish period from the parameters to show that
114  // the number of outputs is set by the number of commands sent and not the rate they are sent.
115  ros::Rate publish_rate(2. / publish_period);
116 
117  // Send a few Cartesian velocity commands
118  for (size_t i = 0; i < num_commands && ros::ok(); ++i)
119  {
120  auto msg = moveit::util::make_shared_from_pool<geometry_msgs::TwistStamped>();
121  msg->header.stamp = ros::Time::now();
122  msg->header.frame_id = "panda_link0";
123  msg->twist.angular.y = 1.0;
124 
125  // Send the message
126  twist_stamped_pub.publish(msg);
127  publish_rate.sleep();
128  }
129 
130  EXPECT_GT(received_count, num_commands - 20);
131  EXPECT_GT(received_count, (unsigned)0);
132  EXPECT_LT(received_count, num_commands + 20);
133  servo_->setPaused(true);
134 }
135 
136 TEST_F(ServoFixture, SendJointServoTest)
137 {
138  servo_->start();
139 
140  auto parameters = servo_->getParameters();
141 
142  // count trajectory messages sent by servo
143  size_t received_count = 0;
144  boost::function<void(const trajectory_msgs::JointTrajectoryConstPtr&)> traj_callback =
145  [&received_count](const trajectory_msgs::JointTrajectoryConstPtr& /*msg*/) { ++received_count; };
146  auto traj_sub = nh_.subscribe(parameters.command_out_topic, 1, traj_callback);
147 
148  // Create publisher to send servo commands
149  auto joint_servo_pub = nh_.advertise<control_msgs::JointJog>(parameters.joint_command_in_topic, 1);
150 
151  constexpr double test_duration = 1.0;
152  const double publish_period = parameters.publish_period;
153  const size_t num_commands = static_cast<size_t>(test_duration / publish_period);
154 
155  // Set the rate differently from the publish period from the parameters to show that
156  // the number of outputs is set by the number of commands sent and not the rate they are sent.
157  ros::Rate publish_rate(2. / publish_period);
158 
159  // Send a few joint velocity commands
160  for (size_t i = 0; i < num_commands && ros::ok(); ++i)
161  {
162  auto msg = moveit::util::make_shared_from_pool<control_msgs::JointJog>();
163  msg->header.stamp = ros::Time::now();
164  msg->header.frame_id = "panda_link3";
165  msg->velocities.push_back(0.1);
166 
167  // Send the message
168  joint_servo_pub.publish(msg);
169  publish_rate.sleep();
170  }
171 
172  EXPECT_GT(received_count, num_commands - 20);
173  EXPECT_GT(received_count, (unsigned)0);
174  EXPECT_LT(received_count, num_commands + 20);
175  servo_->setPaused(true);
176 }
177 
178 // This a friend test of a private member function
179 TEST_F(ServoFixture, EnforceVelLimitsTest)
180 {
181  auto parameters = servo_->getParameters();
182  const double publish_period = parameters.publish_period;
183 
184  // Request joint angle changes that are too fast, given the control period in servo settings YAML file.
185  Eigen::ArrayXd delta_theta(7);
186  delta_theta[0] = 0; // rad
187  delta_theta[1] = 0.01;
188  delta_theta[2] = 0.02;
189  delta_theta[3] = 0.03;
190  delta_theta[4] = 0.04;
191  delta_theta[5] = 0.05;
192  delta_theta[6] = 0.06;
193 
194  // Store the original joint commands for comparison before applying velocity scaling.
195  Eigen::ArrayXd orig_delta_theta = delta_theta;
196  enforceVelLimits(delta_theta);
197 
198  // From Panda arm MoveIt joint_limits.yaml. The largest velocity limits for a joint.
199  const double panda_max_joint_vel = 2.610; // rad/s
200  const double velocity_scaling_factor = panda_max_joint_vel / (orig_delta_theta.maxCoeff() / publish_period);
201  const double tolerance = 5e-3;
202  for (int i = 0; i < 7; ++i)
203  {
204  EXPECT_NEAR(orig_delta_theta(i) * velocity_scaling_factor, delta_theta(i), tolerance);
205  }
206 
207  // Now, negative joint angle deltas. Some will result to velocities
208  // greater than the arm joint velocity limits.
209  delta_theta[0] = 0; // rad
210  delta_theta[1] = -0.01;
211  delta_theta[2] = -0.02;
212  delta_theta[3] = -0.03;
213  delta_theta[4] = -0.04;
214  delta_theta[5] = -0.05;
215  delta_theta[6] = -0.06;
216 
217  // Store the original joint commands for comparison before applying velocity scaling.
218  orig_delta_theta = delta_theta;
219  enforceVelLimits(delta_theta);
220  for (int i = 0; i < 7; ++i)
221  {
222  EXPECT_NEAR(orig_delta_theta(i) * velocity_scaling_factor, delta_theta(i), tolerance);
223  }
224 
225  // Final test with joint angle deltas that will result in velocities
226  // below the lowest Panda arm joint velocity limit.
227  delta_theta[0] = 0; // rad
228  delta_theta[1] = -0.013;
229  delta_theta[2] = 0.023;
230  delta_theta[3] = -0.004;
231  delta_theta[4] = 0.021;
232  delta_theta[5] = 0.012;
233  delta_theta[6] = 0.0075;
234 
235  // Store the original joint commands for comparison before applying velocity scaling.
236  orig_delta_theta = delta_theta;
237  enforceVelLimits(delta_theta);
238  for (int i = 0; i < 7; ++i)
239  {
240  EXPECT_NEAR(orig_delta_theta(i), delta_theta(i), tolerance);
241  }
242 }
243 } // namespace moveit_servo
244 
245 int main(int argc, char** argv)
246 {
247  ros::init(argc, argv, LOGNAME);
248  testing::InitGoogleTest(&argc, argv);
249 
251  spinner.start();
252 
253  int result = RUN_ALL_TESTS();
254  return result;
255 }
moveit_servo::ServoFixture::TearDown
void TearDown() override
Definition: basic_servo_tests.cpp:80
servo.h
moveit_servo::ServoFixture::enforceVelLimits
void enforceVelLimits(Eigen::ArrayXd &delta_theta)
Definition: basic_servo_tests.cpp:85
ros::init
ROSCPP_DECL void init(const M_string &remappings, const std::string &name, uint32_t options=0)
ros.h
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: basic_servo_tests.cpp:59
make_shared_from_pool.h
ros::ok
ROSCPP_DECL bool ok()
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
EXPECT_NEAR
#define EXPECT_NEAR(a, b, prec)
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
LOGNAME
static const std::string LOGNAME
Definition: basic_servo_tests.cpp:52
tolerance
S tolerance()
ros::Rate
ros::Duration::sleep
bool sleep() const
moveit_servo::TEST_F
TEST_F(ServoFixture, SendTwistStampedTest)
Definition: basic_servo_tests.cpp:94
main
int main(int argc, char **argv)
Definition: basic_servo_tests.cpp:245
moveit_servo::ServoFixture::nh_
ros::NodeHandle nh_
Definition: basic_servo_tests.cpp:89
ros::Duration
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