コード例 #1
0
ファイル: test_time.cpp プロジェクト: shizhexu/rcl
/* Tests the rcl_system_time_point_now() function.
 */
TEST_F(TestTimeFixture, test_rcl_system_time_point_now) {
  assert_no_realloc_begin();
  rcl_ret_t ret;
  // Check for invalid argument error condition (allowed to alloc).
  ret = rcl_system_time_point_now(nullptr);
  EXPECT_EQ(ret, RCL_RET_INVALID_ARGUMENT) << rcl_get_error_string_safe();
  rcl_reset_error();
  assert_no_malloc_begin();
  assert_no_free_begin();
  // Check for normal operation (not allowed to alloc).
  rcl_system_time_point_t now = {0};
  ret = rcl_system_time_point_now(&now);
  assert_no_malloc_end();
  assert_no_realloc_end();
  assert_no_free_end();
  stop_memory_checking();
  EXPECT_EQ(ret, RCL_RET_OK) << rcl_get_error_string_safe();
  EXPECT_NE(now.nanoseconds, 0u);
  // Compare to std::chrono::system_clock time (within a second).
  now = {0};
  ret = rcl_system_time_point_now(&now);
  {
    std::chrono::system_clock::time_point now_sc = std::chrono::system_clock::now();
    auto now_ns = std::chrono::duration_cast<std::chrono::nanoseconds>(now_sc.time_since_epoch());
    int64_t now_ns_int = now_ns.count();
    int64_t now_diff = now.nanoseconds - now_ns_int;
    const int k_tolerance_ms = 1000;
    EXPECT_LE(llabs(now_diff), RCL_MS_TO_NS(k_tolerance_ms)) << "system_clock differs";
  }
}
コード例 #2
0
  bool add_handles_to_wait_set(rcl_wait_set_t * wait_set)
  {
    for (auto subscription : subscription_handles_) {
      if (rcl_wait_set_add_subscription(wait_set, subscription) != RCL_RET_OK) {
        RCUTILS_LOG_ERROR_NAMED(
          "rclcpp",
          "Couldn't add subscription to wait set: %s", rcl_get_error_string_safe());
        return false;
      }
    }

    for (auto client : client_handles_) {
      if (rcl_wait_set_add_client(wait_set, client) != RCL_RET_OK) {
        RCUTILS_LOG_ERROR_NAMED(
          "rclcpp",
          "Couldn't add client to wait set: %s", rcl_get_error_string_safe());
        return false;
      }
    }

    for (auto service : service_handles_) {
      if (rcl_wait_set_add_service(wait_set, service) != RCL_RET_OK) {
        RCUTILS_LOG_ERROR_NAMED(
          "rclcpp",
          "Couldn't add service to wait set: %s", rcl_get_error_string_safe());
        return false;
      }
    }

    for (auto timer : timer_handles_) {
      if (rcl_wait_set_add_timer(wait_set, timer) != RCL_RET_OK) {
        RCUTILS_LOG_ERROR_NAMED(
          "rclcpp",
          "Couldn't add timer to wait set: %s", rcl_get_error_string_safe());
        return false;
      }
    }

    for (auto guard_condition : guard_conditions_) {
      if (rcl_wait_set_add_guard_condition(wait_set, guard_condition) != RCL_RET_OK) {
        RCUTILS_LOG_ERROR_NAMED(
          "rclcpp",
          "Couldn't add guard_condition to wait set: %s",
          rcl_get_error_string_safe());
        return false;
      }
    }
    return true;
  }
コード例 #3
0
ファイル: test_subscription.cpp プロジェクト: dhood/rcl
 void TearDown()
 {
   assert_no_malloc_end();
   assert_no_realloc_end();
   assert_no_free_end();
   stop_memory_checking();
   set_on_unexpected_malloc_callback(nullptr);
   set_on_unexpected_realloc_callback(nullptr);
   set_on_unexpected_free_callback(nullptr);
   rcl_ret_t ret = rcl_node_fini(this->node_ptr);
   delete this->node_ptr;
   EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string_safe();
   ret = rcl_shutdown();
   EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string_safe();
 }
コード例 #4
0
 /**
  * This function is templated on the input message type, MessageT.
  * \param[in] msg A shared pointer to the message to send.
  */
 virtual void
 publish(std::unique_ptr<MessageT, MessageDeleter> & msg)
 {
   this->do_inter_process_publish(msg.get());
   if (store_intra_process_message_) {
     // Take the pointer from the unique_msg, release it and pass as a void *
     // to the ipm. The ipm should then capture it again as a unique_ptr of
     // the correct type.
     // TODO(wjwwood):
     //   investigate how to transfer the custom deleter (if there is one)
     //   from the incoming unique_ptr through to the ipm's unique_ptr.
     //   See: http://stackoverflow.com/questions/11002641/dynamic-casting-for-unique-ptr
     MessageT * msg_ptr = msg.get();
     msg.release();
     uint64_t message_seq =
       store_intra_process_message_(intra_process_publisher_id_, msg_ptr, typeid(MessageT));
     rcl_interfaces::msg::IntraProcessMessage ipm;
     ipm.publisher_id = intra_process_publisher_id_;
     ipm.message_sequence = message_seq;
     auto status = rcl_publish(&intra_process_publisher_handle_, &ipm);
     if (status != RCL_RET_OK) {
       // *INDENT-OFF* (prevent uncrustify from making unnecessary indents here)
       throw std::runtime_error(
         std::string("failed to publish intra process message: ") + rcl_get_error_string_safe());
       // *INDENT-ON*
     }
   } else {
     // Always destroy the message, even if we don't consume it, for consistency.
     msg.reset();
   }
 }
コード例 #5
0
ファイル: test_service.cpp プロジェクト: erlerobot/rcl
 void SetUp()
 {
   stop_memory_checking();
   rcl_ret_t ret;
   ret = rcl_init(0, nullptr, rcl_get_default_allocator());
   ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string_safe();
   this->node_ptr = new rcl_node_t;
   *this->node_ptr = rcl_get_zero_initialized_node();
   const char * name = "node_name";
   rcl_node_options_t node_options = rcl_node_get_default_options();
   ret = rcl_node_init(this->node_ptr, name, &node_options);
   ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string_safe();
   set_on_unexpected_malloc_callback([]() {ASSERT_FALSE(true) << "UNEXPECTED MALLOC";});
   set_on_unexpected_realloc_callback([]() {ASSERT_FALSE(true) << "UNEXPECTED REALLOC";});
   set_on_unexpected_free_callback([]() {ASSERT_FALSE(true) << "UNEXPECTED FREE";});
   start_memory_checking();
 }
コード例 #6
0
ファイル: client_fixture.cpp プロジェクト: dhood/rcl
bool
wait_for_client_to_be_ready(
  rcl_client_t * client,
  size_t max_tries,
  int64_t period_ms)
{
  rcl_wait_set_t wait_set = rcl_get_zero_initialized_wait_set();
  rcl_ret_t ret = rcl_wait_set_init(&wait_set, 0, 0, 0, 1, 0, rcl_get_default_allocator());
  if (ret != RCL_RET_OK) {
    fprintf(stderr, "Error in wait set init: %s\n", rcl_get_error_string_safe());
    return false;
  }
  auto wait_set_exit = make_scope_exit([&wait_set]() {
    if (rcl_wait_set_fini(&wait_set) != RCL_RET_OK) {
      fprintf(stderr, "Error in wait set fini: %s\n", rcl_get_error_string_safe());
      throw std::runtime_error("error while waiting for client");
    }
  });
  size_t iteration = 0;
  do {
    ++iteration;
    if (rcl_wait_set_clear_clients(&wait_set) != RCL_RET_OK) {
      fprintf(stderr, "Error in wait_set_clear_clients: %s\n", rcl_get_error_string_safe());
      return false;
    }
    if (rcl_wait_set_add_client(&wait_set, client) != RCL_RET_OK) {
      fprintf(stderr, "Error in wait_set_add_client: %s\n", rcl_get_error_string_safe());
      return false;
    }
    ret = rcl_wait(&wait_set, RCL_MS_TO_NS(period_ms));
    if (ret == RCL_RET_TIMEOUT) {
      continue;
    }
    if (ret != RCL_RET_OK) {
      fprintf(stderr, "Error in wait: %s\n", rcl_get_error_string_safe());
      return false;
    }
    for (size_t i = 0; i < wait_set.size_of_clients; ++i) {
      if (wait_set.clients[i] && wait_set.clients[i] == client) {
        return true;
      }
    }
  } while (iteration < max_tries);
  return false;
}
コード例 #7
0
ファイル: test_subscription.cpp プロジェクト: dhood/rcl
class CLASSNAME (TestSubscriptionFixture, RMW_IMPLEMENTATION) : public ::testing::Test
{
public:
  rcl_node_t * node_ptr;
  void SetUp()
  {
    stop_memory_checking();
    rcl_ret_t ret;
    ret = rcl_init(0, nullptr, rcl_get_default_allocator());
    ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string_safe();
    this->node_ptr = new rcl_node_t;
    *this->node_ptr = rcl_get_zero_initialized_node();
    const char * name = "node_name";
    rcl_node_options_t node_options = rcl_node_get_default_options();
    ret = rcl_node_init(this->node_ptr, name, &node_options);
    ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string_safe();
    set_on_unexpected_malloc_callback([]() {ASSERT_FALSE(true) << "UNEXPECTED MALLOC";});
    set_on_unexpected_realloc_callback([]() {ASSERT_FALSE(true) << "UNEXPECTED REALLOC";});
    set_on_unexpected_free_callback([]() {ASSERT_FALSE(true) << "UNEXPECTED FREE";});
    start_memory_checking();
  }
コード例 #8
0
ファイル: utilities.cpp プロジェクト: esteve/rclcpp
void
rclcpp::utilities::init(int argc, char * argv[])
{
  g_is_interrupted.store(false);
  if (rcl_init(argc, argv, rcl_get_default_allocator()) != RCL_RET_OK) {
    // *INDENT-OFF* (prevent uncrustify from making unnecessary indents here)
    throw std::runtime_error(
      std::string("failed to initialize rmw implementation: ") + rcl_get_error_string_safe());
    // *INDENT-ON*
  }
#ifdef HAS_SIGACTION
  struct sigaction action;
  memset(&action, 0, sizeof(action));
  sigemptyset(&action.sa_mask);
  action.sa_sigaction = ::signal_handler;
  action.sa_flags = SA_SIGINFO;
  ssize_t ret = sigaction(SIGINT, &action, &old_action);
  if (ret == -1)
#else
  ::old_signal_handler = std::signal(SIGINT, ::signal_handler);
  // NOLINTNEXTLINE(readability/braces)
  if (::old_signal_handler == SIG_ERR)
#endif
  {
    const size_t error_length = 1024;
    // NOLINTNEXTLINE(runtime/arrays)
    char error_string[error_length];
#ifndef _WIN32
#ifdef _GNU_SOURCE
    char * msg = strerror_r(errno, error_string, error_length);
    if (msg != error_string) {
      strncpy(error_string, msg, error_length);
      msg[error_length - 1] = '\0';
    }
#else
    int error_status = strerror_r(errno, error_string, error_length);
    if (error_status != 0) {
      throw std::runtime_error("Failed to get error string for errno: " + std::to_string(errno));
    }
#endif
#else
    strerror_s(error_string, error_length, errno);
#endif
    // *INDENT-OFF* (prevent uncrustify from making unnecessary indents here)
    throw std::runtime_error(
      std::string("Failed to set SIGINT signal handler: (" + std::to_string(errno) + ")") +
      error_string);
    // *INDENT-ON*
  }
}
コード例 #9
0
ファイル: test_time.cpp プロジェクト: shizhexu/rcl
/* Tests the rcl_steady_time_point_now() function.
 */
TEST_F(TestTimeFixture, test_rcl_steady_time_point_now) {
  assert_no_realloc_begin();
  rcl_ret_t ret;
  // Check for invalid argument error condition (allowed to alloc).
  ret = rcl_steady_time_point_now(nullptr);
  EXPECT_EQ(ret, RCL_RET_INVALID_ARGUMENT) << rcl_get_error_string_safe();
  rcl_reset_error();
  assert_no_malloc_begin();
  assert_no_free_begin();
  // Check for normal operation (not allowed to alloc).
  rcl_steady_time_point_t now = {0};
  ret = rcl_steady_time_point_now(&now);
  assert_no_malloc_end();
  assert_no_realloc_end();
  assert_no_free_end();
  stop_memory_checking();
  EXPECT_EQ(ret, RCL_RET_OK) << rcl_get_error_string_safe();
  EXPECT_NE(now.nanoseconds, 0u);
  // Compare to std::chrono::steady_clock difference of two times (within a second).
  now = {0};
  ret = rcl_steady_time_point_now(&now);
  std::chrono::steady_clock::time_point now_sc = std::chrono::steady_clock::now();
  EXPECT_EQ(ret, RCL_RET_OK) << rcl_get_error_string_safe();
  // Wait for a little while.
  std::this_thread::sleep_for(std::chrono::milliseconds(100));
  // Then take a new timestamp with each and compare.
  rcl_steady_time_point_t later;
  ret = rcl_steady_time_point_now(&later);
  std::chrono::steady_clock::time_point later_sc = std::chrono::steady_clock::now();
  EXPECT_EQ(ret, RCL_RET_OK) << rcl_get_error_string_safe();
  int64_t steady_diff = later.nanoseconds - now.nanoseconds;
  int64_t sc_diff =
    std::chrono::duration_cast<std::chrono::nanoseconds>(later_sc - now_sc).count();
  const int k_tolerance_ms = 1;
  EXPECT_LE(llabs(steady_diff - sc_diff), RCL_MS_TO_NS(k_tolerance_ms)) << "steady_clock differs";
}
コード例 #10
0
ファイル: test_service.cpp プロジェクト: erlerobot/rcl
void
wait_for_service_to_be_ready(
  rcl_service_t * service,
  size_t max_tries,
  int64_t period_ms,
  bool & success)
{
  rcl_wait_set_t wait_set = rcl_get_zero_initialized_wait_set();
  rcl_ret_t ret = rcl_wait_set_init(&wait_set, 0, 0, 0, 0, 1, rcl_get_default_allocator());
  ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string_safe();
  auto wait_set_exit = make_scope_exit([&wait_set]() {
    stop_memory_checking();
    rcl_ret_t ret = rcl_wait_set_fini(&wait_set);
    ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string_safe();
  });
  size_t iteration = 0;
  do {
    ++iteration;
    ret = rcl_wait_set_clear_services(&wait_set);
    ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string_safe();
    ret = rcl_wait_set_add_service(&wait_set, service);
    ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string_safe();
    ret = rcl_wait(&wait_set, RCL_MS_TO_NS(period_ms));
    if (ret == RCL_RET_TIMEOUT) {
      continue;
    }
    ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string_safe();
    for (size_t i = 0; i < wait_set.size_of_services; ++i) {
      if (wait_set.services[i] && wait_set.services[i] == service) {
        success = true;
        return;
      }
    }
  } while (iteration < max_tries);
  success = false;
}
コード例 #11
0
ファイル: utilities.cpp プロジェクト: esteve/rclcpp
void
rclcpp::utilities::release_sigint_guard_condition(rcl_wait_set_t * waitset)
{
  std::lock_guard<std::mutex> lock(g_sigint_guard_cond_handles_mutex);
  auto kv = g_sigint_guard_cond_handles.find(waitset);
  if (kv != g_sigint_guard_cond_handles.end()) {
    if (rcl_guard_condition_fini(&kv->second) != RCL_RET_OK) {
      // *INDENT-OFF* (prevent uncrustify from making unnecessary indents here)
      throw std::runtime_error(std::string(
        "Failed to destroy sigint guard condition: ") +
        rcl_get_error_string_safe());
      // *INDENT-ON*
    }
    g_sigint_guard_cond_handles.erase(kv);
  } else {
    // *INDENT-OFF* (prevent uncrustify from making unnecessary indents here)
    throw std::runtime_error(std::string(
      "Tried to release sigint guard condition for nonexistent waitset"));
    // *INDENT-ON*
  }
}
コード例 #12
0
ファイル: utilities.cpp プロジェクト: esteve/rclcpp
rcl_guard_condition_t *
rclcpp::utilities::get_sigint_guard_condition(rcl_wait_set_t * waitset)
{
  std::lock_guard<std::mutex> lock(g_sigint_guard_cond_handles_mutex);
  auto kv = g_sigint_guard_cond_handles.find(waitset);
  if (kv != g_sigint_guard_cond_handles.end()) {
    return &kv->second;
  } else {
    rcl_guard_condition_t handle =
      rcl_get_zero_initialized_guard_condition();
    rcl_guard_condition_options_t options = rcl_guard_condition_get_default_options();
    if (rcl_guard_condition_init(&handle, options) != RCL_RET_OK) {
      // *INDENT-OFF* (prevent uncrustify from making unnecessary indents here)
      throw std::runtime_error(std::string(
        "Couldn't initialize guard condition: ") + rcl_get_error_string_safe());
      // *INDENT-ON*
    }
    g_sigint_guard_cond_handles[waitset] = handle;
    return &g_sigint_guard_cond_handles[waitset];
  }
}
コード例 #13
0
ファイル: utilities.cpp プロジェクト: esteve/rclcpp
signal_handler(int signal_value)
#endif
{
  // TODO(wjwwood): remove? move to console logging at some point?
  printf("signal_handler(%d)\n", signal_value);
#ifdef HAS_SIGACTION
  if (old_action.sa_flags & SA_SIGINFO) {
    if (old_action.sa_sigaction != NULL) {
      old_action.sa_sigaction(signal_value, siginfo, context);
    }
  } else {
    // *INDENT-OFF*
    if (
      old_action.sa_handler != NULL &&  // Is set
      old_action.sa_handler != SIG_DFL &&  // Is not default
      old_action.sa_handler != SIG_IGN)  // Is not ignored
    // *INDENT-ON*
    {
      old_action.sa_handler(signal_value);
    }
  }
#else
  if (old_signal_handler) {
    old_signal_handler(signal_value);
  }
#endif
  g_signal_status = signal_value;
  {
    std::lock_guard<std::mutex> lock(g_sigint_guard_cond_handles_mutex);
    for (auto const & kv : g_sigint_guard_cond_handles) {
      rcl_ret_t status = rcl_trigger_guard_condition(&(kv.second));
      if (status != RCL_RET_OK) {
        fprintf(stderr,
          "[rclcpp::error] failed to trigger guard condition: %s\n", rcl_get_error_string_safe());
      }
    }
  }
  g_is_interrupted.store(true);
  g_interrupt_condition_variable.notify_all();
}
コード例 #14
0
ファイル: utilities.cpp プロジェクト: esteve/rclcpp
void
rclcpp::utilities::shutdown()
{
  g_signal_status = SIGINT;
  {
    std::lock_guard<std::mutex> lock(g_sigint_guard_cond_handles_mutex);
    for (auto const & kv : g_sigint_guard_cond_handles) {
      if (rcl_trigger_guard_condition(&(kv.second)) != RCL_RET_OK) {
        fprintf(stderr,
          "[rclcpp::error] failed to trigger sigint guard condition: %s\n",
          rcl_get_error_string_safe());
      }
    }
  }
  g_is_interrupted.store(true);
  g_interrupt_condition_variable.notify_all();
  {
    std::lock_guard<std::mutex> lock(on_shutdown_mutex_);
    for (auto & on_shutdown_callback : on_shutdown_callbacks_) {
      on_shutdown_callback();
    }
  }
}
コード例 #15
0
ファイル: exceptions.cpp プロジェクト: jwang11/rclcpp
RCLErrorBase::RCLErrorBase(rcl_ret_t ret, const rcl_error_state_t * error_state)
: ret(ret), message(error_state->message), file(error_state->file), line(error_state->line_number),
  formatted_message(rcl_get_error_string_safe())
{}
コード例 #16
0
ファイル: service_fixture.cpp プロジェクト: dhood/rcl
int main(int argc, char ** argv)
{
  int main_ret = 0;
  {
    if (rcl_init(argc, argv, rcl_get_default_allocator()) != RCL_RET_OK) {
      fprintf(stderr, "Error in rcl init: %s\n", rcl_get_error_string_safe());
      return -1;
    }
    rcl_node_t node = rcl_get_zero_initialized_node();
    const char * name = "node_name";
    rcl_node_options_t node_options = rcl_node_get_default_options();
    if (rcl_node_init(&node, name, &node_options) != RCL_RET_OK) {
      fprintf(stderr, "Error in node init: %s\n", rcl_get_error_string_safe());
      return -1;
    }
    auto node_exit = make_scope_exit([&main_ret, &node]() {
      if (rcl_node_fini(&node) != RCL_RET_OK) {
        fprintf(stderr, "Error in node fini: %s\n", rcl_get_error_string_safe());
        main_ret = -1;
      }
    });

    const rosidl_service_type_support_t * ts = ROSIDL_GET_TYPE_SUPPORT(
      example_interfaces, srv, AddTwoInts);
    const char * topic = "add_two_ints";

    rcl_service_t service = rcl_get_zero_initialized_service();
    rcl_service_options_t service_options = rcl_service_get_default_options();
    rcl_ret_t ret = rcl_service_init(&service, &node, ts, topic, &service_options);
    if (ret != RCL_RET_OK) {
      fprintf(stderr, "Error in service init: %s\n", rcl_get_error_string_safe());
      return -1;
    }

    auto service_exit = make_scope_exit([&main_ret, &service, &node]() {
      if (rcl_service_fini(&service, &node)) {
        fprintf(stderr, "Error in service fini: %s\n", rcl_get_error_string_safe());
        main_ret = -1;
      }
    });

    std::this_thread::sleep_for(std::chrono::milliseconds(1000));

    // Initialize a response.
    example_interfaces__srv__AddTwoInts_Response service_response;
    example_interfaces__srv__AddTwoInts_Response__init(&service_response);
    auto response_exit = make_scope_exit([&service_response]() {
      example_interfaces__srv__AddTwoInts_Response__fini(&service_response);
    });

    // Block until a client request comes in.

    if (!wait_for_service_to_be_ready(&service, 1000, 100)) {
      fprintf(stderr, "Service never became ready\n");
      return -1;
    }

    // Take the pending request.
    example_interfaces__srv__AddTwoInts_Request service_request;
    example_interfaces__srv__AddTwoInts_Request__init(&service_request);
    auto request_exit = make_scope_exit([&service_request]() {
      example_interfaces__srv__AddTwoInts_Request__fini(&service_request);
    });
    rmw_request_id_t header;
    // TODO(jacquelinekay) May have to check for timeout error codes
    if (rcl_take_request(&service, &header, &service_request) != RCL_RET_OK) {
      fprintf(stderr, "Error in take_request: %s\n", rcl_get_error_string_safe());
      return -1;
    }

    // Sum the request and send the response.
    service_response.sum = service_request.a + service_request.b;
    if (rcl_send_response(&service, &header, &service_response) != RCL_RET_OK) {
      fprintf(stderr, "Error in send_response: %s\n", rcl_get_error_string_safe());
      return -1;
    }
    // Our scope exits should take care of fini for everything
  }
  return main_ret;
}
コード例 #17
0
ファイル: client_fixture.cpp プロジェクト: dhood/rcl
int main(int argc, char ** argv)
{
  int main_ret = 0;
  {
    if (rcl_init(argc, argv, rcl_get_default_allocator()) != RCL_RET_OK) {
      fprintf(stderr, "Error in rcl init: %s\n", rcl_get_error_string_safe());
      return -1;
    }
    rcl_node_t node = rcl_get_zero_initialized_node();
    const char * name = "node_name";
    rcl_node_options_t node_options = rcl_node_get_default_options();
    if (rcl_node_init(&node, name, &node_options) != RCL_RET_OK) {
      fprintf(stderr, "Error in node init: %s\n", rcl_get_error_string_safe());
      return -1;
    }
    auto node_exit = make_scope_exit([&main_ret, &node]() {
      if (rcl_node_fini(&node) != RCL_RET_OK) {
        fprintf(stderr, "Error in node fini: %s\n", rcl_get_error_string_safe());
        main_ret = -1;
      }
    });

    const rosidl_service_type_support_t * ts = ROSIDL_GET_TYPE_SUPPORT(
      example_interfaces, srv, AddTwoInts);
    const char * topic = "add_two_ints";

    rcl_client_t client = rcl_get_zero_initialized_client();
    rcl_client_options_t client_options = rcl_client_get_default_options();
    rcl_ret_t ret = rcl_client_init(&client, &node, ts, topic, &client_options);
    if (ret != RCL_RET_OK) {
      fprintf(stderr, "Error in client init: %s\n", rcl_get_error_string_safe());
      return -1;
    }

    auto client_exit = make_scope_exit([&client, &main_ret, &node]() {
      if (rcl_client_fini(&client, &node)) {
        fprintf(stderr, "Error in client fini: %s\n", rcl_get_error_string_safe());
        main_ret = -1;
      }
    });

    // Initialize a request.
    example_interfaces__srv__AddTwoInts_Request client_request;
    example_interfaces__srv__AddTwoInts_Request__init(&client_request);
    client_request.a = 1;
    client_request.b = 2;
    int64_t sequence_number;

    if (rcl_send_request(&client, &client_request, &sequence_number)) {
      fprintf(stderr, "Error in send request: %s\n", rcl_get_error_string_safe());
      return -1;
    }

    if (sequence_number != 1) {
      fprintf(stderr, "Got invalid sequence number\n");
      return -1;
    }

    example_interfaces__srv__AddTwoInts_Request__fini(&client_request);

    // Initialize the response owned by the client and take the response.
    example_interfaces__srv__AddTwoInts_Response client_response;
    example_interfaces__srv__AddTwoInts_Response__init(&client_response);

    if (!wait_for_client_to_be_ready(&client, 1000, 100)) {
      fprintf(stderr, "Client never became ready\n");
      return -1;
    }
    rmw_request_id_t header;
    if (rcl_take_response(&client, &header, &client_response) != RCL_RET_OK) {
      fprintf(stderr, "Error in send response: %s\n", rcl_get_error_string_safe());
      return -1;
    }

    example_interfaces__srv__AddTwoInts_Response__fini(&client_response);
  }

  return main_ret;
}
コード例 #18
0
ファイル: test_service.cpp プロジェクト: erlerobot/rcl
/* Basic nominal test of a service.
 */
TEST_F(TestServiceFixture, test_service_nominal) {
  stop_memory_checking();
  rcl_ret_t ret;
  const rosidl_service_type_support_t * ts = ROSIDL_GET_TYPE_SUPPORT(
    example_interfaces, srv, AddTwoInts);
  const char * topic = "add_two_ints";

  rcl_service_t service = rcl_get_zero_initialized_service();
  rcl_service_options_t service_options = rcl_service_get_default_options();
  ret = rcl_service_init(&service, this->node_ptr, ts, topic, &service_options);
  ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string_safe();

  // Check that the service name matches what we assigned.
  EXPECT_EQ(strcmp(rcl_service_get_service_name(&service), topic), 0);
  auto service_exit = make_scope_exit([&service, this]() {
    stop_memory_checking();
    rcl_ret_t ret = rcl_service_fini(&service, this->node_ptr);
    EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string_safe();
  });

  rcl_client_t client = rcl_get_zero_initialized_client();
  rcl_client_options_t client_options = rcl_client_get_default_options();
  ret = rcl_client_init(&client, this->node_ptr, ts, topic, &client_options);
  ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string_safe();
  auto client_exit = make_scope_exit([&client, this]() {
    stop_memory_checking();
    rcl_ret_t ret = rcl_client_fini(&client, this->node_ptr);
    EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string_safe();
  });


  // TODO(wjwwood): add logic to wait for the connection to be established
  //                use count_services busy wait mechanism
  //                until then we will sleep for a short period of time
  std::this_thread::sleep_for(std::chrono::milliseconds(1000));

  // Initialize a request.
  example_interfaces__srv__AddTwoInts_Request client_request;
  example_interfaces__srv__AddTwoInts_Request__init(&client_request);
  client_request.a = 1;
  client_request.b = 2;
  int64_t sequence_number;
  ret = rcl_send_request(&client, &client_request, &sequence_number);
  EXPECT_EQ(sequence_number, 1);
  example_interfaces__srv__AddTwoInts_Request__fini(&client_request);
  ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string_safe();

  bool success;
  wait_for_service_to_be_ready(&service, 10, 100, success);
  ASSERT_TRUE(success);

  // This scope simulates the service responding in a different context so that we can
  // test take_request/send_response in a single-threaded, deterministic execution.
  {
    // Initialize a response.
    example_interfaces__srv__AddTwoInts_Response service_response;
    example_interfaces__srv__AddTwoInts_Response__init(&service_response);
    auto msg_exit = make_scope_exit([&service_response]() {
      stop_memory_checking();
      example_interfaces__srv__AddTwoInts_Response__fini(&service_response);
    });

    // Initialize a separate instance of the request and take the pending request.
    example_interfaces__srv__AddTwoInts_Request service_request;
    example_interfaces__srv__AddTwoInts_Request__init(&service_request);
    rmw_request_id_t header;
    ret = rcl_take_request(&service, &header, &service_request);
    ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string_safe();

    EXPECT_EQ(1, service_request.a);
    EXPECT_EQ(2, service_request.b);
    // Simulate a response callback by summing the request and send the response..
    service_response.sum = service_request.a + service_request.b;
    ret = rcl_send_response(&service, &header, &service_response);
    ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string_safe();
  }
  wait_for_service_to_be_ready(&service, 10, 100, success);

  // Initialize the response owned by the client and take the response.
  example_interfaces__srv__AddTwoInts_Response client_response;
  example_interfaces__srv__AddTwoInts_Response__init(&client_response);

  rmw_request_id_t header;
  ret = rcl_take_response(&client, &header, &client_response);
  ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string_safe();
  EXPECT_EQ(client_response.sum, 3);
  EXPECT_EQ(header.sequence_number, 1);
}