Giter VIP home page Giter VIP logo

rclex's Introduction

Hex version API docs License ci-latest ci-all_version

日本語のREADME

Rclex

Rclex is a ROS 2 client library for the functional language Elixir.

This library lets you perform basic ROS 2 behaviors by calling out from Elixir code into the RCL (ROS Client Library) API, which uses the ROS 2 common hierarchy.

Additionally, publisher-subscriber (PubSub) communication between nodes and associated callback functions are executed as Erlang lightweight processes. This enables the creation of and communication between a large number of fault-tolerant nodes while suppressing memory load.

What is ROS 2

ROS 2 (Robot Operating System 2) is a state-of-the-art Robot development platform. In ROS 2, each functional unit is exposed as a node, and by combining these nodes you can create different robot applications. Additionally, communication between nodes uses a PubSub model where publishers and subscribers exchange information by specifying a common topic name.

The main benefits of ROS 2 are that the DDS (Data Distribution Service) protocol was adopted for communication, and the library was divided into a hierarchical structure. This allows us to develop ROS 2 client libraries in various languages and, of course, to build robot applications in Elixir.

For details on ROS 2, see the official ROS 2 Documentation.

Recommended environment

Native environment

The basic and recommended environment is where the host (development) and the target (operation) are the same.

Currently, we use the following environment as the main development target:

  • Ubuntu 22.04.4 LTS (Jammy Jellyfish)
  • ROS 2 Humble Hawksbill
  • Elixir 1.15.7-otp-26
  • Erlang/OTP 26.2.2

We highly recommend using Humble for ROS 2 LTS distribution. Iron, the STS distribution, is experimentally supported and confirmed for the proper operation only in the native environment. See detail and status on Issue#228. Although we also use Foxy and Galactic as CI targets, they have already reached EOL.

For other environments used to check the operation of this library, please refer to here.

Docker environment

The pre-built Docker images are available at Docker Hub. You can also try the power of Rclex with it easily. Please check "Docker Environment" section for details.

Nerves device (target)

rclex can be operated onto Nerves. In this case, you do not need to prepare the ROS 2 environment on the host computer to build Nerves project (so awesome!).

Please refer to Use on Nerves section and b5g-ex/rclex_on_nerves example repository for more details!

Features

Currently, the Rclex API allows for the following:

  1. The ability to create a large number of publishers sending to the same topic.
  2. The ability to create large numbers of each combination of publishers, topics, and subscribers.

You can find the API documentation at https://hexdocs.pm/rclex.

Please refer rclex/rclex_examples for the examples of usage along with the sample code.

How to use

This section explains the quickstart for rclex in the native environment where ROS 2 and Elixir have been installed.

Create the project

First of all, create the Mix project as a normal Elixir project.

mix new rclex_usage
cd rclex_usage

Install rclex

rclex is available in Hex.

You can install this package into your project by adding rclex to your list of dependencies in mix.exs:

  defp deps do
    [
      ...
      {:rclex, "~> 0.10.1"},
      ...
    ]
  end

After that, execute mix deps.get into the project repository.

mix deps.get

Setup the ROS 2 environment

source /opt/ros/humble/setup.bash

Configure ROS 2 message types you want to use

Rclex provides pub/sub-based topic communication using the message type defined in ROS 2. Please refer here for more details about message types in ROS 2.

The message types you want to use in your project can be specified in ros2_message_types in config/config.exs. Multiple message types can be specified separated by comma ,.

The following config/config.exs example wants to use String type.

import Config

config :rclex, ros2_message_types: ["std_msgs/msg/String"]

Then, execute the following Mix task to generate required definitions and files for message types.

mix rclex.gen.msgs

When editing config/config.exs to change the message types, do mix rclex.gen.msgs again.

Write Rclex code

Now, you can acquire the environment for Rclex API! Of course, you can execute APIs on IEx directly.

Here is the simplest implementation example lib/rclex_usage.ex that will publish the string to /chatter topic.

defmodule RclexUsage do
  alias Rclex.Pkgs.StdMsgs

  def publish_message do
    Rclex.start_node("talker")
    Rclex.start_publisher(StdMsgs.Msg.String, "/chatter", "talker")

    data = "Hello World from Rclex!"
    msg = struct(StdMsgs.Msg.String, %{data: data})

    IO.puts("Rclex: Publishing: #{data}")
    Rclex.publish(msg, "/chatter", "talker")
  end
end

Please also check the examples for Rclex.

Build and Execute

Build your application as follows.

mix compile
iex -S mix

Operate the following command on IEx.

iex()> RclexUsage.publish_message
Rclex: Publishing: Hello World from Rclex!
:ok

You can confirm the above operation by subscribing with ros2 topic echo from the other terminal.

$ source /opt/ros/humble/setup.bash
$ ros2 topic echo /chatter std_msgs/msg/String
data: Hello World from Rclex!
---

Enhance devepoment experience

This section describes the information mainly for developers.

Docker environment

This repository provides a docker compose environment for library development with Docker.

As mentioned above, pre-built Docker images are available at Docker Hub, which can be used to easily try out Rclex. You can set the environment variable $RCLEX_DOCKER_TAG to the version of the target environment. Please refer to here for the available environments.

# optional: set to the target environment (default `latest`)
export RCLEX_DOCKER_TAG=latest
# create and start the container
docker compose up -d
# execute the container (with the workdir where this repository is mounted)
docker compose exec -w /root/rclex rclex_docker /bin/bash
# stop the container
docker compose down

In GitHub Actions, we perform CI on multiple tool versions at Pull Requests by using these Docker environments. However, we cannot guarantee operation in all of these environments.

Automatic execution of mix test, etc.

mix test.watch is introduced to automatically run unit test mix test and code formatting mix format every time the source code was edited.

$ mix test.watch
# or, run on docker by following
$ docker compose run --rm -w /root/rclex rclex_docker mix test.watch

Confirmation of communication operation

To check the operation, especially for communication features of this library, we prepare rclex/rclex_connection_tests to test the communication with the nodes implemented with Rclcpp.

cd /path/to/yours
git clone https://github.com/rclex/rclex
git clone https://github.com/rclex/rclex_connection_tests
cd /path/to/yours/rclex_connection_tests
./run-all.sh

Presentations

Maintainers and developers (including past)

rclex's People

Contributors

celaxodon avatar dependabot-preview[bot] avatar dependabot[bot] avatar felixpe avatar hiroiimanishi avatar kebus426 avatar kianmeng avatar pojiro avatar s-hosoai avatar shiroro466 avatar steve-at avatar takasehideki avatar ymtszw avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rclex's Issues

Credo report occurs on v0.6.0_rc

https://github.com/rclex/rclex/runs/4899585539?check_suite_focus=true

Checking 17 source files ...

  Software Design                                                               
┃ 
┃ [D] → Found a TODO tag in a comment: # TODO nodeに紐付いているpub,subをきちんと終了させる
┃       lib/rclex/node.ex:238 #(Rclex.Node.handle_call)
┃ [D] → Found a TODO tag in a comment: # TODO: has_keyで見る
┃       lib/rclex/node.ex:173 #(Rclex.Node.handle_call)

  Code Readability                                                              
┃ 
┃ [R] ↗ Function/macro/guard names should be written in snake_case.
┃       lib/rclex/nifs.ex:309:7 #(Rclex.Nifs.readdata_std_msgs__msg__String)
┃ [R] ↗ Function/macro/guard names should be written in snake_case.
┃       lib/rclex/nifs.ex:306:7 #(Rclex.Nifs.setdata_std_msgs__msg__String)
┃ [R] ↗ Function/macro/guard names should be written in snake_case.
┃       lib/rclex/nifs.ex:303:7 #(Rclex.Nifs.init_msg_std_msgs__msg__String)
┃ [R] ↗ Function/macro/guard names should be written in snake_case.
┃       lib/rclex/nifs.ex:294:7 #(Rclex.Nifs.readdata_geometry_msgs__msg__Twist)
┃ [R] ↗ Function/macro/guard names should be written in snake_case.
┃       lib/rclex/nifs.ex:291:7 #(Rclex.Nifs.setdata_geometry_msgs__msg__Twist)
┃ [R] ↗ Function/macro/guard names should be written in snake_case.
┃       lib/rclex/nifs.ex:288:7 #(Rclex.Nifs.init_msg_geometry_msgs__msg__Twist)
┃ [R] ↗ Function/macro/guard names should be written in snake_case.
┃       lib/rclex/nifs.ex:300:7 #(Rclex.Nifs.create_empty_msg_std_msgs__msg__String)
┃ [R] ↗ Function/macro/guard names should be written in snake_case.
┃       lib/rclex/nifs.ex:297:7 #(Rclex.Nifs.get_typesupport_std_msgs__msg__String)
┃ [R] ↗ Function/macro/guard names should be written in snake_case.
┃       lib/rclex/nifs.ex:285:7 #(Rclex.Nifs.create_empty_msg_geometry_msgs__msg__Twist)
┃ [R] ↗ Function/macro/guard names should be written in snake_case.
┃       lib/rclex/nifs.ex:282:7 #(Rclex.Nifs.get_typesupport_geometry_msgs__msg__Twist)

  Refactoring opportunities                                                     
┃ 
┃ [F] → Function takes too many parameters (arity is 9, max is 8).
┃       lib/rclex/nifs.ex:244:7 #(Rclex.Nifs.rcl_wait_set_init)

  Warnings - please take a look                                                 
┃ 
┃ [W] ↗ There should be no unused return values for Enum functions.
┃       lib/rclex/publisher.ex:47:5 #(Rclex.Publisher.publish)
┃ [W] ↗ There should be no unused return values for Enum functions.
┃       lib/rclex/job_executor.ex:42:8 #(Rclex.JobExecutor.handle_cast)
┃ [W] ↗ There should be no unused return values for Enum functions.
┃       lib/rclex/job_executor.ex:34:8 #(Rclex.JobExecutor.handle_cast)

Please report incorrect results: https://github.com/rrrene/credo/issues

Analysis took 0.3 seconds (0.08s to load, 0.2s running 52 checks on 17 files)
188 mods/funs, found 3 warnings, 1 refactoring opportunity, 10 code readability issues, 2 software design suggestions.

Showing priority issues: ↑ ↗ →  (use `mix credo explain` to explain issues, `mix credo --help` for options).
Error: Process completed with exit code 4.

`publish/2` sometimes failed just after `create_publisher/3`

When Publisher/publish/2 was executed immediately after Node/create_publisher/3, we observed this would sometimes fail. And more curiously, when publishing several times (e.g., in a loop), only the first time publishing may fail.
We have not been able to find out the cause of this fully, but it is possible that the publisher is trying to process the publication before it is generated.

One of the conservative solutions is to insert Process.sleep(100) between them. We will apply this for now to existing samples, but we will attempt to solve the essentials.

`mix test` failed after merging #42 get_node_info

mix test failed after merging #42 get_node_info.


Report on GitHub Actions:
https://github.com/rclex/rclex/runs/3043218395


The error is varied with ROSDISTRO.

message on dashing

Compiling 6 files (.ex)
Generated rclex app
finished rcl_init
finished rcl_init
.publishers finish
subscribers finish
node finish
node finish
.

Finished in 0.07 seconds
2 tests, 0 failures

Randomized with seed 960469
double free or corruption (fasttop)
/__w/_temp/14b5c79e-865a-4473-a19e-cabce5b3f5d2.sh: line 3:  2113 Aborted                 (core dumped) mix test
Error: Process completed with exit code 134.

message on foxy

Compiling 6 files (.ex)
Generated rclex app
finished rcl_init
.finished rcl_init


  1) test rcl_get_topic_names_and_types (RclexTest)
     test/rclex_test.exs:18
     ** (MatchError) no match of right hand side value: [{'/testtopic', ['std_msgs/msg/String']}]
     code: [ name_and_types_tuple_1 | [ name_and_types_tuple_2 ] ]= names_and_types_tuple_list
     stacktrace:
       test/rclex_test.exs:29: (test)



Finished in 0.1 seconds
2 tests, 1 failure

Randomized with seed 786112

Consider more appropriate location where message files will be generated

Currently, the files for custom messages will be generated at the following location in the build step.

  • header files in C: src/*/msg
  • typesupport definition for Elixir code: lib/rclex/*/msg

We don't think the above is not the best since the library code may be modified by user operations. So we consider the another location and way to generate them.


Note:

Refactoring and restructuring suggestions

使う際に気になったところをざっとピックアップしました。例示していないモジュールも同様に再整理します。
多少API構成も変わってしまいますが、どうでしょう?
image

テストをするためのモジュール等が足りない

テストのために作ったノードの情報を取得、解析等ができるようなテスト用のモジュールが必要。
例えばRclexでノードを作成した際、意図した通りに作られているかどうかを確認するために作成したノードの情報がリストに変換されれば自分が意図していたノードの情報をリストに書いて比較することできちんと作成できていたかどうか判別できる。
また、subscriberのcallback関数はmsgのみを引数に取るのでテストの親プロセスの情報を渡せず、プロセス間でデータのやり取りが出来ない(現在は一時ファイルを作成し、そこで読み書きを行うことでデータのやり取りを行っている)。これらをどうにか受け渡す方法が必要。

`mix rclex.prep.ros2` failed when using for Nerves development

v0.8.1 をリリースしました!のですが,,, 残念ながら問題を抱えていました,,,
ROS 2環境無しの状態で Nerves 向けに作業を進めようとすると,mix rclex.prep.ros2 が正常に動作しません.より適切には,このMixタスクを実行するためにはまずその前に rclex をコンパイルする必要があり,そのためには ROS 2 環境が必要となるためです.なかなか悩ましい状況です,,,

Enrich `mix test`

Current mix test only targets on only basic functions. We need to support the behavior of all APIs as much as possible.

mix compile failed on dashing-ex1.11.4-otp23.3.1

https://github.com/rclex/rclex/runs/2711160555?check_suite_focus=true

source /opt/ros/dashing/setup.bash
  source /opt/ros/dashing/setup.bash
  cd rclex
  mix local.hex --force
  mix deps.get
  mix compile
  shell: bash --noprofile --norc -e -o pipefail {0}

13:37:15.504 [warn]  Description: 'Authenticity is not established by certificate path validation'
     Reason: 'Option {verify, verify_peer} and cacertfile/cacerts is missing'


13:37:15.651 [warn]  Description: 'Authenticity is not established by certificate path validation'
     Reason: 'Option {verify, verify_peer} and cacertfile/cacerts is missing'


13:37:15.708 [warn]  Description: 'Authenticity is not established by certificate path validation'
     Reason: 'Option {verify, verify_peer} and cacertfile/cacerts is missing'

* creating /github/home/.mix/archives/hex-0.21.2
Resolving Hex dependencies...
Dependency resolution completed:
Unchanged:
  earmark_parser 1.4.9
  elixir_make 0.6.2
  ex_doc 0.24.2
  makeup 1.0.3
  makeup_elixir 0.14.1
  makeup_erlang 0.1.1
  nimble_parsec 0.6.0
* Getting elixir_make (Hex package)
* Getting ex_doc (Hex package)
* Getting earmark_parser (Hex package)
* Getting makeup_elixir (Hex package)
* Getting makeup_erlang (Hex package)
* Getting makeup (Hex package)
* Getting nimble_parsec (Hex package)
==> earmark_parser
Compiling 1 file (.yrl)
could not compile dependency :earmark_parser, "mix compile" failed. You can recompile this dependency with "mix deps.compile earmark_parser", update it with "mix deps.update earmark_parser" or clean it with "mix deps.clean earmark_parser"
** (Mix) Could not compile "src/link_text_parser.yrl" because the application "parsetools" could not be found. This may happen if your package manager broke Erlang into multiple packages and may be fixed by installing the missing "erlang-dev" and "erlang-parsetools" packages
==> rclex
Error: Process completed with exit code 1.

Boring warnings appeared on `mix compile`

Warning messages are important hints that can lead to issues in the future.
We need to remove them since most of them relate to unused variables/aliases.

warning: variable "pub" is unused (if the variable is not meant to be used, prefix it with an underscore)
  lib/rclex/publisher.ex:66: Rclex.Publisher.terminate/2

warning: unused alias Nifs
  lib/rclex/jobqueue.ex:2

warning: unused alias Nifs
  lib/rclex/jobexecutor.ex:2

warning: variable "id" is unused (if the variable is not meant to be used, prefix it with an underscore)
  lib/rclex/executor.ex:29: Rclex.Executor.init/1

warning: variable "do_nothing" does not exist and is being expanded to "do_nothing()", please use parentheses to remove the ambiguity or change the variable name
  lib/rclex/subloop.ex:57: Rclex.SubLoop.each_subscribe/3

warning: variable "call_back" is unused (if the variable is not meant to be used, prefix it with an underscore)
  lib/rclex/subloop.ex:42: Rclex.SubLoop.each_subscribe/3

warning: variable "state" is unused (if the variable is not meant to be used, prefix it with an underscore)
  lib/rclex/subloop.ex:91: Rclex.SubLoop.terminate/2

warning: variable "state" is unused (if the variable is not meant to be used, prefix it with an underscore)
  lib/rclex/subloop.ex:95: Rclex.SubLoop.terminate/2

warning: unused alias Nifs
  lib/rclex/timer.ex:2

warning: Rclex.Timer.terminate_timer/2 is undefined or private. Did you mean one of:

      * terminate/2

  lib/rclex.ex:83: Rclex.waiting_input/2

test scrpit "simple_pubsub/rclcpp_to_rclex.sh" sometimes failed in GitHub Actions

We could not reproduce it yet,,,

example:
https://github.com/rclex/rclex/runs/2711160527?check_suite_focus=true

INFO: running test scrpit: simple_pubsub/rclcpp_to_rclex.sh
==> rclex
make: Nothing to be done for 'all'.
finished rcl_init
received msg:plf
subscribers finish
node finish
enter rcl_shutdown
TESTINFO: published message  : plfMC5QM3
TESTINFO: subscribed message : plf
TESTINFO: result : 1
TESTERROR: ./simple_pubsub/rclcpp_to_rclex.sh failed.
WARN: simple_pubsub/rclcpp_to_rclex.sh failed!

Subscriber cannot receive the first message.

I implement a simple Pub / Sub. Subscriber waits for any message, and publisher send message continuously.
When publisher sends the first message, subscriber cannot receive it. When publisher sends the second message, subscriber receives the first and second messages.

Refactor the structure of modules

I think the modules are not neatly organized. Here is the candidate to refactor.

  • Rclex: operation for Rclex environment (e.g.: init, finish)
  • Rclex.Node: operation for ROS 2 nodes
  • Rclex.Publisher: operation for publishers in terms of ROS 2
  • Rclex.Subscriber: operation for Subscribers in terms of ROS 2
  • Rclex.Timer: operation for ROS 2 Timer functions
  • Rclex.Message: operation for ROS 2 msgs
  • Rclex.Topic: operation for ROS 2 topic

Some warnings appeared to make NIFs

==> rclex
mkdir -p /root/rclex_connection_tests/rclex_node/_build/dev/lib/rclex/priv
mkdir -p /root/rclex_connection_tests/rclex_node/_build/dev/lib/rclex/obj
gcc -c -I/usr/lib/erlang/usr/include -I/opt/ros/foxy/include -g -O2 -Wall -Wextra -Wno-unused-parameter -pedantic -fPIC -DFOXY -o /root/rclex_connection_tests/rclex_node/_build/dev/lib/rclex/obj/total_nif.o src/total_nif.c
gcc -c -I/usr/lib/erlang/usr/include -I/opt/ros/foxy/include -g -O2 -Wall -Wextra -Wno-unused-parameter -pedantic -fPIC -DFOXY -o /root/rclex_connection_tests/rclex_node/_build/dev/lib/rclex/obj/init_nif.o src/init_nif.c
src/init_nif.c: In function ‘nif_rcl_init_options_init’:
src/init_nif.c:52:16: warning: variable ‘ret’ set but not used [-Wunused-but-set-variable]
   52 |   ERL_NIF_TERM ret;
      |                ^~~
gcc -c -I/usr/lib/erlang/usr/include -I/opt/ros/foxy/include -g -O2 -Wall -Wextra -Wno-unused-parameter -pedantic -fPIC -DFOXY -o /root/rclex_connection_tests/rclex_node/_build/dev/lib/rclex/obj/node_nif.o src/node_nif.c
src/node_nif.c: In function ‘nif_rcl_node_init’:
src/node_nif.c:54:7: warning: variable ‘res’ set but not used [-Wunused-but-set-variable]
   54 |   int res = 0;
      |       ^~~
src/node_nif.c: In function ‘nif_rcl_node_init_without_namespace’:
src/node_nif.c:99:7: warning: variable ‘res’ set but not used [-Wunused-but-set-variable]
   99 |   int res = 0;
      |       ^~~
gcc -c -I/usr/lib/erlang/usr/include -I/opt/ros/foxy/include -g -O2 -Wall -Wextra -Wno-unused-parameter -pedantic -fPIC -DFOXY -o /root/rclex_connection_tests/rclex_node/_build/dev/lib/rclex/obj/publisher_nif.o src/publisher_nif.c
src/publisher_nif.c: In function ‘nif_rcl_publisher_init’:
src/publisher_nif.c:110:7: warning: variable ‘return_value’ set but not used [-Wunused-but-set-variable]
  110 |   int return_value = 0;
      |       ^~~~~~~~~~~~
gcc -c -I/usr/lib/erlang/usr/include -I/opt/ros/foxy/include -g -O2 -Wall -Wextra -Wno-unused-parameter -pedantic -fPIC -DFOXY -o /root/rclex_connection_tests/rclex_node/_build/dev/lib/rclex/obj/subscription_nif.o src/subscription_nif.c
src/subscription_nif.c: In function ‘nif_rcl_subscription_init’:
src/subscription_nif.c:69:7: warning: variable ‘return_value’ set but not used [-Wunused-but-set-variable]
   69 |   int return_value;
      |       ^~~~~~~~~~~~
src/subscription_nif.c: In function ‘nif_rcl_take’:
src/subscription_nif.c:191:16: warning: unused variable ‘ret’ [-Wunused-variable]
  191 |   ERL_NIF_TERM ret,ret_sub,ret_msginfo,ret_sub_alloc;
      |                ^~~
gcc -c -I/usr/lib/erlang/usr/include -I/opt/ros/foxy/include -g -O2 -Wall -Wextra -Wno-unused-parameter -pedantic -fPIC -DFOXY -o /root/rclex_connection_tests/rclex_node/_build/dev/lib/rclex/obj/wait_nif.o src/wait_nif.c
src/wait_nif.c: In function ‘nif_get_sublist_from_waitset’:
src/wait_nif.c:293:64: warning: passing argument 2 of ‘enif_make_resource’ discards ‘const’ qualifier from pointer target type [-Wdiscarded-qualifiers]
  293 |     ret[i] = enif_make_resource(env,(res_waitset->subscriptions[i]));
      |                                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
In file included from src/wait_nif.c:6:
/usr/lib/erlang/usr/include/erl_nif_api_funcs.h:113:74: note: expected ‘void *’ but argument is of type ‘const rcl_subscription_t *’ {aka ‘const struct rcl_subscription_t *’}
  113 | ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM,enif_make_resource,(ErlNifEnv*, void* obj));
      |                                                                    ~~~~~~^~~
/usr/lib/erlang/usr/include/erl_nif.h:339:76: note: in definition of macro ‘ERL_NIF_API_FUNC_DECL’
  339 | #  define ERL_NIF_API_FUNC_DECL(RET_TYPE, NAME, ARGS) extern RET_TYPE NAME ARGS
      |                                                                            ^~~~
src/wait_nif.c:282:23: warning: unused variable ‘res_sub’ [-Wunused-variable]
  282 |   rcl_subscription_t* res_sub;
      |                       ^~~~~~~
src/wait_nif.c: In function ‘nif_rcl_wait_set_init’:
src/wait_nif.c:122:3: warning: ignoring return value of ‘rcl_wait_set_init’, declared with attribute warn_unused_result [-Wunused-result]
  122 |   rcl_wait_set_init(res_waitset,number_of_subscriptions,number_of_guard_conditions,number_of_timers,number_of_clients,
      |   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  123 |                     number_of_services,number_of_events,res_context,*res_alloc);
      |                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
gcc -c -I/usr/lib/erlang/usr/include -I/opt/ros/foxy/include -g -O2 -Wall -Wextra -Wno-unused-parameter -pedantic -fPIC -DFOXY -o /root/rclex_connection_tests/rclex_node/_build/dev/lib/rclex/obj/graph_nif.o src/graph_nif.c
src/graph_nif.c: In function ‘nif_rcl_get_topic_names_and_types’:
src/graph_nif.c:48:38: warning: comparison with string literal results in unspecified behavior [-Waddress]
   48 |   bool no_demangle = res_no_demangle == "true";
      |                                      ^~
src/graph_nif.c:55:40: warning: passing argument 2 of ‘memset’ makes integer from pointer without a cast [-Wint-conversion]
   55 |   (void)memset(&res_names_and_types[0],NULL,sizeof(rcl_names_and_types_t));
      |                                        ^~~~
      |                                        |
      |                                        void *
In file included from /usr/include/features.h:461,
                 from /usr/include/x86_64-linux-gnu/sys/types.h:25,
                 from /usr/lib/erlang/usr/include/erl_drv_nif.h:158,
                 from /usr/lib/erlang/usr/include/erl_nif.h:31,
                 from src/graph_nif.c:7:
/usr/include/x86_64-linux-gnu/bits/string_fortified.h:59:1: note: expected ‘int’ but argument is of type ‘void *’
   59 | __NTH (memset (void *__dest, int __ch, size_t __len))
      | ^~~~~
src/graph_nif.c:29:16: warning: variable ‘ret’ set but not used [-Wunused-but-set-variable]
   29 |   ERL_NIF_TERM ret;
      |                ^~~
src/graph_nif.c:27:7: warning: variable ‘res’ set but not used [-Wunused-but-set-variable]
   27 |   int res;
      |       ^~~
gcc -c -I/usr/lib/erlang/usr/include -I/opt/ros/foxy/include -g -O2 -Wall -Wextra -Wno-unused-parameter -pedantic -fPIC -DFOXY -o /root/rclex_connection_tests/rclex_node/_build/dev/lib/rclex/obj/msg_int16_nif.o src/msg_int16_nif.c
src/msg_int16_nif.c: In function ‘nif_std_msgs__msg__Int16__destroy’:
src/msg_int16_nif.c:80:16: warning: unused variable ‘ret’ [-Wunused-variable]
   80 |   ERL_NIF_TERM ret;
      |                ^~~
src/msg_int16_nif.c: In function ‘nif_getmsgtype_int16’:
src/msg_int16_nif.c:103:12: warning: assignment discards ‘const’ qualifier from pointer target type [-Wdiscarded-qualifiers]
  103 |   *res_tmp = ROSIDL_GET_MSG_TYPE_SUPPORT(std_msgs,msg,Int16);
      |            ^
src/msg_int16_nif.c: In function ‘nif_readdata_int16’:
src/msg_int16_nif.c:112:16: warning: unused variable ‘ret’ [-Wunused-variable]
  112 |   ERL_NIF_TERM ret;
      |                ^~~
src/msg_int16_nif.c: In function ‘nif_setdata_int16’:
src/msg_int16_nif.c:127:16: warning: unused variable ‘ret’ [-Wunused-variable]
  127 |   ERL_NIF_TERM ret;
      |                ^~~
gcc -c -I/usr/lib/erlang/usr/include -I/opt/ros/foxy/include -g -O2 -Wall -Wextra -Wno-unused-parameter -pedantic -fPIC -DFOXY -o /root/rclex_connection_tests/rclex_node/_build/dev/lib/rclex/obj/msg_string_nif.o src/msg_string_nif.c
src/msg_string_nif.c: In function ‘nif_setdata_string’:
src/msg_string_nif.c:13:26: warning: implicit declaration of function ‘rosidl_runtime_c__String__assign’ [-Wimplicit-function-declaration]
   13 | #define __STRING__ASSIGN rosidl_runtime_c__String__assign
      |                          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/msg_string_nif.c:78:3: note: in expansion of macro ‘__STRING__ASSIGN’
   78 |   __STRING__ASSIGN(res_msg,data_buf);
      |   ^~~~~~~~~~~~~~~~
src/msg_string_nif.c:65:16: warning: unused variable ‘ret’ [-Wunused-variable]
   65 |   ERL_NIF_TERM ret;
      |                ^~~
gcc -o /root/rclex_connection_tests/rclex_node/_build/dev/lib/rclex/priv/rclex_nifs.so -L/usr/lib/erlang/usr/lib -g -shared /root/rclex_connection_tests/rclex_node/_build/dev/lib/rclex/obj/total_nif.o /root/rclex_connection_tests/rclex_node/_build/dev/lib/rclex/obj/init_nif.o /root/rclex_connection_tests/rclex_node/_build/dev/lib/rclex/obj/node_nif.o /root/rclex_connection_tests/rclex_node/_build/dev/lib/rclex/obj/publisher_nif.o /root/rclex_connection_tests/rclex_node/_build/dev/lib/rclex/obj/subscription_nif.o /root/rclex_connection_tests/rclex_node/_build/dev/lib/rclex/obj/wait_nif.o /root/rclex_connection_tests/rclex_node/_build/dev/lib/rclex/obj/graph_nif.o /root/rclex_connection_tests/rclex_node/_build/dev/lib/rclex/obj/msg_int16_nif.o /root/rclex_connection_tests/rclex_node/_build/dev/lib/rclex/obj/msg_string_nif.o -L/opt/ros/foxy/lib -lrcl -lrmw -lrcutils -lrosidl_runtime_c -lrosidl_typesupport_c -lrosidl_typesupport_introspection_c -lstd_msgs__rosidl_generator_c -lstd_msgs__rosidl_typesupport_c -lfastcdr -lfastrtps -lrmw_fastrtps_cpp

`rclex_connection_tests` becomes failed on Dashing from v0.6.0_rc

One of the simplest solution for us is to throw away Dashing because the EOL of Dashing has already been passed :D


https://github.com/rclex/rclex/actions/runs/1729037863

Compiling 19 files (.ex)
warning: variable "defstruct" does not exist and is being expanded to "defstruct()", please use parentheses to remove the ambiguity or change the variable name
  lib/rclex/geometry_msgs/msg/twist.ex:2: Rclex.GeometryMsgs.Msg.Twist


== Compilation error in file lib/rclex/geometry_msgs/msg/twist.ex ==
** (CompileError) lib/rclex/geometry_msgs/msg/twist.ex:2: undefined function defstruct/0

Error: Process completed with exit code 1.

Reapply dialyzer plt cache for github actions

DialyzerのPLTの生成に時間が掛かるため、キャッシュを適用したいが現時点では生成したMsgTypeのコードとの相性が悪くCIでうまくあつかえないため、#180 にて一時的に無効化している。
#139 が解決した後に、再度有効化したい。

Improve Makefile to compile with galactic and humble

Current Makefile supports dashing and foxy only,

rclex/Makefile

Lines 4 to 10 in 64533cb

ifeq ($(ROS_DISTRO), dashing)
ROS_VERSION = DASHING
TYPE_STRUCTURE_DIR = rosidl_generator_c
else ifeq ($(ROS_DISTRO), foxy)
ROS_VERSION = FOXY
TYPE_STRUCTURE_DIR = rosidl_runtime_c
endif

so we cannot test galactic and humble with docker, like below

$ export RCLEX_DOCKER_TAG=galactic-ex1.13.1-otp24.1.7
$ docker compose run --rm -w /root/rclex rclex_docker mix test
gcc -c -I/usr/local/lib/erlang/usr/include -I/opt/ros/galactic/include -I/opt/ros/galactic/include -I/opt/ros/galactic/include -g -O2 -Wall -Wextra -Wno-unused-parameter -pedantic -fPIC -I./src -D2 -o /root/rclex/_build/test/lib/rclex/obj/msg_nif.o src/msg_nif.c
<command-line>: error: macro names must be identifiers
make: *** [Makefile:75: /root/rclex/_build/test/lib/rclex/obj/msg_nif.o] Error 1
** (Mix) Could not compile with "make" (exit status: 2).
If the error message above says that rcl/rcl.h can't be found,
then the fix is to setup the ROS 2 environment. If you have
already installed ROS 2 environment, run the following command.
`. /opt/ros/${ROS_DISTRO}/setup.bash`

This caused by <command-line>: error: macro names must be identifiers, which means -D2 isn't valid.
That must be '-DGALACTIC' in this case.

Release rcl nif resources when GerServer terminates

NIF経由でリソースを確保する rcl 自身のリソースの解放を GenServer の terminate で行うようにするのがよいと思います。
理由は、リソース解放を terminate に委ねることで、 GenServer を殺すだけでリソースが開放できると考えられるからです。
この方法をとると、意図せず GenServer が死んだ場合でもリソース解放が行わることになりリークがなくります。

macOS support

Should we support macOS (Mojave or Catalina) platform?

I believe Alchemists (Elixir programmers) want to use macOS instead of Ubuntu. macOS is also useful to develop web applications.
ROS 2 supports macOS as Tier 1 with binary packages. Although REP 2000 for Dashing only targets on Sierra, Mojave is also fine by my experience (I have never checked it on Catalina).

add CI test for building on Nerves

From v0.8.0, we can now support Rclex running on Nerves!
I think it would be better if we could add CI test for building on Nerves. I believe that the development experience will be much better.
Of course it is difficult to provide support for the testing of the operation, and we do not intend to do so.

Support the env where ROS is installed with "fat" archive

Official instruction for ROS installation guides there are two ways to install ROS env, Debian packages and "fat" archive.
https://docs.ros.org/en/foxy/Installation.html

Current implementation assumes that ROS is installed by Debian packages.
According to the Qiita article written by @kikuzo (thx!), we need to modify Makefile if ROS was installed with "fat" archive.
https://qiita.com/kikuzo/items/e15f2e4938a4dfa0512d#rclex%E3%82%92%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%81%99%E3%82%8B

rclex/Makefile

Lines 1 to 2 in 465ef83

# set directory for ROSDISTRO
ROS_DIR = /opt/ros/$(ROS_DISTRO)

RuntimeError in publisher

RuntimeError occurs but it can continue to execute.

The cause may be that the timer count upper limit has been exceeded. And it may be fixed by #21

def timer_loop(publisher_list, time, callback, count, limit) do
count = count + 1
if(count > limit) do
raise "input times repeated"
end
callback.(publisher_list)
# timeはミリ秒
:timer.sleep(time)
timer_loop(publisher_list, time, callback, count, limit)
end

log:
https://github.com/rclex/rclex/runs/2714785025?check_suite_focus=true

INFO: running test scrpit: simple_pubsub/rclex_to_rclex.sh
==> rclex
make: Nothing to be done for 'all'.
finished rcl_init
==> rclex
make: Nothing to be done for 'all'.
finished rcl_init
publish message:ZT]AVrNWvF
publish ok
publish message:ZT]AVrNWvF
publish ok
received msg:ZT]AVrNWvF

Error: 1.397 [error] Task #PID<0.191.0> started from #PID<0.94.0> terminating
** (RuntimeError) input times repeated
    (rclex 0.3.1) lib/rclex/timer.ex:13: Rclex.Timer.timer_loop/5
    (elixir 1.12.0) lib/task/supervised.ex:90: Task.Supervised.invoke_mfa/2
    (stdlib 3.15) proc_lib.erl:226: :proc_lib.init_p_do_apply/3
Function: &Rclex.Timer.timer_loop/5
    Args: [[#Reference<0.3063312636.2020999169.41410>], 500, #Function<1.15081939/1 in Test.App.SimplePubSub."-fun.pub_callback/1-">, 0, 2]
publish message:ZT]AVrNWvF
publish ok
received msg:ZT]AVrNWvF

Error: 1.416 [error] GenServer #PID<0.194.0> terminating
** (RuntimeError) input times repeated
    (rclex 0.3.1) lib/rclex/timer.ex:13: Rclex.Timer.timer_loop/5
    (elixir 1.12.0) lib/task/supervised.ex:90: Task.Supervised.invoke_mfa/2
    (stdlib 3.15) proc_lib.erl:226: :proc_lib.init_p_do_apply/3
Last message: {:EXIT, #PID<0.191.0>, {%RuntimeError{message: "input times repeated"}, [{Rclex.Timer, :timer_loop, 5, [file: 'lib/rclex/timer.ex', line: 13]}, {Task.Supervised, :invoke_mfa, 2, [file: 'lib/task/supervised.ex', line: 90]}, {:proc_lib, :init_p_do_apply, 3, [file: 'proc_lib.erl', line: 226]}]}}
State: %DynamicSupervisor{args: {{:temporary, 5000}, []}, children: %{}, extra_arguments: [], max_children: :infinity, max_restarts: 3, max_seconds: 5, mod: Task.Supervisor, name: {#PID<0.194.0>, Task.Supervisor}, restarts: [], strategy: :one_for_one}

Error: 1.416 [error] GenServer #PID<0.192.0> terminating
** (RuntimeError) input times repeated
    (rclex 0.3.1) lib/rclex/timer.ex:13: Rclex.Timer.timer_loop/5
    (elixir 1.12.0) lib/task/supervised.ex:90: Task.Supervised.invoke_mfa/2
    (stdlib 3.15) proc_lib.erl:226: :proc_lib.init_p_do_apply/3
Last message: {:EXIT, #PID<0.191.0>, {%RuntimeError{message: "input times repeated"}, [{Rclex.Timer, :timer_loop, 5, [file: 'lib/rclex/timer.ex', line: 13]}, {Task.Supervised, :invoke_mfa, 2, [file: 'lib/task/supervised.ex', line: 90]}, {:proc_lib, :init_p_do_apply, 3, [file: 'proc_lib.erl', line: 226]}]}}
State: %DynamicSupervisor{args: {{:temporary, 5000}, []}, children: %{}, extra_arguments: [], max_children: :infinity, max_restarts: 3, max_seconds: 5, mod: Task.Supervisor, name: {#PID<0.192.0>, Task.Supervisor}, restarts: [], strategy: :one_for_one}
publish message:ZT]AVrNWvF
publish ok
received msg:ZT]AVrNWvF

Error: 2.419 [error] Task #PID<0.196.0> started from #PID<0.94.0> terminating
** (RuntimeError) input times repeated
    (rclex 0.3.1) lib/rclex/timer.ex:13: Rclex.Timer.timer_loop/5
    (elixir 1.12.0) lib/task/supervised.ex:90: Task.Supervised.invoke_mfa/2
    (stdlib 3.15) proc_lib.erl:226: :proc_lib.init_p_do_apply/3
Function: &Rclex.Timer.timer_loop/5
    Args: [[#Reference<0.3063312636.2020999169.41410>], 500, #Function<1.15081939/1 in Test.App.SimplePubSub."-fun.pub_callback/1-">, 0, 2]

Error: 2.419 [error] GenServer #PID<0.199.0> terminating
** (RuntimeError) input times repeated
    (rclex 0.3.1) lib/rclex/timer.ex:13: Rclex.Timer.timer_loop/5
    (elixir 1.12.0) lib/task/supervised.ex:90: Task.Supervised.invoke_mfa/2
    (stdlib 3.15) proc_lib.erl:226: :proc_lib.init_p_do_apply/3
Last message: {:EXIT, #PID<0.196.0>, {%RuntimeError{message: "input times repeated"}, [{Rclex.Timer, :timer_loop, 5, [file: 'lib/rclex/timer.ex', line: 13]}, {Task.Supervised, :invoke_mfa, 2, [file: 'lib/task/supervised.ex', line: 90]}, {:proc_lib, :init_p_do_apply, 3, [file: 'proc_lib.erl', line: 226]}]}}
State: %DynamicSupervisor{args: {{:temporary, 5000}, []}, children: %{}, extra_arguments: [], max_children: :infinity, max_restarts: 3, max_seconds: 5, mod: Task.Supervisor, name: {#PID<0.199.0>, Task.Supervisor}, restarts: [], strategy: :one_for_one}
received msg:ZT]AVrNWvF
publish message:ZT]AVrNWvF

Error: 2.419 [error] GenServer #PID<0.197.0> terminating
** (RuntimeError) input times repeated
    (rclex 0.3.1) lib/rclex/timer.ex:13: Rclex.Timer.timer_loop/5
    (elixir 1.12.0) lib/task/supervised.ex:90: Task.Supervised.invoke_mfa/2
    (stdlib 3.15) proc_lib.erl:226: :proc_lib.init_p_do_apply/3
Last message: {:EXIT, #PID<0.196.0>, {%RuntimeError{message: "input times repeated"}, [{Rclex.Timer, :timer_loop, 5, [file: 'lib/rclex/timer.ex', line: 13]}, {Task.Supervised, :invoke_mfa, 2, [file: 'lib/task/supervised.ex', line: 90]}, {:proc_lib, :init_p_do_apply, 3, [file: 'proc_lib.erl', line: 226]}]}}
State: %DynamicSupervisor{args: {{:temporary, 5000}, []}, children: %{}, extra_arguments: [], max_children: :infinity, max_restarts: 3, max_seconds: 5, mod: Task.Supervisor, name: {#PID<0.197.0>, Task.Supervisor}, restarts: [], strategy: :one_for_one}
publish ok
publish message:ZT]AVrNWvF
publish ok
received msg:ZT]AVrNWvF
publishers finish
enter rcl_shutdown
node finish
subscribers finish
node finish
enter rcl_shutdown
TESTINFO: published message  : ZT]AVrNWvF
TESTINFO: subscribed message : ZT]AVrNWvF
TESTINFO: result : 0
INFO: simple_pubsub/rclex_to_rclex.sh passed!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.