test_dynamic_publisher.cpp
Go to the documentation of this file.
1 /*********************************************************************
2 * Software License Agreement (BSD License)
3 *
4 * Copyright (c) 2022, Czech Technical University in Prague
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 the Willow Garage 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 /* Code inspired by test_two_links_moving_joint.cpp from robot_state_publisher. */
35 /* Author: Martin Pecka */
36 
37 #include <string>
38 
39 #include <gtest/gtest.h>
40 #include <ros/ros.h>
41 #include <tf2_ros/buffer.h>
43 #include <sensor_msgs/JointState.h>
44 
45 #include <dynamic_reconfigure/client.h>
46 #include <dynamic_robot_state_publisher/DynamicRobotStateConfig.h>
47 
48 using namespace ros;
49 using namespace tf2_ros;
50 using namespace robot_state_publisher;
51 
52 #define EPS 0.01
53 
54 TEST(DynamicPublisherTest, Base)
55 {
56  ros::NodeHandle nh, pnh("~");
57  std::string baseRobotDescription, moreRobotDescription;
58  ASSERT_TRUE(nh.getParam("robot_description", baseRobotDescription));
59  ASSERT_TRUE(nh.getParam("more_robot_description", moreRobotDescription));
60 
61  ROS_INFO("Creating tf listener");
62  Buffer buffer;
63  TransformListener listener(buffer);
64 
65  dynamic_reconfigure::Client<DynamicRobotStateConfig> reconfigClient("test", NodeHandle(nh, "dynamic_pub"));
66  DynamicRobotStateConfig config;
67  auto spin = [](size_t num = 10, double duration = 0.1) {
68  for (size_t i = 0; i < num; ++i) {
69  ros::spinOnce();
70  ros::WallDuration(duration).sleep();
71  }
72  };
73  spin();
74  ASSERT_TRUE(reconfigClient.getCurrentConfiguration(config, ros::Duration(1.0)));
75  ASSERT_EQ(baseRobotDescription, config.robot_description);
76 
77  ROS_INFO("Publishing joint state to robot state publisher");
78  ros::Publisher js_pub = nh.advertise<sensor_msgs::JointState>("joint_states", 10);
79  ros::WallDuration(0.5).sleep();
80 
81  sensor_msgs::JointState js_msg;
82  js_msg.name.push_back("joint1");
83  js_msg.position.push_back(M_PI);
84 
85  auto publishJointStates = [&]() {
86  for (unsigned int i = 0; i < 10; i++) {
87  js_msg.header.stamp = ros::Time::now();
88  js_pub.publish(js_msg);
89  ros::WallDuration(0.1).sleep();
90  }
91  };
92  publishJointStates();
93 
94  auto spinUntilFrame = [&](const std::string& frame, size_t num = 10, double duration = 0.1) {
95  for (size_t i = 0; i < num && !buffer.canTransform("link1", frame, Time()); ++i) {
96  ros::spinOnce();
97  ros::WallDuration(duration).sleep();
98  }
99  };
100  spinUntilFrame("link2");
101  EXPECT_FALSE(buffer.canTransform("link1", "link3", Time()));
102  ASSERT_TRUE(buffer.canTransform("link1", "link2", Time()));
103 
104  auto t = buffer.lookupTransform("link1", "link2", Time());
105  EXPECT_NEAR(t.transform.translation.x, 5.0, EPS);
106  EXPECT_NEAR(t.transform.translation.y, 0.0, EPS);
107  EXPECT_NEAR(t.transform.translation.z, 0.0, EPS);
108 
109  // Now load the moreRobotDescription and check that link3 is reachable
110 
111  buffer.clear();
112 
113  config.robot_description = moreRobotDescription;
114  ASSERT_TRUE(reconfigClient.setConfiguration(config));
115  spin(10, 0.01);
116  ASSERT_TRUE(reconfigClient.getCurrentConfiguration(config, ros::Duration(1.0)));
117 
118  publishJointStates();
119  spinUntilFrame("link3");
120  ASSERT_TRUE(buffer.canTransform("link1", "link3", Time()));
121  ASSERT_TRUE(buffer.canTransform("link1", "link2", Time()));
122 
123  EXPECT_EQ(moreRobotDescription, config.robot_description);
124 
125  t = buffer.lookupTransform("link1", "link2", Time());
126  EXPECT_NEAR(t.transform.translation.x, 5.0, EPS);
127  EXPECT_NEAR(t.transform.translation.y, 0.0, EPS);
128  EXPECT_NEAR(t.transform.translation.z, 0.0, EPS);
129 
130  t = buffer.lookupTransform("link1", "link3", Time());
131  EXPECT_NEAR(t.transform.translation.x, 5.0, EPS);
132  EXPECT_NEAR(t.transform.translation.y, 5.0, EPS);
133  EXPECT_NEAR(t.transform.translation.z, 0.0, EPS);
134 
135  // And load the base description back, check that link3 is no longer reachable.
136 
137  buffer.clear();
138 
139  config.robot_description = baseRobotDescription;
140  ASSERT_TRUE(reconfigClient.setConfiguration(config));
141  spin(10, 0.01);
142  ASSERT_TRUE(reconfigClient.getCurrentConfiguration(config, ros::Duration(1.0)));
143 
144  publishJointStates();
145  spinUntilFrame("link2");
146  EXPECT_FALSE(buffer.canTransform("link1", "link3", Time()));
147  ASSERT_TRUE(buffer.canTransform("link1", "link2", Time()));
148 
149  EXPECT_EQ(baseRobotDescription, config.robot_description);
150 }
151 
152 int main(int argc, char** argv)
153 {
154  testing::InitGoogleTest(&argc, argv);
155  ros::init(argc, argv, "test_dynamic_publisher");
156  return RUN_ALL_TESTS();
157 }
main
int main(int argc, char **argv)
Definition: test_dynamic_publisher.cpp:152
ros::WallDuration::sleep
bool sleep() const
ros::Publisher
TEST
TEST(DynamicPublisherTest, Base)
Definition: test_dynamic_publisher.cpp:54
ros::init
ROSCPP_DECL void init(const M_string &remappings, const std::string &name, uint32_t options=0)
ros
ros::NodeHandle::getParam
bool getParam(const std::string &key, bool &b) const
ros.h
ros::spinOnce
ROSCPP_DECL void spinOnce()
buffer.h
ros::Publisher::publish
void publish(const boost::shared_ptr< M > &message) const
ros::NodeHandle::advertise
Publisher advertise(AdvertiseOptions &ops)
tf2_ros::TransformListener
tf2_ros::Buffer::canTransform
virtual bool canTransform(const std::string &target_frame, const ros::Time &target_time, const std::string &source_frame, const ros::Time &source_time, const std::string &fixed_frame, const ros::Duration timeout, std::string *errstr=NULL) const
tf2_ros
EPS
#define EPS
Definition: test_dynamic_publisher.cpp:52
Base
tf2::BufferCore::clear
void clear()
tf2_ros::Buffer
ros::NodeHandle
robot_state_publisher
transform_listener.h
ros::Time
ros::spin
ROSCPP_DECL void spin()
ros::WallDuration
ROS_INFO
#define ROS_INFO(...)
ros::Duration
tf2_ros::Buffer::lookupTransform
virtual geometry_msgs::TransformStamped lookupTransform(const std::string &target_frame, const ros::Time &target_time, const std::string &source_frame, const ros::Time &source_time, const std::string &fixed_frame, const ros::Duration timeout) const
ros::NodeHandle
ros::Time::now
static Time now()


dynamic_robot_state_publisher
Author(s): Martin Pecka
autogenerated on Fri May 6 2022 02:34:15