ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question
1

Communication between rclpy client and rlcpp server

asked 2022-07-20 16:25:31 -0500

asmartbaby gravatar image

updated 2022-07-25 12:15:11 -0500

I am working on converting a ros 1 (noetic) project to ros 2 (foxy). I am on Ubuntu 20.04 I am running into an issue where the python node call the service and the cpp node receives the request and fills out the response. The python node however never receives the response. Any

Here is the function in the python node that calls the service

    def _adjust_time(
        self,
        time: rclpy.builtin_interfaces.msg.Time,
        clock_convert: rclpy.client.Client,
    ) -> float:
        """Convert the ROS time to be compatible with the data time."""
        self.get_logger().info("Adjusting time")
        req = TimeConversion.Request()
        req.ros_time = time
        future = clock_convert.call_async(req)
        rclpy.spin_until_future_complete(self, future)
        rclpy.logging.get_logger().info("future complete")
        res = future.result()
        rclpy.logging.get_logger().info(f"Converted time: {res}")
        calendar = res.calendar
        return _calendar_to_seconds(calendar)

Here is the cpp node

#include "rclcpp/rclcpp.hpp"
#include "bus_msgs/srv/time_conversion.hpp"

#include <time.h>
#include <chrono>

// Modality enumeration
enum ConversionMode
{
  WALL = 0,
  MIDNIGHT = 1
};

std::chrono::system_clock::time_point start_time;
ConversionMode mode;

/*!
 * \brief Creates a callback to convert a ros::time to a wall clock message
 */
bool conversionCallback(std::shared_ptr<bus_msgs::srv::TimeConversion::Request> req,
                        std::shared_ptr<bus_msgs::srv::TimeConversion::Response> res)
{
  time_t updated_time;  // Time for conversion

  // *** Conversion for midnight mode *** //
  if (mode == ConversionMode::MIDNIGHT)
  {
    RCLCPP_INFO(rclcpp::get_logger("clock_conversion_node"), "Converting to midnight mode");
    // Add the ros time seconds
    std::chrono::system_clock::time_point update =
        start_time + std::chrono::duration<int, std::ratio<1> >(req->ros_time.sec);

    // Extract the time values
    updated_time = std::chrono::system_clock::to_time_t(update);
  }
  else if (mode == ConversionMode::WALL)
  {
    RCLCPP_INFO(rclcpp::get_logger("clock_conversion_node"), "Converting to wall clock mode");
    updated_time =
        static_cast<time_t>(req->ros_time.sec);  // Note that this assumes time_t implemented as seconds from 1970
  }
  else
  {
    RCLCPP_ERROR(rclcpp::get_logger("rclcpp"), "clock_conversion_node::conversionCallback() Unaccounted for mode");
  }

  // Create the response
  struct tm* timeinfo = localtime(&updated_time);
  res->calendar.nanosec = req->ros_time.nanosec;
  res->calendar.sec = timeinfo->tm_sec;
  res->calendar.min = timeinfo->tm_min;
  res->calendar.hour = timeinfo->tm_hour;
  res->calendar.mday = timeinfo->tm_mday;
  res->calendar.mon = timeinfo->tm_mon;
  res->calendar.year = timeinfo->tm_year;
  res->calendar.wday = timeinfo->tm_wday;
  res->calendar.yday = timeinfo->tm_yday;
  res->calendar.isdst = timeinfo->tm_isdst;
  RCLCPP_INFO(rclcpp::get_logger("clock_conversion_node"), "Returning....");
  RCLCPP_INFO_STREAM(rclcpp::get_logger("clock_conversion_node"), "Returning: " << req->ros_time.sec);
  return true;
}

int main(int argc, char** argv)
{
  // Initialize ros and create a node handle
  rclcpp::init(argc, argv);
  auto node = rclcpp::Node::make_shared("clock_conversion_node");
  // Create parameters for reading in
  int mode_in = static_cast<int>(ConversionMode::WALL);
  int mday_in = 1;    // Day of the month (1-31)
  int mon_in = 2;     // Months since January (0-11)
  int year_in = 122;  // Years since 1900

  // Read in parameters
  if (!node->get_parameter("mode", mode_in))
  {
    RCLCPP_INFO(node->get_logger(), "Reading in mode from launch file.");
    node->declare_parameter("mode");
    node->get_parameter("mode", mode_in);
  }
  if (!node->get_parameter("start_mday", mday_in))
  {
    RCLCPP_INFO(node->get_logger(), "Reading in start_mday from launch file.");
    node->declare_parameter("start_mday");
    node->get_parameter("start_mday", mday_in);
  }
  if (!node->get_parameter("start_mon", mon_in))
  {
    RCLCPP_INFO(node->get_logger(), "Reading in start_mon from launch file.");
    node->declare_parameter("start_mon");
    node->get_parameter("start_mon", mon_in);
  }
  if (!node->get_parameter("start_year", year_in))
  {
    RCLCPP_INFO(node->get_logger(), "Reading in start_year from launch file.");
    node->declare_parameter("start_year");
    node->get_parameter("start_year", year_in);
  }

  // Make a time value from the inputs
  std::tm t{};
  t.tm_year = year_in;
  t.tm_mon = mon_in;
  t.tm_mday = mday_in;
  t.tm_hour = 0;
  t.tm_min = 0;
  t.tm_sec = 0;

  // Calculate the conversion varlables
  mode = static_cast<ConversionMode>(mode_in);
  start_time = std::chrono ...
(more)
edit retag flag offensive close merge delete

1 Answer

Sort by ยป oldest newest most voted
0

answered 2022-07-26 12:56:10 -0500

asmartbaby gravatar image

So I ended up figuring out what the problem was. The python function was nested in the callback of another service. Because I did not specify the callback group they defaulted to the same callback group which was mutually exclusive. I also did not specify a multi threaded executor so multiple callbacks could not be executed at the same time. Here is the article on callback groups if anyone else runs into this problem (Using Callback groups).

edit flag offensive delete link more

Comments

Thanks for the link.

Would you be able to post the code that fixed it for you?

Thanks

zsnafu gravatar image zsnafu  ( 2022-09-09 14:40:46 -0500 )edit

Question Tools

1 follower

Stats

Asked: 2022-07-20 16:25:31 -0500

Seen: 161 times

Last updated: Jul 26 '22