Skip to content

Commit a6981b9

Browse files
[tests] Restructure test_sot_loader.
1 parent 09feb19 commit a6981b9

File tree

3 files changed

+140
-20
lines changed

3 files changed

+140
-20
lines changed

tests/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,10 @@ if(BUILD_TESTING)
115115
ament_target_dependencies(${current_test_name} dynamic_graph_bridge_msgs
116116
rclcpp rcl_interfaces std_srvs)
117117

118+
# Install tests
119+
install(TARGETS test_${test_name}
120+
DESTINATION lib/${PROJECT_NAME})
121+
118122
endmacro(create_ros_bridge_unittest test_name)
119123

120124
# C++ unit-tests.

tests/impl_test_sot_external_interface.cpp

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ ImplTestSotExternalInterface::ImplTestSotExternalInterface(
2525
ImplTestSotExternalInterface::~ImplTestSotExternalInterface() {}
2626

2727
void ImplTestSotExternalInterface::init() {
28+
std::cout << "ImplTestSotExternalInterface::init - begin" << std::endl;
2829
std::vector<double> ctrl_vector;
2930
ctrl_vector.resize(2);
3031

@@ -52,11 +53,23 @@ void ImplTestSotExternalInterface::init() {
5253

5354
RosNodePtr py_inter_ptr = get_ros_node("python_interpreter");
5455
// Set the control time step parameter to 0.001
55-
double ts = 0.001;
56+
double ts = 0.01;
5657

58+
// Publish parameters related to the control interface
5759
py_inter_ptr->declare_parameter<double>("/sot_controller/dt", ts);
60+
// Create services to interact with the embedded python interpreter.
5861
py_interpreter_srv_->start_ros_service();
62+
63+
// Non blocking spinner to deal with ros.
64+
// Be careful: here with tests we do not care about real time issue.
65+
// In the real robot you need to make sure that the control loop is
66+
// not block and that the thread associated with the services is not blocking
67+
// the control loop.
68+
ros_spin_non_blocking();
69+
5970
device_->timeStep(ts);
71+
72+
std::cout << "ImplTestSotExternalInterface::init - end" << std::endl;
6073
}
6174

6275
void ImplTestSotExternalInterface::setupSetSensors(
@@ -66,7 +79,7 @@ void ImplTestSotExternalInterface::setupSetSensors(
6679

6780
void ImplTestSotExternalInterface::nominalSetSensors(
6881
std::map<std::string, dynamicgraph::sot::SensorValues> &) {
69-
std::cout << "ImplTestSotExternalInterface::nominalSetSensors" << std::endl;
82+
// std::cout << "ImplTestSotExternalInterface::nominalSetSensors" << std::endl;
7083
}
7184

7285
void ImplTestSotExternalInterface::cleanupSetSensors(

tests/test_sot_loader.cpp

Lines changed: 121 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,14 @@
33
#include <gmock/gmock.h>
44
#pragma clang diagnostic pop
55

6+
using namespace std::chrono_literals;
7+
8+
#include <rclcpp/rclcpp.hpp>
9+
610
#include "dynamic_graph_bridge/ros.hpp"
711
#include "dynamic_graph_bridge/sot_loader.hh"
812
#include "dynamic_graph_bridge_msgs/msg/vector.hpp"
9-
#include "test_common.hpp"
13+
#include "dynamic_graph_bridge/ros_python_interpreter_server.hpp"
1014

1115
namespace test_sot_loader {
1216
int l_argc;
@@ -21,29 +25,131 @@ class MockSotLoaderTest : public ::testing::Test {
2125
public:
2226
rclcpp::Subscription<dynamic_graph_bridge_msgs::msg::Vector>::SharedPtr
2327
subscription_;
28+
bool service_done_;
29+
std::string node_name_;
30+
std::string response_dg_python_result_;
2431

25-
~MockSotLoader() {}
32+
MockSotLoader():
33+
node_name_("unittest_sot_loader") {}
2634

27-
void topic_callback(const dynamic_graph_bridge_msgs::msg::Vector::SharedPtr msg) const {
28-
auto lsize=msg->data.size();
35+
~MockSotLoader() {
36+
service_done_ = false;
37+
response_dg_python_result_ = "";
2938
}
3039

40+
void topic_callback(const dynamic_graph_bridge_msgs::msg::Vector::SharedPtr msg) const {
41+
bool ok=true;
42+
for(std::vector<double>::size_type idx=0;idx<msg->data.size();idx++) {
43+
if (msg->data[idx]!=0.0)
44+
ok=false;
45+
}
46+
ASSERT_TRUE(ok);
47+
}
48+
// This method is to listen to publication from the control signal (dg world)
49+
// to the control_ros topic (ros world).
3150
void subscribe_to_a_topic() {
32-
subscription_ = create_subscription<dynamic_graph_bridge_msgs::msg::Vector>(
33-
"control_ros", 1, std::bind(&MockSotLoader::topic_callback, this,
34-
std::placeholders::_1));
51+
subscription_ = dynamic_graph_bridge::get_ros_node(node_name_)->
52+
create_subscription<dynamic_graph_bridge_msgs::msg::Vector>(
53+
"control_ros", 1, std::bind(&MockSotLoader::topic_callback, this,
54+
std::placeholders::_1));
55+
}
56+
57+
// This method is to receive the result of client request to run_python_file
58+
//
59+
void response_dg_python(
60+
const rclcpp::Client<dynamic_graph_bridge_msgs::srv::RunPythonFile>::SharedFuture
61+
future) {
62+
RCLCPP_INFO(rclcpp::get_logger("dynamic_graph_bridge"), "response_dg_python:");
63+
auto status = future.wait_for(500ms);
64+
if (status == std::future_status::ready) {
65+
// uncomment below line if using Empty() message
66+
// RCLCPP_INFO(this->get_logger(), "Result: success");
67+
// comment below line if using Empty() message
68+
RCLCPP_INFO(rclcpp::get_logger("dynamic_graph_bridge"),
69+
"response_dg_python - Result: %s",
70+
future.get()->result.c_str());
71+
service_done_ = true;
72+
response_dg_python_result_ = future.get()->result;
73+
} else {
74+
RCLCPP_INFO(rclcpp::get_logger("dynmic_graph_bridge"),
75+
"response_dg_python - Service In-Progress...");
76+
}
77+
}
78+
79+
void start_run_python_script_ros_service(const std::string& file_name) {
80+
// Service name.
81+
std::string service_name = "/dynamic_graph_bridge/run_python_file";
82+
// Create a client from a temporary node.
83+
auto client = dynamic_graph_bridge::get_ros_node(node_name_)->
84+
create_client<dynamic_graph_bridge_msgs::srv::RunPythonFile>(
85+
service_name);
86+
ASSERT_TRUE(client->wait_for_service(1s));
87+
88+
// Fill the command message.
89+
dynamic_graph_bridge_msgs::srv::RunPythonFile::Request::SharedPtr request =
90+
std::make_shared<
91+
dynamic_graph_bridge_msgs::srv::RunPythonFile::Request>();
92+
request->input = file_name;
93+
// Call the service.
94+
auto response =
95+
client->async_send_request(request,
96+
std::bind(&MockSotLoader::response_dg_python,
97+
this,
98+
std::placeholders::_1));
99+
RCLCPP_INFO(rclcpp::get_logger("dynamic_graph_bridge"),
100+
"Send request to service %s - Waiting",
101+
service_name.c_str());
102+
response.wait();
103+
RCLCPP_INFO(rclcpp::get_logger("dynamic_graph_bridge"),
104+
"Get the answer");
105+
106+
}
107+
108+
void display_services(
109+
std::map<std::string, std::vector<std::string> >& list_service_and_types) {
110+
for (std::map<std::string, std::vector<std::string> >::const_iterator
111+
const_it = list_service_and_types.begin();
112+
const_it != list_service_and_types.end(); ++const_it) {
113+
std::cerr << const_it->first << "\t\t\t";
114+
for (unsigned i = 0; i < const_it->second.size(); ++i) {
115+
std::cerr << std::right;
116+
std::cerr << const_it->second[i] << std::endl;
117+
}
118+
}
119+
}
120+
121+
void local_ros_spin() {
122+
RCLCPP_INFO(rclcpp::get_logger("dynamic_graph_bridge"),
123+
"local_ros_spin");
124+
dynamic_graph_bridge::ros_spin();
35125
}
36126

37127
void generateEvents() {
38128
usleep(20000);
39-
std::cerr << "Start Dynamic Graph " << std::endl;
129+
RCLCPP_INFO(rclcpp::get_logger("dynamic_graph_bridge"),
130+
"Start Dynamic Graph ");
40131
dynamic_graph_stopped_ = false;
41132

42-
usleep(20000);
43-
std::cerr << "Stop Dynamic Graph " << std::endl;
133+
std::string file_name =
134+
TEST_CONFIG_PATH + std::string("simple_ros_publish.py");
135+
std::string result = "";
136+
std::string standard_output = "";
137+
std::string standard_error = "";
138+
start_run_python_script_ros_service(file_name);
139+
140+
141+
usleep(100000);
142+
std::map<std::string, std::vector<std::string>> list_service_and_types;
143+
dynamic_graph_bridge::RosNodePtr ros_node = dynamic_graph_bridge::get_ros_node(node_name_);
144+
bool simple_service_exists = false;
145+
146+
usleep(30720000); // Wait 30s
147+
RCLCPP_INFO(rclcpp::get_logger("dynamic_graph_bridge"),
148+
"Stop Dynamic Graph ");
44149
dynamic_graph_stopped_ = true;
45150
}
46151

152+
47153
void testLoadController() {
48154
// Set input call
49155
int argc = 2;
@@ -79,16 +185,11 @@ class MockSotLoaderTest : public ::testing::Test {
79185
// Start the thread generating events.
80186
std::thread local_events(&MockSotLoader::generateEvents, this);
81187

82-
// Create and call the clients.
83-
std::string file_name =
84-
TEST_CONFIG_PATH + std::string("simple_ros_publish.py");
85-
std::string result = "";
86-
std::string standard_output = "";
87-
std::string standard_error = "";
88-
//start_run_python_script_ros_service(file_name, result);
188+
// Start the thread for ros events.
189+
std::thread local_ros_spin_thread(&MockSotLoader::local_ros_spin, this);
89190

90191
// Wait for each threads.
91-
SotLoader::lthread_join(); // Wait 100 ms
192+
SotLoader::lthread_join();
92193
local_events.join();
93194
}
94195
};
@@ -111,11 +212,13 @@ class MockSotLoaderTest : public ::testing::Test {
111212
void SetUp() {
112213
mockSotLoader_ptr_ = new MockSotLoader();
113214
mockSotLoader_ptr_->initialize();
215+
dynamic_graph_bridge::ros_spin_non_blocking();
114216
}
115217

116218
void TearDown() {
117219
delete mockSotLoader_ptr_;
118220
mockSotLoader_ptr_ = nullptr;
221+
dynamic_graph_bridge::ros_clean();
119222
}
120223
};
121224

0 commit comments

Comments
 (0)