├── .gitignore
├── CMakeLists.txt
├── LICENSE
├── README.md
├── cmake
└── FindZeroMQ.cmake
├── package.xml
├── scripts
├── listener_zmq.py
└── talker_zmq.py
└── src
├── listener_zmq.cpp
└── talker_zmq.cpp
/.gitignore:
--------------------------------------------------------------------------------
1 | # ignore vscode config files
2 | .vscode/
3 |
4 | # Prerequisites
5 | *.d
6 |
7 | # Compiled Object files
8 | *.slo
9 | *.lo
10 | *.o
11 | *.obj
12 |
13 | # Precompiled Headers
14 | *.gch
15 | *.pch
16 |
17 | # Compiled Dynamic libraries
18 | *.so
19 | *.dylib
20 | *.dll
21 |
22 | # Fortran module files
23 | *.mod
24 | *.smod
25 |
26 | # Compiled Static libraries
27 | *.lai
28 | *.la
29 | *.a
30 | *.lib
31 |
32 | # Executables
33 | *.exe
34 | *.out
35 | *.app
36 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 2.8.3)
2 | project(ros_zeromq_tutorial)
3 |
4 | set(CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}")
5 | set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake CACHE INTERNAL "" FORCE)
6 |
7 | find_package(ZeroMQ)
8 | find_package(catkin REQUIRED COMPONENTS roscpp)
9 |
10 | catkin_package()
11 | include_directories(include ${catkin_INCLUDE_DIRS} ${ZeroMQ_INCLUDE_DIRS})
12 |
13 | add_executable(talker_zmq src/talker_zmq.cpp)
14 | target_link_libraries(talker_zmq ${catkin_LIBRARIES} ${ZeroMQ_LIBRARIES})
15 |
16 | add_executable(listener_zmq src/listener_zmq.cpp)
17 | target_link_libraries(listener_zmq ${catkin_LIBRARIES} ${ZeroMQ_LIBRARIES})
18 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Ravi Prakash Joshi
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ROS ZeroMQ Tutorial
2 |
3 | This tutorial shows how to use [ZeroMQ](http://zeromq.org) with ROS for publishing and subscribing to messages. The following two languages are supported:
4 |
5 | * CPP
6 | * Python (see [thanks](#thanks) section)
7 |
8 |
9 | ## Dependencies
10 | 1. [ZeroMQ](http://zeromq.org/): Install ZeroMQ using following command:
11 | ```
12 | sudo apt-get install libzmq3-dev
13 | ```
14 | _It should be easy to install newer versions of ZeroMQ, and this repository should be compatible with them. However, please note that this repository is only for demonstration purposes. Therefore, we have not tested it thoroughly. In such cases, please feel free to open a new [issue](#issue) to inform the changes to authors._
15 |
16 |
17 | ## Compilation
18 | 1. Make sure to download complete repository. Use `git clone` or download zip as per convenience.
19 | 1. Invoke catkin tool inside ros workspace i.e., `catkin_make`
20 |
21 |
22 | ## Steps to run
23 | 1. Start ROS Core by using the following command:
24 | ```
25 | roscore
26 | ```
27 | 1. Invoke the publisher by using the following command:
28 | ```
29 | rosrun ros_zeromq_tutorial talker_zmq
30 | ```
31 | Alternatively, the python version of talker can be started by using the following command:
32 | ```
33 | rosrun ros_zeromq_tutorial talker_zmq.py
34 | ```
35 | 1. The published data can be seen by using the following command:
36 | ```
37 | rosrun ros_zeromq_tutorial listener_zmq
38 | ```
39 | Alternatively, the python version of listener can be started by using the following command:
40 | ```
41 | rosrun ros_zeromq_tutorial listener_zmq.py
42 | ```
43 |
44 |
45 | ## Issue
46 | Please check [here](https://github.com/ravijo/ros_zeromq_tutorial/issues) and create issues accordingly.
47 |
48 |
49 | ## Thanks
50 | The following authors are sincerely acknowledged for the improvements of this package:
51 | * [Md Rakin Sarder](https://github.com/tunchunairarko): For providing python nodes
52 |
--------------------------------------------------------------------------------
/cmake/FindZeroMQ.cmake:
--------------------------------------------------------------------------------
1 | ##=============================================================================
2 | ##
3 | ## Copyright (c) Kitware, Inc.
4 | ## All rights reserved.
5 | ## See LICENSE.txt for details.
6 | ##
7 | ## This software is distributed WITHOUT ANY WARRANTY; without even
8 | ## the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
9 | ## PURPOSE. See the above copyright notice for more information.
10 | ##
11 | ##=============================================================================
12 | # - Try to find ZeroMQ headers and libraries
13 | #
14 | # Usage of this module as follows:
15 | #
16 | # find_package(ZeroMQ)
17 | #
18 | # Variables used by this module, they can change the default behaviour and need
19 | # to be set before calling find_package:
20 | #
21 | # ZeroMQ_ROOT_DIR Set this variable to the root installation of
22 | # ZeroMQ if the module has problems finding
23 | # the proper installation path.
24 | #
25 | # Variables defined by this module:
26 | #
27 | # ZeroMQ_FOUND System has ZeroMQ libs/headers
28 | # ZeroMQ_LIBRARIES The ZeroMQ libraries
29 | # ZeroMQ_INCLUDE_DIR The location of ZeroMQ headers
30 | # ZeroMQ_VERSION The version of ZeroMQ
31 |
32 | find_path(ZeroMQ_ROOT_DIR
33 | NAMES include/zmq.h
34 | )
35 |
36 | if(MSVC)
37 | #add in all the names it can have on windows
38 | if(CMAKE_GENERATOR_TOOLSET MATCHES "v140" OR MSVC14)
39 | set(_zmq_TOOLSET "-v140")
40 | elseif(CMAKE_GENERATOR_TOOLSET MATCHES "v120" OR MSVC12)
41 | set(_zmq_TOOLSET "-v120")
42 | elseif(CMAKE_GENERATOR_TOOLSET MATCHES "v110_xp")
43 | set(_zmq_TOOLSET "-v110_xp")
44 | elseif(CMAKE_GENERATOR_TOOLSET MATCHES "v110" OR MSVC11)
45 | set(_zmq_TOOLSET "-v110")
46 | elseif(CMAKE_GENERATOR_TOOLSET MATCHES "v100" OR MSVC10)
47 | set(_zmq_TOOLSET "-v100")
48 | elseif(CMAKE_GENERATOR_TOOLSET MATCHES "v90" OR MSVC90)
49 | set(_zmq_TOOLSET "-v90")
50 | endif()
51 |
52 | set(_zmq_versions
53 | "4_1_5" "4_1_4" "4_1_3" "4_1_2" "4_1_1" "4_1_0"
54 | "4_0_8" "4_0_7" "4_0_6" "4_0_5" "4_0_4" "4_0_3" "4_0_2" "4_0_1" "4_0_0"
55 | "3_2_5" "3_2_4" "3_2_3" "3_2_2" "3_2_1" "3_2_0" "3_1_0")
56 |
57 | set(_zmq_release_names)
58 | set(_zmq_debug_names)
59 | foreach( ver ${_zmq_versions})
60 | list(APPEND _zmq_release_names "libzmq${_zmq_TOOLSET}-mt-${ver}")
61 | endforeach()
62 | foreach( ver ${_zmq_versions})
63 | list(APPEND _zmq_debug_names "libzmq${_zmq_TOOLSET}-mt-gd-${ver}")
64 | endforeach()
65 |
66 | #now try to find the release and debug version
67 | find_library(ZeroMQ_LIBRARY_RELEASE
68 | NAMES ${_zmq_release_names} zmq libzmq
69 | HINTS ${ZeroMQ_ROOT_DIR}/bin
70 | ${ZeroMQ_ROOT_DIR}/lib
71 | )
72 |
73 | find_library(ZeroMQ_LIBRARY_DEBUG
74 | NAMES ${_zmq_debug_names} zmq libzmq
75 | HINTS ${ZeroMQ_ROOT_DIR}/bin
76 | ${ZeroMQ_ROOT_DIR}/lib
77 | )
78 |
79 | if(ZeroMQ_LIBRARY_RELEASE AND ZeroMQ_LIBRARY_DEBUG)
80 | set(ZeroMQ_LIBRARY
81 | debug ${ZeroMQ_LIBRARY_DEBUG}
82 | optimized ${ZeroMQ_LIBRARY_RELEASE}
83 | )
84 | elseif(ZeroMQ_LIBRARY_RELEASE)
85 | set(ZeroMQ_LIBRARY ${ZeroMQ_LIBRARY_RELEASE})
86 | elseif(ZeroMQ_LIBRARY_DEBUG)
87 | set(ZeroMQ_LIBRARY ${ZeroMQ_LIBRARY_DEBUG})
88 | endif()
89 |
90 | else()
91 | find_library(ZeroMQ_LIBRARY
92 | NAMES zmq libzmq
93 | HINTS ${ZeroMQ_ROOT_DIR}/lib
94 | )
95 | endif()
96 |
97 | find_path(ZeroMQ_INCLUDE_DIR
98 | NAMES zmq.h
99 | HINTS ${ZeroMQ_ROOT_DIR}/include
100 | )
101 |
102 | function(extract_version_value value_name file_name value)
103 | file(STRINGS ${file_name} val REGEX "${value_name} .")
104 | string(FIND ${val} " " last REVERSE)
105 | string(SUBSTRING ${val} ${last} -1 val)
106 | string(STRIP ${val} val)
107 | set(${value} ${val} PARENT_SCOPE)
108 | endfunction(extract_version_value)
109 |
110 | extract_version_value("ZMQ_VERSION_MAJOR" ${ZeroMQ_INCLUDE_DIR}/zmq.h MAJOR)
111 | extract_version_value("ZMQ_VERSION_MINOR" ${ZeroMQ_INCLUDE_DIR}/zmq.h MINOR)
112 | extract_version_value("ZMQ_VERSION_PATCH" ${ZeroMQ_INCLUDE_DIR}/zmq.h PATCH)
113 |
114 | set(ZeroMQ_VER "${MAJOR}.${MINOR}.${PATCH}")
115 |
116 | #We are using the 2.8.10 signature of find_package_handle_standard_args,
117 | #as that is the version that ParaView 5.1 && VTK 6/7 ship, and inject
118 | #into the CMake module path. This allows our FindModule to work with
119 | #projects that include VTK/ParaView before searching for Remus
120 | include(FindPackageHandleStandardArgs)
121 | find_package_handle_standard_args(
122 | ZeroMQ
123 | REQUIRED_VARS ZeroMQ_LIBRARY ZeroMQ_INCLUDE_DIR
124 | VERSION_VAR ZeroMQ_VER
125 | )
126 |
127 | set(ZeroMQ_FOUND ${ZEROMQ_FOUND})
128 | set(ZeroMQ_INCLUDE_DIRS ${ZeroMQ_INCLUDE_DIR})
129 | set(ZeroMQ_LIBRARIES ${ZeroMQ_LIBRARY})
130 | set(ZeroMQ_VERSION ${ZeroMQ_VER})
131 |
132 | mark_as_advanced(
133 | ZeroMQ_ROOT_DIR
134 | ZeroMQ_LIBRARY
135 | ZeroMQ_LIBRARY_DEBUG
136 | ZeroMQ_LIBRARY_RELEASE
137 | ZeroMQ_INCLUDE_DIR
138 | ZeroMQ_VERSION
139 | )
140 |
--------------------------------------------------------------------------------
/package.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | ros_zeromq_tutorial
4 | 0.0.0
5 | The ros_zeromq_tutorial package
6 | Ravi Joshi
7 | Ravi Joshi
8 | MIT
9 | catkin
10 | roscpp
11 | rospy
12 | roscpp
13 | rospy
14 |
15 |
--------------------------------------------------------------------------------
/scripts/listener_zmq.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | import zmq
4 | import rospy
5 |
6 |
7 | def listener():
8 | rospy.init_node("listener_zmq", anonymous=True)
9 |
10 | context = zmq.Context()
11 | socket = context.socket(zmq.SUB)
12 |
13 | TOPIC = b""
14 | socket.setsockopt(zmq.SUBSCRIBE, TOPIC)
15 |
16 | linger = 0
17 | socket.setsockopt(zmq.LINGER, linger)
18 | socket.connect("tcp://localhost:6666")
19 |
20 | while not rospy.is_shutdown():
21 | string = socket.recv()
22 | # topic, messagedata = string.split()
23 | rospy.loginfo("I heard %s", string)
24 |
25 | socket.close()
26 | context.close()
27 |
28 |
29 | if __name__ == "__main__":
30 | listener()
31 |
--------------------------------------------------------------------------------
/scripts/talker_zmq.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | import rospy
4 | import zmq
5 |
6 |
7 | def talker():
8 | rospy.init_node("talker_zmq", anonymous=True)
9 | rate = rospy.Rate(10) # 10hz
10 |
11 | context = zmq.Context()
12 | socket = context.socket(zmq.PUB)
13 | socket.bind("tcp://*:6666")
14 |
15 | while not rospy.is_shutdown():
16 | msg_str = "hello_world_%s" % rospy.get_time()
17 | rospy.loginfo(msg_str)
18 | socket.send_string(msg_str)
19 | rate.sleep()
20 |
21 |
22 | if __name__ == "__main__":
23 | try:
24 | talker()
25 | except rospy.ROSInterruptException:
26 | pass
27 |
--------------------------------------------------------------------------------
/src/listener_zmq.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * listener_zmq.cpp
3 | * Author: Ravi Joshi
4 | * Date: 2018/01/18
5 | */
6 |
7 | #include
8 |
9 | #include
10 |
11 | int main(int argc, char** argv) {
12 | ros::init(argc, argv, "listener_zmq", ros::init_options::AnonymousName);
13 |
14 | zmq::context_t context(1);
15 | zmq::socket_t subscriber(context, ZMQ_SUB);
16 |
17 | std::string TOPIC = "";
18 | subscriber.setsockopt(ZMQ_SUBSCRIBE, TOPIC.c_str(), TOPIC.length()); // allow all messages
19 |
20 | int linger = 0; // Proper shutdown ZeroMQ
21 | subscriber.setsockopt(ZMQ_LINGER, &linger, sizeof(linger));
22 |
23 | subscriber.connect("tcp://localhost:6666");
24 |
25 | while (ros::ok()) {
26 | zmq::message_t message;
27 | int rc = subscriber.recv(&message);
28 | if (rc) {
29 | std::string recv_string;
30 |
31 | std::istringstream iss(static_cast(message.data()));
32 | iss >> recv_string;
33 | ROS_INFO_STREAM("I heard " << recv_string);
34 | }
35 | }
36 |
37 | // Clean up your socket and context here
38 | subscriber.close();
39 | context.close();
40 | return 0;
41 | }
42 |
--------------------------------------------------------------------------------
/src/talker_zmq.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * talker_zmq.cpp
3 | * Author: Ravi Joshi
4 | * Date: 2018/01/18
5 | */
6 |
7 | #include
8 |
9 | #include
10 |
11 | int main(int argc, char** argv) {
12 | ros::init(argc, argv, "talker_zmq", ros::init_options::AnonymousName);
13 |
14 | ros::Time::init(); // Workaround since we are not using NodeHandle
15 | ros::Rate loop_rate(10);
16 |
17 | // Prepare our context and publisher
18 | zmq::context_t context(1);
19 | zmq::socket_t publisher(context, ZMQ_PUB);
20 | publisher.bind("tcp://*:6666");
21 |
22 | while (ros::ok()) {
23 | std::stringstream msg_str_stream;
24 | msg_str_stream << "hello_world_" << ros::Time::now();
25 | std::string msg_str = msg_str_stream.str();
26 |
27 | zmq::message_t message(msg_str.length());
28 | memcpy(message.data(), msg_str.c_str(), msg_str.length());
29 |
30 | ROS_INFO_STREAM(msg_str);
31 | publisher.send(message);
32 | loop_rate.sleep();
33 | }
34 | // Clean up your socket and context here
35 | publisher.close();
36 | context.close();
37 |
38 | return 0;
39 | }
40 |
--------------------------------------------------------------------------------