Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update services examples #317

Open
wants to merge 5 commits into
base: rolling
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions rclcpp/services/minimal_client/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,19 @@ find_package(ament_cmake REQUIRED)
find_package(example_interfaces REQUIRED)
find_package(rclcpp REQUIRED)

add_executable(client_main main.cpp)
ament_target_dependencies(client_main rclcpp example_interfaces)
add_executable(client_lambda lambda.cpp)
ament_target_dependencies(client_lambda rclcpp example_interfaces)

install(TARGETS client_main
add_executable(client_member_function member_function.cpp)
ament_target_dependencies(client_member_function rclcpp example_interfaces)

add_executable(client_not_composable not_composable.cpp)
ament_target_dependencies(client_not_composable rclcpp example_interfaces)

install(TARGETS
client_lambda
client_member_function
client_not_composable
DESTINATION lib/${PROJECT_NAME})

if(BUILD_TESTING)
Expand Down
67 changes: 67 additions & 0 deletions rclcpp/services/minimal_client/lambda.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// Copyright 2016 Open Source Robotics Foundation, Inc.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You may want to update the copyright information, at least with the year 2021.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// Copyright 2016 Open Source Robotics Foundation, Inc.
// Copyright 2024 Open Source Robotics Foundation, Inc.

Happy new year 🆕 can be applied to other new files.

//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <chrono>
#include <cinttypes>
#include <memory>

#include "example_interfaces/srv/add_two_ints.hpp"
#include "rclcpp/rclcpp.hpp"

using namespace std::chrono_literals;
using example_interfaces::srv::AddTwoInts;

/* This example creates a subclass of Node and uses std::bind() to register a
* member function as a callback from the client. */

class MinimalClient : public rclcpp::Node
{
public:
MinimalClient()
: Node("minimal_client")
{
client_ = this->create_client<AddTwoInts>("add_two_ints");
while (!client_->wait_for_service(1s)) {
if (!rclcpp::ok()) {
RCLCPP_ERROR(this->get_logger(), "client interrupted while waiting for service to appear.");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To prevent an infinite loop, add return (which is valid in a ctor) to leave the loop, cf. the return 1; in not_composable.cpp. However, note that the spin(node) in the main function must not be called if rclcpp::ok() is already false since this will cause an the given context is not valid error. Probably it is better to move the waiting for the service into a one-shot timer as in the examples_rclcpp_minimal_action_client example.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think @threeal tries to keep the current behavior here, i am okay with current behavior for this example so that user does not need to issue service 1st.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Once the return issue is solved, it is probably also necessary to change the logger to rclcpp::get_logger("rclcpp") as in not_composable.cpp.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why? this log is not obviously for rclcpp? so getting logger from this(Node) is fine? (saying current code looks fine.)

}
RCLCPP_INFO(this->get_logger(), "waiting for service to appear...");
}
auto request = std::make_shared<AddTwoInts::Request>();
request->a = 41;
request->b = 1;
auto result_future = client_->async_send_request(
request,
[this](rclcpp::Client<AddTwoInts>::SharedFutureWithRequest result_future) {
auto result = result_future.get();
auto request = result.first;
auto response = result.second;
RCLCPP_INFO(
this->get_logger(), "result of %" PRId64 " + %" PRId64 " = %" PRId64,
request->a, request->b, response->sum);
rclcpp::shutdown();
});
}

private:
rclcpp::Client<AddTwoInts>::SharedPtr client_;
};

int main(int argc, char * argv[])
{
rclcpp::init(argc, argv);
rclcpp::spin(std::make_shared<MinimalClient>());
rclcpp::shutdown();
return 0;
}
69 changes: 69 additions & 0 deletions rclcpp/services/minimal_client/member_function.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// Copyright 2016 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <chrono>
#include <cinttypes>
#include <memory>

#include "example_interfaces/srv/add_two_ints.hpp"
#include "rclcpp/rclcpp.hpp"

using namespace std::chrono_literals;
using std::placeholders::_1;
using example_interfaces::srv::AddTwoInts;

/* This example creates a subclass of Node and uses std::bind() to register a
* member function as a callback from the client. */

class MinimalClient : public rclcpp::Node
{
public:
MinimalClient()
: Node("minimal_client")
{
client_ = this->create_client<AddTwoInts>("add_two_ints");
while (!client_->wait_for_service(1s)) {
if (!rclcpp::ok()) {
RCLCPP_ERROR(this->get_logger(), "client interrupted while waiting for service to appear.");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See my above comment about leaving the loop by a return.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Once the return issue is solved, it is probably also necessary to change the logger to rclcpp::get_logger("rclcpp") as in not_composable.cpp.

}
RCLCPP_INFO(this->get_logger(), "waiting for service to appear...");
}
auto request = std::make_shared<AddTwoInts::Request>();
request->a = 41;
request->b = 1;
auto result_future = client_->async_send_request(
request, std::bind(&MinimalClient::service_callback, this, _1));
}

private:
void service_callback(rclcpp::Client<AddTwoInts>::SharedFutureWithRequest result_future) const
{
auto result = result_future.get();
auto request = result.first;
auto response = result.second;
RCLCPP_INFO(
this->get_logger(), "result of %" PRId64 " + %" PRId64 " = %" PRId64,
request->a, request->b, response->sum);
rclcpp::shutdown();
}
rclcpp::Client<AddTwoInts>::SharedPtr client_;
};

int main(int argc, char * argv[])
{
rclcpp::init(argc, argv);
rclcpp::spin(std::make_shared<MinimalClient>());
rclcpp::shutdown();
return 0;
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,20 @@
#include "example_interfaces/srv/add_two_ints.hpp"
#include "rclcpp/rclcpp.hpp"

using AddTwoInts = example_interfaces::srv::AddTwoInts;
using namespace std::chrono_literals;
using example_interfaces::srv::AddTwoInts;

/* We do not recommend this style anymore, because composition of multiple
* nodes in the same executable is not possible. Please see one of the subclass
* examples for the "new" recommended styles. This example is only included
* for completeness because it is similar to "classic" standalone ROS nodes. */

int main(int argc, char * argv[])
{
rclcpp::init(argc, argv);
auto node = rclcpp::Node::make_shared("minimal_client");
auto client = node->create_client<AddTwoInts>("add_two_ints");
while (!client->wait_for_service(std::chrono::seconds(1))) {
while (!client->wait_for_service(1s)) {
if (!rclcpp::ok()) {
RCLCPP_ERROR(node->get_logger(), "client interrupted while waiting for service to appear.");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
RCLCPP_ERROR(node->get_logger(), "client interrupted while waiting for service to appear.");
RCLCPP_ERROR(rclcpp::get_logger("rclcpp"), "client interrupted while waiting for service to appear.");

With the node's logger, the publisher for rosout will occasionally raise a publisher's context is invalid exception on this line.

return 1;
Expand All @@ -43,10 +49,10 @@ int main(int argc, char * argv[])
RCLCPP_ERROR(node->get_logger(), "service call failed :(");
return 1;
}
auto result = result_future.get();
auto response = result_future.get();
RCLCPP_INFO(
node->get_logger(), "result of %" PRId64 " + %" PRId64 " = %" PRId64,
request->a, request->b, result->sum);
request->a, request->b, response->sum);
rclcpp::shutdown();
return 0;
}
15 changes: 12 additions & 3 deletions rclcpp/services/minimal_service/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,19 @@ find_package(ament_cmake REQUIRED)
find_package(example_interfaces REQUIRED)
find_package(rclcpp REQUIRED)

add_executable(service_main main.cpp)
ament_target_dependencies(service_main rclcpp example_interfaces)
add_executable(service_lambda lambda.cpp)
ament_target_dependencies(service_lambda rclcpp example_interfaces)

install(TARGETS service_main
add_executable(service_member_function member_function.cpp)
ament_target_dependencies(service_member_function rclcpp example_interfaces)

add_executable(service_not_composable not_composable.cpp)
ament_target_dependencies(service_not_composable rclcpp example_interfaces)

install(TARGETS
service_lambda
service_member_function
service_not_composable
DESTINATION lib/${PROJECT_NAME})

if(BUILD_TESTING)
Expand Down
54 changes: 54 additions & 0 deletions rclcpp/services/minimal_service/lambda.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Copyright 2016 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <cinttypes>
#include <memory>

#include "example_interfaces/srv/add_two_ints.hpp"
#include "rclcpp/rclcpp.hpp"

using example_interfaces::srv::AddTwoInts;

/* This example creates a subclass of Node and uses a fancy C++11 lambda
* function to shorten the callback syntax, at the expense of making the
* code somewhat more difficult to understand at first glance. */

class MinimalService : public rclcpp::Node
{
public:
MinimalService()
: Node("minimal_service")
{
server_ = this->create_service<AddTwoInts>(
"add_two_ints",
[this](const AddTwoInts::Request::SharedPtr request,
AddTwoInts::Response::SharedPtr response) {
RCLCPP_INFO(
this->get_logger(),
"request: %" PRId64 " + %" PRId64, request->a, request->b);
response->sum = request->a + request->b;
});
}

private:
rclcpp::Service<AddTwoInts>::SharedPtr server_;
};

int main(int argc, char * argv[])
{
rclcpp::init(argc, argv);
rclcpp::spin(std::make_shared<MinimalService>());
rclcpp::shutdown();
return 0;
}
57 changes: 57 additions & 0 deletions rclcpp/services/minimal_service/member_function.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// Copyright 2016 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <cinttypes>
#include <memory>

#include "example_interfaces/srv/add_two_ints.hpp"
#include "rclcpp/rclcpp.hpp"

using std::placeholders::_1;
using std::placeholders::_2;
using example_interfaces::srv::AddTwoInts;

/* This example creates a subclass of Node and uses std::bind() to register a
* member function as a callback from the server. */

class MinimalService : public rclcpp::Node
{
public:
MinimalService()
: Node("minimal_service")
{
server_ = this->create_service<AddTwoInts>(
"add_two_ints", std::bind(&MinimalService::service_callback, this, _1, _2));
}

private:
void service_callback(
const AddTwoInts::Request::SharedPtr request,
AddTwoInts::Response::SharedPtr response) const
{
RCLCPP_INFO(
this->get_logger(),
"request: %" PRId64 " + %" PRId64, request->a, request->b);
response->sum = request->a + request->b;
}
rclcpp::Service<AddTwoInts>::SharedPtr server_;
};

int main(int argc, char * argv[])
{
rclcpp::init(argc, argv);
rclcpp::spin(std::make_shared<MinimalService>());
rclcpp::shutdown();
return 0;
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,18 @@
#include "example_interfaces/srv/add_two_ints.hpp"
#include "rclcpp/rclcpp.hpp"

using AddTwoInts = example_interfaces::srv::AddTwoInts;
using example_interfaces::srv::AddTwoInts;
rclcpp::Node::SharedPtr g_node = nullptr;

/* We do not recommend this style anymore, because composition of multiple
* nodes in the same executable is not possible. Please see one of the subclass
* examples for the "new" recommended styles. This example is only included
* for completeness because it is similar to "classic" standalone ROS nodes. */

void handle_service(
const std::shared_ptr<rmw_request_id_t> request_header,
const std::shared_ptr<AddTwoInts::Request> request,
const std::shared_ptr<AddTwoInts::Response> response)
const AddTwoInts::Request::SharedPtr request,
AddTwoInts::Response::SharedPtr response)
{
(void)request_header;
RCLCPP_INFO(
g_node->get_logger(),
"request: %" PRId64 " + %" PRId64, request->a, request->b);
Expand Down
2 changes: 1 addition & 1 deletion rclcpp/topics/minimal_publisher/lambda.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class MinimalPublisher : public rclcpp::Node
{
publisher_ = this->create_publisher<std_msgs::msg::String>("topic", 10);
auto timer_callback =
[this]() -> void {
[this]() {
auto message = std_msgs::msg::String();
message.data = "Hello, world! " + std::to_string(this->count_++);
RCLCPP_INFO(this->get_logger(), "Publishing: '%s'", message.data.c_str());
Expand Down
1 change: 0 additions & 1 deletion rclcpp/topics/minimal_publisher/member_function.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
// limitations under the License.

#include <chrono>
#include <functional>
#include <memory>
#include <string>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
// limitations under the License.

#include <chrono>
#include <functional>
#include <memory>
#include <string>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
// limitations under the License.

#include <chrono>
#include <functional>
#include <memory>
#include <sstream>
#include <string>
Expand Down
Loading