Async Comm
A library for asynchronous serial communication
Async Comm Library

This project provides a C++ library that gives a simple interface for asynchronous serial communications over a serial port or UDP. It uses the Boost.Asio library under the hood, but hides from the user the details of interfacing with the ports or sockets and managing send/receive buffers.

Including in your project

There are three ways to use the async_comm library in your project:

  1. If you'll be using the library in a ROS package, install from the ROS repositories
  2. Build and install the library on your system, then use CMake's find_package() functionality
  3. Include the async_comm as a submodule in your project

With the second and third options, you will need to ensure that the Boost library is installed before proceeding:

sudo apt -y install libboost-dev

ROS install

The async_comm library is released as a third-party, non-catkin package for ROS following the guidelines in REP 136. To use the library in your ROS package, first install the library from the ROS repositories:

sudo apt install ros-<DISTRO>-async-comm

Replace <DISTRO> with your ROS distribution. The library is currently released for kinetic, lunar, and melodic.

Then, add something like the following lines to your package's CMakeLists.txt:

set(CMAKE_CXX_FLAGS "-std=c++11")
find_package(async_comm REQUIRED)
catkin_package(
...
DEPENDS async_comm
)
include_directories(
${catkin_INCLUDE_DIRS}
...
${async_comm_INCLUDE_DIRS}
)
add_executable(my_node src/my_node.cpp)
target_link_libraries(my_node ${async_comm_LIBRARIES})

Also be sure to list async_comm as a dependency in your package.xml:

<?xml version="1.0"?>
<package format="2">
...
<depend>async_comm</depend>
...
</package>

System install

First, download and install the library:

git clone https://github.com/dpkoch/async_comm.git
cd async_comm
mkdir build && cd build/
cmake .. && make
sudo make install

Then, do something like this in your project's CMakeLists.txt:

cmake_minimum_required(VERSION 2.8.11)
project(my_project)
set(CMAKE_CXX_FLAGS "-std=c++11")
find_package(async_comm REQUIRED)
include_directories(${async_comm_INCLUDE_DIRS})
add_executable(my_project src/my_project.cpp)
target_link_libraries(my_project ${async_comm_LIBRARIES})

Including as a submodule

If you don't want to go with the ROS or system install options, the next easiest way to embed the async_comm library in your project is as a Git submodule. The following instructions are for a project using Git for version control and CMake for a build system, but should serve as a starting point for other setups.

For example, to put async_comm in the lib/async_comm directory, run the following from the root of your project:

git submodule add https://github.com/dpkoch/async_comm.git lib/async_comm

Your CMakeLists.txt file would then look something like this:

cmake_minimum_required(VERSION 2.8.11)
project(my_project)
set(CMAKE_CXX_FLAGS "-std=c++11")
add_subdirectory(lib/async_comm)
include_directories(lib/async_comm/include)
add_executable(my_project src/my_project.cpp)
target_link_libraries(my_project async_comm)

Usage

There are two classes that you'll use directly as a user:

Both of these classes have the same interface and inherit from the async_comm::Comm base class. The constructors for each class require the arguments to specify the details of the serial port or UDP socket.

The interface consists of the following functions:

More details can be found in the code API documentation. Very simple example programs are provided to illustrate the usage as described below.

One tricky part is registering the member function of a class as the receive callback. This is accomplished using std::bind. For example, if I want to register the receive function of MyClass from within the class, I would use

{C++}
serial_.register_receive_callback(std::bind(&MyClass::receive, this, std::placeholders::_1, std::placeholders::_2));

where serial_ is an instance of async_comm::Serial.

Examples

There are three examples provided in the repository. The first two are very simple, while the third is more complete. To build the examples, run CMake with the -DASYNC_COMM_BUILD_EXAMPLES=ON flag.