micro-ROS / micro-ROS/micro_ros_setup

Topic created but no data communicating with agent using custom udp transport

オープン
#747 コメント 1 件 リアクション 0 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

主要言語
Shell
スター
509
フォーク
183
平均マージ
22時間 26分
マージ済み PR(30日)
7

説明

- Hardware description: Linux Host machine
- RTOS: Linux
- Installation type: micro-ros-setup
- Version or commit hash: humble

#### Steps to reproduce the issue
Hi, I'm new to ros and microros. I'm trying to run microros on an resources constraint **custom linux board** .
And **first testing it on my Linux Host**. I've built the static library from the tutorial : https://micro.ros.org/docs/tutorials/advanced/create_custom_static_library/
**toolchain.cmake** and **colcon.meta** are below.

Next step I've write my **custom udp transport** as below.
Then compile the code as an executable file and run it.
And I run the agent on the same host machine from the tutorial :
https://micro.ros.org/docs/tutorials/core/first_application_linux/

#### Expected behavior
Expected to publish data.
#### Actual behavior
It has success create the topic `ros2 topic list`
but `ros2 topic echo` didn't show anything

![topic](https://github.com/user-attachments/assets/561aacf5-6a96-46da-87d1-7311219adc27)
![agent](https://github.com/user-attachments/assets/ccf06af3-46de-459e-99b9-131b2801dd01)

#### Additional information
`````
# toolchain.cmake

set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_CROSSCOMPILING 0)
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)

set(CMAKE_C_COMPILER /usr/bin/gcc)
set(CMAKE_CXX_COMPILER /usr/bin/g++)

set(CMAKE_C_COMPILER_WORKS 1 CACHE INTERNAL "")
set(CMAKE_CXX_COMPILER_WORKS 1 CACHE INTERNAL "")

set(FLAGS "-O2 -ffunction-sections -fdata-sections" CACHE STRING "" FORCE)

set(CMAKE_C_FLAGS_INIT "-std=c11 ${FLAGS}" CACHE STRING "" FORCE)
set(CMAKE_CXX_FLAGS_INIT "-std=c++11 ${FLAGS}" CACHE STRING "" FORCE)

set(__BIG_ENDIAN__ 0)
`````
```
# colcon.meta

{
"names": {
"tracetools": {
"cmake-args": [
"-DTRACETOOLS_DISABLED=ON",
"-DTRACETOOLS_STATUS_CHECKING_TOOL=OFF"
]
},
"rosidl_typesupport": {
"cmake-args": [
"-DROSIDL_TYPESUPPORT_SINGLE_TYPESUPPORT=ON"
]
},
"rcl": {
"cmake-args": [
"-DBUILD_TESTING=OFF",
"-DRCL_COMMAND_LINE_ENABLED=OFF",
"-DRCL_LOGGING_ENABLED=OFF"
]
},
"rcutils": {
"cmake-args": [
"-DENABLE_TESTING=OFF",
"-DRCUTILS_NO_FILESYSTEM=ON",
"-DRCUTILS_NO_THREAD_SUPPORT=ON",
"-DRCUTILS_NO_64_ATOMIC=ON",
"-DRCUTILS_AVOID_DYNAMIC_ALLOCATION=ON"
]
},
"microxrcedds_client": {
"cmake-args": [
"-DUCLIENT_PIC=OFF",
"-DUCLIENT_PROFILE_UDP=OFF",
"-DUCLIENT_PROFILE_TCP=OFF",
"-DUCLIENT_PROFILE_DISCOVERY=OFF",
"-DUCLIENT_PROFILE_SERIAL=OFF",
"-UCLIENT_PROFILE_STREAM_FRAMING=ON",
"-DUCLIENT_PROFILE_CUSTOM_TRANSPORT=ON"
]
},
"rmw_microxrcedds": {
"cmake-args": [
"-DRMW_UXRCE_MAX_NODES=1",
"-DRMW_UXRCE_MAX_PUBLISHERS=5",
"-DRMW_UXRCE_MAX_SUBSCRIPTIONS=5",
"-DRMW_UXRCE_MAX_SERVICES=1",
"-DRMW_UXRCE_MAX_CLIENTS=1",
"-DRMW_UXRCE_MAX_HISTORY=4",
"-DRMW_UXRCE_TRANSPORT=custom"
]
}
}
}
```

```
// custom_transport.h

#include
#include
#include
#include
#include
#include

#include
#include

struct custom_transport_args{
std::string address;
uint16_t port;
};

bool custom_transport_open(struct uxrCustomTransport *transport);
bool custom_transport_close(struct uxrCustomTransport *transport);
size_t custom_transport_write(struct uxrCustomTransport *transport, const uint8_t *buf, size_t len, uint8_t *errcode);
size_t custom_transport_read(struct uxrCustomTransport *transport, uint8_t *buf, size_t len, int timeout, uint8_t *errcode);

static inline void set_custom_udp_transports(std::string agent_ip, uint16_t agent_port){
static struct custom_transport_args arg;
arg.address = agent_ip;
arg.port = agent_port;

rmw_uros_set_custom_transport(
false,
(void *) &arg,
custom_transport_open,
custom_transport_close,
custom_transport_write,
custom_transport_read
);
}
```
```
// custom_transport.cpp

#include
int sock_fd;
struct sockaddr_in serverAddr;

bool custom_transport_open(struct uxrCustomTransport *transport){
struct custom_transport_args *args = (struct custom_transport_args *) transport->args;

if((sock_fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) return false;

memset(&serverAddr, 0, sizeof(serverAddr));

// Filling server information
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(args->port);
int ret = inet_pton(AF_INET, args->address.c_str(), &serverAddr.sin_addr);

if(ret <= 0) return false;

printf("\tOpen...\n");
return true;
}

bool custom_transport_close(struct uxrCustomTransport *transport){
close(sock_fd);
printf("\tClose...\n");
return true;
}
size_t custom_transport_write(struct uxrCustomTransport *transport, const uint8_t *buf, size_t len, uint8_t *errcode){
//(void)errcode;
ssize_t sent = sendto(sock_fd, buf, len, MSG_CONFIRM, (const struct sockaddr *) &serverAddr, sizeof(serverAddr));
if(sent < 0){
errcode = (uint8_t *) sent;
}

printf("\tWrite...\n");
return sent;
}
size_t custom_transport_read(struct uxrCustomTransport *transport, uint8_t *buf, size_t len, int timeout, uint8_t *errcode){
//(void)errcode;
socklen_t sock_len;

struct timeval timev;
timev.tv_sec = timeout / 1000;
timev.tv_usec = (timeout % 1000) * 1000;
setsockopt(sock_fd, SOL_SOCKET, SO_RCVTIMEO, &timev, sizeof(timev));

ssize_t read = recvfrom(sock_fd, buf, len, MSG_WAITALL, (struct sockaddr *) &serverAddr, &sock_len);
if(read < 0){
errcode = (uint8_t *) read;
return 0;
}

printf("\tRead...\n");
return read;
}
```
```
// main.cpp

#include
#include
#include
#include
#include
#include
#include

#include
#include
#include

#define RCCHECK(fn) { rcl_ret_t temp_rc = fn; if((temp_rc != RCL_RET_OK)){printf("Failed status on line %d: %d. Aborting.\n",__LINE__,(int)temp_rc); return 1;}}
#define RCSOFTCHECK(fn) { rcl_ret_t temp_rc = fn; if((temp_rc != RCL_RET_OK)){printf("Failed status on line %d: %d. Continuing.\n",__LINE__,(int)temp_rc);}}

std::string agent_ip = "127.0.0.1";
uint16_t agent_port = 8080;

rcl_publisher_t publisher;
std_msgs__msg__Int32 msg;

void timer_callback(rcl_timer_t * timer, int64_t last_call_time){
printf("Timer call back...\n");
(void) last_call_time;
if (timer != NULL){
RCSOFTCHECK(rcl_publish(&publisher, &msg, NULL));
printf("Sent: %d\n", msg.data);
msg.data++;
}
}

int main(){
// set custom transport
set_custom_udp_transports(agent_ip, agent_port);

rcl_allocator_t allocator = rcl_get_default_allocator();
rclc_support_t support;

// create init_options
RCCHECK(rclc_support_init(&support, 0, NULL, &allocator));

// create node
rcl_node_t node;
RCCHECK(rclc_node_init_default(&node, "int32_publisher_rclc", "", &support));

// create publisher
RCCHECK(rclc_publisher_init_default(
&publisher,
&node,
ROSIDL_GET_MSG_TYPE_SUPPORT(std_msgs, msg, Int32),
"std_msgs_msg_Int32"));

// create timer,
rcl_timer_t timer;
const unsigned int timer_timeout = 1000;

RCCHECK(rclc_timer_init_default(
&timer,
&support,
RCL_MS_TO_NS(timer_timeout),
timer_callback));

// create executor
rclc_executor_t executor = rclc_executor_get_zero_initialized_executor();
RCCHECK(rclc_executor_init(&executor, &support.context, 1, &allocator));
RCCHECK(rclc_executor_add_timer(&executor, &timer));

msg.data = 0;

rclc_executor_spin(&executor);

RCCHECK(rcl_publisher_fini(&publisher, &node));
RCCHECK(rcl_node_fini(&node));
}
```

コントリビューションガイド

コントリビューションガイドを開く

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

調査の方向性

custom_transport.cpp と main.cpp から始め、次にカスタム実行可能ファイルを agent とともに実行し、ros2 topic echo を確認する前にトランスポートコールバックがデータを交換しているかを調べます。カスタム UDP セットアップを、リンクされている micro-ROS チュートリアルと比較します。既存の Int32 publisher が ros2 topic echo を通じて確認できるメッセージを生成すれば完了です。

索引モデルが issue の本文から書いたものです。

評価

技術スタック
cpp, linux
領域
embedded-iot, networking
issue の種類
バグ
難易度
4/5
見積もり時間
3〜5日
活発さ
静か
明瞭さ
おおむね明確
初心者へのやさしさ
42/100

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。