├── .gitignore
├── CMakeLists.txt
├── LICENSE
├── README.md
├── package.xml
└── src
├── examples
├── chatter
│ ├── CMakeLists.txt
│ ├── Makefile
│ ├── README.md
│ └── main
│ │ ├── CMakeLists.txt
│ │ ├── component.mk
│ │ ├── esp_chatter.cpp
│ │ ├── include
│ │ └── esp_chatter.h
│ │ └── main.c
└── echo
│ ├── CMakeLists.txt
│ ├── Makefile
│ ├── README.md
│ └── main
│ ├── CMakeLists.txt
│ ├── component.mk
│ ├── esp_echo.cpp
│ ├── include
│ └── esp_echo.h
│ └── main.c
├── ros_lib
├── CMakeLists.txt
├── ESP32Hardware.h
├── Kconfig
├── esp_ros_wifi.c
├── esp_ros_wifi.h
└── ros.h
└── rosserial_esp32
└── make_libraries.py
/.gitignore:
--------------------------------------------------------------------------------
1 | build/
2 | bin/
3 | lib/
4 | msg_gen/
5 | srv_gen/
6 | msg/*Action.msg
7 | msg/*ActionFeedback.msg
8 | msg/*ActionGoal.msg
9 | msg/*ActionResult.msg
10 | msg/*Feedback.msg
11 | msg/*Goal.msg
12 | msg/*Result.msg
13 | msg/_*.py
14 |
15 | # Generated by dynamic reconfigure
16 | *.cfgc
17 | /cfg/cpp/
18 | /cfg/*.py
19 |
20 | # Ignore generated docs
21 | *.dox
22 | *.wikidoc
23 |
24 | # eclipse stuff
25 | .project
26 | .cproject
27 |
28 | # qcreator stuff
29 | CMakeLists.txt.user
30 |
31 | srv/_*.py
32 | *.pcd
33 | *.pyc
34 | qtcreator-*
35 | *.user
36 |
37 | /planning/cfg
38 | /planning/docs
39 | /planning/src
40 |
41 | *~
42 |
43 | # Emacs
44 | .#*
45 |
46 | # Catkin custom files
47 | CATKIN_IGNORE
48 |
49 | # IDF specific files
50 | sdkconfig
51 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 2.8.3)
2 | project(rosserial_esp32)
3 |
4 | ## Compile as C++11, supported in ROS Kinetic and newer
5 | # add_compile_options(-std=c++11)
6 |
7 | ## Find catkin macros and libraries
8 | ## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
9 | ## is used, also find other catkin packages
10 | find_package(catkin REQUIRED COMPONENTS
11 | message_generation
12 | )
13 |
14 | ## System dependencies are found with CMake's conventions
15 | # find_package(Boost REQUIRED COMPONENTS system)
16 |
17 |
18 | ## Uncomment this if the package has a setup.py. This macro ensures
19 | ## modules and global scripts declared therein get installed
20 | ## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html
21 | # catkin_python_setup()
22 |
23 | ################################################
24 | ## Declare ROS messages, services and actions ##
25 | ################################################
26 |
27 | ## To declare and build messages, services or actions from within this
28 | ## package, follow these steps:
29 | ## * Let MSG_DEP_SET be the set of packages whose message types you use in
30 | ## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...).
31 | ## * In the file package.xml:
32 | ## * add a build_depend tag for "message_generation"
33 | ## * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET
34 | ## * If MSG_DEP_SET isn't empty the following dependency has been pulled in
35 | ## but can be declared for certainty nonetheless:
36 | ## * add a exec_depend tag for "message_runtime"
37 | ## * In this file (CMakeLists.txt):
38 | ## * add "message_generation" and every package in MSG_DEP_SET to
39 | ## find_package(catkin REQUIRED COMPONENTS ...)
40 | ## * add "message_runtime" and every package in MSG_DEP_SET to
41 | ## catkin_package(CATKIN_DEPENDS ...)
42 | ## * uncomment the add_*_files sections below as needed
43 | ## and list every .msg/.srv/.action file to be processed
44 | ## * uncomment the generate_messages entry below
45 | ## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...)
46 |
47 | ## Generate messages in the 'msg' folder
48 | # add_message_files(
49 | # FILES
50 | # Message1.msg
51 | # Message2.msg
52 | # )
53 |
54 | ## Generate services in the 'srv' folder
55 | # add_service_files(
56 | # FILES
57 | # Service1.srv
58 | # Service2.srv
59 | # )
60 |
61 | ## Generate actions in the 'action' folder
62 | # add_action_files(
63 | # FILES
64 | # Action1.action
65 | # Action2.action
66 | # )
67 |
68 | ## Generate added messages and services with any dependencies listed here
69 | generate_messages(
70 | # DEPENDENCIES
71 | # rosserial_msgs
72 | )
73 |
74 | ################################################
75 | ## Declare ROS dynamic reconfigure parameters ##
76 | ################################################
77 |
78 | ## To declare and build dynamic reconfigure parameters within this
79 | ## package, follow these steps:
80 | ## * In the file package.xml:
81 | ## * add a build_depend and a exec_depend tag for "dynamic_reconfigure"
82 | ## * In this file (CMakeLists.txt):
83 | ## * add "dynamic_reconfigure" to
84 | ## find_package(catkin REQUIRED COMPONENTS ...)
85 | ## * uncomment the "generate_dynamic_reconfigure_options" section below
86 | ## and list every .cfg file to be processed
87 |
88 | ## Generate dynamic reconfigure parameters in the 'cfg' folder
89 | # generate_dynamic_reconfigure_options(
90 | # cfg/DynReconf1.cfg
91 | # cfg/DynReconf2.cfg
92 | # )
93 |
94 | ###################################
95 | ## catkin specific configuration ##
96 | ###################################
97 | ## The catkin_package macro generates cmake config files for your package
98 | ## Declare things to be passed to dependent projects
99 | ## INCLUDE_DIRS: uncomment this if your package contains header files
100 | ## LIBRARIES: libraries you create in this project that dependent projects also need
101 | ## CATKIN_DEPENDS: catkin_packages dependent projects also need
102 | ## DEPENDS: system dependencies of this project that dependent projects also need
103 | catkin_package(
104 | # INCLUDE_DIRS include
105 | # LIBRARIES rosserial_esp32
106 | CATKIN_DEPENDS message_runtime
107 | # DEPENDS system_lib
108 | )
109 |
110 | ###########
111 | ## Build ##
112 | ###########
113 |
114 | ## Specify additional locations of header files
115 | ## Your package locations should be listed before other locations
116 | include_directories(
117 | # include
118 | ${catkin_INCLUDE_DIRS}
119 | )
120 |
121 | ## Declare a C++ library
122 | # add_library(${PROJECT_NAME}
123 | # src/${PROJECT_NAME}/rosserial_esp32.cpp
124 | # )
125 |
126 | ## Add cmake target dependencies of the library
127 | ## as an example, code may need to be generated before libraries
128 | ## either from message generation or dynamic reconfigure
129 | # add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
130 |
131 | ## Declare a C++ executable
132 | ## With catkin_make all packages are built within a single CMake context
133 | ## The recommended prefix ensures that target names across packages don't collide
134 | # add_executable(${PROJECT_NAME}_node src/rosserial_esp32_node.cpp)
135 |
136 | ## Rename C++ executable without prefix
137 | ## The above recommended prefix causes long target names, the following renames the
138 | ## target back to the shorter version for ease of user use
139 | ## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node"
140 | # set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "")
141 |
142 | ## Add cmake target dependencies of the executable
143 | ## same as for the library above
144 | # add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
145 |
146 | ## Specify libraries to link a library or executable target against
147 | # target_link_libraries(${PROJECT_NAME}_node
148 | # ${catkin_LIBRARIES}
149 | # )
150 |
151 | #############
152 | ## Install ##
153 | #############
154 |
155 | # all install targets should use catkin DESTINATION variables
156 | # See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html
157 |
158 | ## Mark executable scripts (Python etc.) for installation
159 | ## in contrast to setup.py, you can choose the destination
160 | # install(PROGRAMS
161 | # scripts/my_python_script
162 | # DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
163 | # )
164 |
165 | ## Mark executables and/or libraries for installation
166 | # install(TARGETS ${PROJECT_NAME} ${PROJECT_NAME}_node
167 | # ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
168 | # LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
169 | # RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
170 | # )
171 |
172 | ## Mark cpp header files for installation
173 | # install(DIRECTORY include/${PROJECT_NAME}/
174 | # DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
175 | # FILES_MATCHING PATTERN "*.h"
176 | # PATTERN ".svn" EXCLUDE
177 | # )
178 |
179 | ## Mark other files for installation (e.g. launch and bag files, etc.)
180 | install(DIRECTORY
181 | src/ros_lib
182 | # myfile2
183 | DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}/src
184 | )
185 |
186 | catkin_install_python(
187 | PROGRAMS src/${PROJECT_NAME}/make_libraries.py
188 | DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}
189 | )
190 |
191 | #############
192 | ## Testing ##
193 | #############
194 |
195 | ## Add gtest based cpp test target and link libraries
196 | # catkin_add_gtest(${PROJECT_NAME}-test test/test_rosserial_esp32.cpp)
197 | # if(TARGET ${PROJECT_NAME}-test)
198 | # target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME})
199 | # endif()
200 |
201 | ## Add folders to be run by python nosetests
202 | # catkin_add_nosetests(test)
203 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | BSD License
2 | -----------
3 |
4 | Copyright (c) 2019 Sachin Parekh
5 | All rights reserved.
6 |
7 | Redistribution and use in source and binary forms, with or without modification,
8 | are permitted provided that the following conditions are met:
9 |
10 | * Redistributions of source code must retain the above copyright notice, this
11 | list of conditions and the following disclaimer.
12 |
13 | * Redistributions in binary form must reproduce the above copyright notice, this
14 | list of conditions and the following disclaimer in the documentation and/or
15 | other materials provided with the distribution.
16 |
17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
21 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
24 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## rosserial_esp32
2 |
3 | This package is based on [rosserial](http://wiki.ros.org/rosserial) to enable communication between ROS and ESP32 using ESP-IDF.
4 |
5 | Supports rosserial communication over **UART** and **WiFi**
6 |
7 | ### Generate ROS libraries
8 | Follow the steps below in order to generate and include ROS libraries
9 | (This will create a component in IDF_PATH and need to generate it only once)
10 |
11 | ```
12 | $ cd path/to/catkin_ws/src/
13 | $ git clone https:/www.github.com/sachin0x18/rosserial_esp32.git
14 | $ rosrun rosserial_esp32 make_libraries.py $IDF_PATH/components/
15 | ```
16 |
17 | After execution of above commands, all the necessary ROS files would have been generated in `$IDF_PATH/components/rosserial_esp32/`
18 |
19 | ### Examples
20 | * [chatter](src/examples/chatter)
21 | * [echo](src/examples/echo)
22 |
--------------------------------------------------------------------------------
/package.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | rosserial_esp32
4 | 1.0.0
5 | rosserial_client for ESP32 on ESP-IDF
6 |
7 |
8 |
9 |
10 | Sachin Parekh
11 |
12 |
13 |
14 |
15 |
16 | BSD
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 | catkin
43 |
44 | message_generation
45 |
46 | message_runtime
47 | rospy
48 | rosserial_client
49 | rosserial_msgs
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
--------------------------------------------------------------------------------
/src/examples/chatter/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # The following lines of boilerplate have to be in your project's
2 | # CMakeLists in this exact order for cmake to work correctly
3 | cmake_minimum_required(VERSION 3.5)
4 |
5 | include($ENV{IDF_PATH}/tools/cmake/project.cmake)
6 | project(chatter)
7 |
--------------------------------------------------------------------------------
/src/examples/chatter/Makefile:
--------------------------------------------------------------------------------
1 | #
2 | # This is a project Makefile. It is assumed the directory this Makefile resides in is a
3 | # project subdirectory.
4 | #
5 |
6 | PROJECT_NAME := chatter
7 |
8 | include $(IDF_PATH)/make/project.mk
9 |
--------------------------------------------------------------------------------
/src/examples/chatter/README.md:
--------------------------------------------------------------------------------
1 | ## Chatter
2 |
3 | This code publishes data on the topic `chatter`
4 |
5 | ### Build and Flash
6 |
7 | Generate the ROS libraries prior to building this example as instructed in the [README](../../../README.md) of root directory
8 |
9 | Default mode of rosserial communication is over UART.
10 |
11 | To use WiFi:
12 | 1. Enable rosserial over WiFi
13 |
14 | `idf.py menuconfig` -> `Component config` -> `rosserial` ->`rosserial over WiFi using TCP`
15 |
16 | 2. Enter WiFi and server details
17 |
18 | ```
19 | $ export ESPPORT=/dev/ttyUSB0
20 | $ idf.py build flash
21 | ```
22 |
23 | On a new terminal
24 |
25 | ```
26 | $ roscore
27 | ```
28 |
29 | On another new terminal
30 |
31 | -- UART
32 | ```
33 | $ rosrun rosserial_python serial_node.py _baud:=11520
34 | ```
35 | -- WiFi
36 | ```
37 | $ rosrun rosserial_python serial_node.py tcp
38 | ```
39 |
40 | On another new terminal
41 |
42 | ```
43 | $ rostopic echo chatter
44 | ```
45 |
--------------------------------------------------------------------------------
/src/examples/chatter/main/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | idf_component_register(SRCS "main.c"
2 | "esp_chatter.cpp"
3 | INCLUDE_DIRS "include")
4 |
--------------------------------------------------------------------------------
/src/examples/chatter/main/component.mk:
--------------------------------------------------------------------------------
1 | #
2 | # "main" pseudo-component makefile.
3 | #
4 | # (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
5 |
6 |
--------------------------------------------------------------------------------
/src/examples/chatter/main/esp_chatter.cpp:
--------------------------------------------------------------------------------
1 | #include "ros.h"
2 | #include "std_msgs/String.h"
3 | #include "esp_chatter.h"
4 |
5 | ros::NodeHandle nh;
6 |
7 | std_msgs::String str_msg;
8 | ros::Publisher chatter("chatter", &str_msg);
9 |
10 | char hello[13] = "hello world!";
11 |
12 | void rosserial_setup()
13 | {
14 | // Initialize ROS
15 | nh.initNode();
16 | nh.advertise(chatter);
17 | }
18 |
19 | void rosserial_publish()
20 | {
21 | str_msg.data = hello;
22 | // Send the message
23 | chatter.publish(&str_msg);
24 | nh.spinOnce();
25 | }
26 |
--------------------------------------------------------------------------------
/src/examples/chatter/main/include/esp_chatter.h:
--------------------------------------------------------------------------------
1 | #ifndef ESP_CHATTER_H
2 | #define ESP_CHATTER_H
3 |
4 | #ifdef __cplusplus
5 | extern "C" {
6 | #endif
7 |
8 | void rosserial_setup();
9 |
10 | void rosserial_publish();
11 |
12 | #ifdef __cplusplus
13 | }
14 | #endif
15 |
16 | #endif /* ESP_CHATTER_H */
17 |
--------------------------------------------------------------------------------
/src/examples/chatter/main/main.c:
--------------------------------------------------------------------------------
1 | #include "stdio.h"
2 | #include "esp_chatter.h"
3 | #include "freertos/FreeRTOS.h"
4 | #include "freertos/task.h"
5 |
6 | int app_main()
7 | {
8 | rosserial_setup();
9 | while(1) {
10 | rosserial_publish();
11 | vTaskDelay(100);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/examples/echo/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # The following lines of boilerplate have to be in your project's
2 | # CMakeLists in this exact order for cmake to work correctly
3 | cmake_minimum_required(VERSION 3.5)
4 |
5 | include($ENV{IDF_PATH}/tools/cmake/project.cmake)
6 | project(echo)
7 |
--------------------------------------------------------------------------------
/src/examples/echo/Makefile:
--------------------------------------------------------------------------------
1 | #
2 | # This is a project Makefile. It is assumed the directory this Makefile resides in is a
3 | # project subdirectory.
4 | #
5 |
6 | PROJECT_NAME := echo
7 |
8 | include $(IDF_PATH)/make/project.mk
9 |
--------------------------------------------------------------------------------
/src/examples/echo/README.md:
--------------------------------------------------------------------------------
1 | ## Echo
2 |
3 | This code subscribes to `echo` and publishes on `ack`
4 | The data received on `echo` will be published on `ack`
5 |
6 | ### Build and Flash
7 |
8 | Generate the ROS libraries prior to building this example as instructed in the [README](../../../README.md) of root directory (If done already, ignore)
9 |
10 | Default mode of rosserial communication is over UART.
11 |
12 | To use WiFi:
13 | 1. Enable rosserial over WiFi
14 |
15 | `idf.py menuconfig` -> `Component config` -> `rosserial` ->`rosserial over WiFi using TCP`
16 |
17 | 2. Enter WiFi and server details
18 |
19 | ```
20 | $ export ESPPORT=/dev/ttyUSB0
21 | $ idf.py build flash
22 | ```
23 |
24 | On a new terminal
25 |
26 | ```
27 | $ roscore
28 | ```
29 |
30 | On another new terminal
31 |
32 | -- UART
33 | ```
34 | $ rosrun rosserial_python serial_node.py _baud:=11520
35 | ```
36 | -- WiFi
37 | ```
38 | $ rosrun rosserial_python serial_node.py tcp
39 | ```
40 |
41 | On another new terminal
42 | ```
43 | $ rostopic echo ack
44 | ```
45 |
46 | On another new terminal
47 | ```
48 | rostopic pub echo std_msgs/String "Hello World\!" --once
49 | ```
50 |
--------------------------------------------------------------------------------
/src/examples/echo/main/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | idf_component_register(SRCS "main.c"
2 | "esp_echo.cpp"
3 | INCLUDE_DIRS "include")
4 |
--------------------------------------------------------------------------------
/src/examples/echo/main/component.mk:
--------------------------------------------------------------------------------
1 | #
2 | # "main" pseudo-component makefile.
3 | #
4 | # (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
5 |
6 |
--------------------------------------------------------------------------------
/src/examples/echo/main/esp_echo.cpp:
--------------------------------------------------------------------------------
1 | #include "ros.h"
2 | #include "std_msgs/String.h"
3 | #include "esp_echo.h"
4 |
5 | ros::NodeHandle nh;
6 |
7 | std_msgs::String str_msg;
8 | ros::Publisher ack("ack", &str_msg);
9 |
10 | void messageCb( const std_msgs::String& msg){
11 | ack.publish(&msg);
12 | }
13 |
14 | ros::Subscriber echo("echo", &messageCb);
15 |
16 | void rosserial_setup()
17 | {
18 | // Initialize ROS
19 | nh.initNode();
20 | nh.subscribe(echo);
21 | nh.advertise(ack);
22 | }
23 |
24 | void rosserial_spinonce()
25 | {
26 | nh.spinOnce();
27 | }
28 |
--------------------------------------------------------------------------------
/src/examples/echo/main/include/esp_echo.h:
--------------------------------------------------------------------------------
1 | #ifndef ESP_SUBSCRIBER_H
2 | #define ESP_SUBSCRIBER_H
3 |
4 | #ifdef __cplusplus
5 | extern "C" {
6 | #endif
7 |
8 | void rosserial_setup();
9 |
10 | void rosserial_spinonce();
11 |
12 | #ifdef __cplusplus
13 | }
14 | #endif
15 |
16 | #endif /* ESP_SUBSCRIBER_H */
17 |
--------------------------------------------------------------------------------
/src/examples/echo/main/main.c:
--------------------------------------------------------------------------------
1 | #include "stdio.h"
2 | #include "esp_echo.h"
3 | #include "freertos/FreeRTOS.h"
4 | #include "freertos/task.h"
5 |
6 | int app_main()
7 | {
8 | rosserial_setup();
9 |
10 | while(1) {
11 | rosserial_spinonce();
12 | vTaskDelay(100);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/ros_lib/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | set (srcs
2 | "duration.cpp"
3 | "time.cpp")
4 |
5 | if(CONFIG_ROSSERIAL_OVER_WIFI)
6 | list(APPEND srcs "esp_ros_wifi.c")
7 | endif()
8 |
9 |
10 | idf_component_register(SRCS "${srcs}"
11 | INCLUDE_DIRS "include"
12 | REQUIRES vfs nvs_flash)
13 |
--------------------------------------------------------------------------------
/src/ros_lib/ESP32Hardware.h:
--------------------------------------------------------------------------------
1 | #ifndef ROS_ESP32_HARDWARE_H_
2 | #define ROS_ESP32_HARDWARE_H_
3 |
4 | extern "C" {
5 | #include "sdkconfig.h"
6 | #include "stdio.h"
7 | #include "esp_err.h"
8 | #include "esp_timer.h"
9 | #include
10 | #include "esp_ros_wifi.h"
11 | }
12 |
13 | #define ROS_SERVER_IP CONFIG_ROSSERVER_IP
14 | #define ROS_SERVER_PORT CONFIG_ROSSERVER_PORT
15 |
16 | #define UART_PORT UART_NUM_0
17 | #define UART_TX_PIN GPIO_NUM_1
18 | #define UART_RX_PIN GPIO_NUM_3
19 |
20 | class ESP32Hardware
21 | {
22 | protected:
23 | uint8_t rx_buf[1024];
24 |
25 | public:
26 | ESP32Hardware()
27 | {
28 | }
29 |
30 | // Initialization code for ESP32
31 | void init()
32 | {
33 | #ifdef CONFIG_ROSSERIAL_OVER_WIFI
34 | esp_ros_wifi_init();
35 | ros_tcp_connect(ROS_SERVER_IP, ROS_SERVER_PORT);
36 | #else
37 | uart_driver_install(UART_PORT, 1024, 1024, 0, NULL, 0);
38 |
39 | //Changing the baudrate will change the baudrate of serial monitor as well
40 | //uart_set_baudrate(UART_PORT, 57600);
41 | #endif
42 | }
43 |
44 | // read a byte from the serial port. -1 = failure
45 | int read()
46 | {
47 | int read_len;
48 | #ifdef CONFIG_ROSSERIAL_OVER_WIFI
49 | read_len = ros_tcp_read(rx_buf, 1);
50 | #else
51 | read_len = uart_read_bytes(UART_PORT, (uint8_t *)rx_buf, 1, 0);
52 | #endif
53 | if (read_len == 1) {
54 | return rx_buf[0];
55 | } else {
56 | return -1;
57 | }
58 | }
59 |
60 | // write data to the connection to ROS
61 | void write(uint8_t* data, int length)
62 | {
63 | #ifdef CONFIG_ROSSERIAL_OVER_WIFI
64 | ros_tcp_send(data, length);
65 | #else
66 | uart_write_bytes(UART_PORT, (char*)data, (size_t)length);
67 | #endif
68 | }
69 |
70 | // returns milliseconds since start of program
71 | unsigned long time()
72 | {
73 | return esp_timer_get_time() / 1000;
74 | }
75 | };
76 | #endif
77 |
--------------------------------------------------------------------------------
/src/ros_lib/Kconfig:
--------------------------------------------------------------------------------
1 | menu "rosserial"
2 |
3 | config ROSSERIAL_OVER_WIFI
4 | bool "rosserial over WiFi using TCP"
5 | default n
6 | help
7 | Use rosserial over WiFi using TCP
8 |
9 | config ROSSERVER_AP
10 | string "WiFi SSID"
11 | default "myssid"
12 | depends on ROSSERIAL_OVER_WIFI
13 | help
14 | SSID (Access point name) of WiFi to connect
15 |
16 | config ROSSERVER_PASS
17 | string "WiFi Password"
18 | default "mypass"
19 | depends on ROSSERIAL_OVER_WIFI
20 | help
21 | Password of the WiFi
22 |
23 | config ROSSERVER_IP
24 | string "IP address of ROS server (roscore)"
25 | default "192.168.0.1"
26 | depends on ROSSERIAL_OVER_WIFI
27 | help
28 | IP address of machine which is running rosserial server
29 |
30 | config ROSSERVER_PORT
31 | int "Port number of ROS server"
32 | default 11411
33 | depends on ROSSERIAL_OVER_WIFI
34 | help
35 | Port number of rosserial server
36 |
37 | Port number is printed on terminal running rosserial_python
38 |
39 | endmenu
40 |
--------------------------------------------------------------------------------
/src/ros_lib/esp_ros_wifi.c:
--------------------------------------------------------------------------------
1 | /*
2 | * WiFi initialization for setting up ROS communication over TCP sockets
3 | */
4 |
5 | #include
6 | #include "freertos/FreeRTOS.h"
7 | #include "freertos/task.h"
8 | #include "freertos/event_groups.h"
9 | #include "esp_system.h"
10 | #include "esp_wifi.h"
11 | #include "esp_event_loop.h"
12 | #include "esp_log.h"
13 | #include "nvs_flash.h"
14 | #include "sdkconfig.h"
15 |
16 | #include "lwip/err.h"
17 | #include "lwip/sockets.h"
18 | #include "lwip/sys.h"
19 | #include
20 |
21 | #define MAXIMUM_RETRY 5
22 |
23 | #define ROS_SERVER_AP CONFIG_ROSSERVER_AP
24 | #define ROS_SERVER_PASS CONFIG_ROSSERVER_PASS
25 |
26 | static EventGroupHandle_t wifi_event_group;
27 |
28 | const int IPV4_GOTIP_BIT = BIT0;
29 |
30 | static const char *TAG = "esp-ros-wifi";
31 |
32 | static int s_retry_num = 0;
33 |
34 | static char addr_str[128];
35 | static int addr_family;
36 | static int ip_protocol;
37 | static int sock;
38 |
39 | static esp_err_t event_handler(void *ctx, system_event_t *event)
40 | {
41 | switch(event->event_id) {
42 | case SYSTEM_EVENT_STA_START:
43 | esp_wifi_connect();
44 | break;
45 | case SYSTEM_EVENT_STA_GOT_IP:
46 | ESP_LOGI(TAG, "got ip:%s",
47 | ip4addr_ntoa(&event->event_info.got_ip.ip_info.ip));
48 | s_retry_num = 0;
49 | xEventGroupSetBits(wifi_event_group, IPV4_GOTIP_BIT);
50 | break;
51 | case SYSTEM_EVENT_STA_DISCONNECTED:
52 | {
53 | if (s_retry_num < MAXIMUM_RETRY) {
54 | esp_wifi_connect();
55 | xEventGroupClearBits(wifi_event_group, IPV4_GOTIP_BIT);
56 | s_retry_num++;
57 | ESP_LOGI(TAG,"Retrying connection to AP");
58 | }
59 | ESP_LOGE(TAG,"Failed to connect to AP");
60 | break;
61 | }
62 | default:
63 | break;
64 | }
65 | return ESP_OK;
66 | }
67 |
68 | void esp_ros_wifi_init()
69 | {
70 | nvs_flash_init();
71 |
72 | wifi_event_group = xEventGroupCreate();
73 |
74 | tcpip_adapter_init();
75 | ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL) );
76 |
77 | wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
78 | ESP_ERROR_CHECK(esp_wifi_init(&cfg));
79 | wifi_config_t wifi_config = {
80 | .sta = {
81 | .ssid = ROS_SERVER_AP,
82 | .password = ROS_SERVER_PASS,
83 | },
84 | };
85 |
86 | ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) );
87 | ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) );
88 | ESP_ERROR_CHECK(esp_wifi_start());
89 |
90 | ESP_LOGI(TAG, "Waiting for AP connection...");
91 | xEventGroupWaitBits(wifi_event_group, IPV4_GOTIP_BIT, false, true, portMAX_DELAY);
92 | ESP_LOGI(TAG, "Connected to AP");
93 | }
94 |
95 | void ros_tcp_connect(const char* host_ip, int port_num)
96 | {
97 | struct sockaddr_in destAddr;
98 | destAddr.sin_addr.s_addr = inet_addr(host_ip);
99 | destAddr.sin_family = AF_INET;
100 | destAddr.sin_port = htons(port_num);
101 | addr_family = AF_INET;
102 | ip_protocol = IPPROTO_IP;
103 | inet_ntoa_r(destAddr.sin_addr, addr_str, sizeof(addr_str) - 1);
104 |
105 | sock = socket(addr_family, SOCK_STREAM, ip_protocol);
106 | if (sock < 0) {
107 | ESP_LOGE(TAG, "Unable to create socket: errno %d", errno);
108 | }
109 |
110 | /* Set sock to non-blocking mode (ASYNC)
111 | * "Lost sync with device, restarting.." error occurs if socket is blocking
112 | */
113 | fcntl(sock, F_SETFL, O_NONBLOCK);
114 |
115 | int err = connect(sock, (struct sockaddr *)&destAddr, sizeof(destAddr));
116 | if (err != 0 && errno != 119) {
117 | ESP_LOGE(TAG, "Socket unable to connect: errno %d", errno);
118 | }
119 | ESP_LOGI(TAG, "Successfully connected");
120 | }
121 |
122 | void ros_tcp_send(uint8_t* data, int length)
123 | {
124 | int err = send(sock, data, length, 0);
125 | if (err < 0) {
126 | ESP_LOGE(TAG, "Error occured during sending: errno %d", errno);
127 | }
128 | }
129 |
130 | int ros_tcp_read(uint8_t* buf, int length)
131 | {
132 | int len = recv(sock, buf, length, 0);
133 | if (len < 0 && errno != 11) {
134 | ESP_LOGE(TAG, "Error receiving data: errno %d", errno);
135 | return -1;
136 | }
137 | return len;
138 | }
139 |
--------------------------------------------------------------------------------
/src/ros_lib/esp_ros_wifi.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | void esp_ros_wifi_init();
4 |
5 | void ros_tcp_connect(const char* host_ip, int port_num);
6 |
7 | void ros_tcp_send(uint8_t* data, int length);
8 |
9 | int ros_tcp_read(uint8_t* buf, int length);
10 |
--------------------------------------------------------------------------------
/src/ros_lib/ros.h:
--------------------------------------------------------------------------------
1 | #ifndef _ROS_H_
2 | #define _ROS_H_
3 |
4 | #include "ros/node_handle.h"
5 | #include "ESP32Hardware.h"
6 |
7 | namespace ros
8 | {
9 | typedef NodeHandle_ NodeHandle; // default 25, 25, 512, 512
10 | }
11 |
12 | #endif
13 |
--------------------------------------------------------------------------------
/src/rosserial_esp32/make_libraries.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | # Software License Agreement (BSD License)
4 | #
5 | # Copyright (c) 2019, Sachin Parekh
6 | # All rights reserved.
7 | #
8 | # Redistribution and use in source and binary forms, with or without
9 | # modification, are permitted provided that the following conditions
10 | # are met:
11 | #
12 | # * Redistributions of source code must retain the above copyright
13 | # notice, this list of conditions and the following disclaimer.
14 | # * Redistributions in binary form must reproduce the above
15 | # copyright notice, this list of conditions and the following
16 | # disclaimer in the documentation and/or other materials provided
17 | # with the distribution.
18 | #
19 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22 | # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23 | # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24 | # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25 | # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 | # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29 | # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 | # POSSIBILITY OF SUCH DAMAGE.
31 |
32 | import rospkg
33 | import rosserial_client
34 | from rosserial_client.make_library import *
35 |
36 | THIS_PACKAGE = "rosserial_esp32"
37 |
38 | __usage__ = """
39 | make_libraries.py generates the ESP32 rosserial library files for ESP32 (ESP-IDF).
40 | It requires the location of your esp-idf/components folder.
41 |
42 | rosrun rosserial_esp32 make_libraries.py $IDF_PATH/components
43 | """
44 |
45 | # for copying files
46 | import shutil
47 |
48 | ROS_TO_EMBEDDED_TYPES = {
49 | 'bool' : ('bool', 1, PrimitiveDataType, []),
50 | 'byte' : ('int8_t', 1, PrimitiveDataType, []),
51 | 'int8' : ('int8_t', 1, PrimitiveDataType, []),
52 | 'char' : ('char', 1, PrimitiveDataType, []),
53 | 'uint8' : ('uint8_t', 1, PrimitiveDataType, []),
54 | 'int16' : ('int16_t', 2, PrimitiveDataType, []),
55 | 'uint16' : ('uint16_t', 2, PrimitiveDataType, []),
56 | 'int32' : ('int32_t', 4, PrimitiveDataType, []),
57 | 'uint32' : ('uint32_t', 4, PrimitiveDataType, []),
58 | 'int64' : ('int64_t', 8, PrimitiveDataType, []),
59 | 'uint64' : ('uint64_t', 8, PrimitiveDataType, []),
60 | 'float32' : ('float', 4, PrimitiveDataType, []),
61 | 'float64' : ('double', 8, PrimitiveDataType, []),
62 | 'time' : ('ros::Time', 8, TimeDataType, ['ros/time']),
63 | 'duration': ('ros::Duration', 8, TimeDataType, ['ros/duration']),
64 | 'string' : ('char*', 0, StringDataType, []),
65 | 'Header' : ('std_msgs::Header', 0, MessageDataType, ['std_msgs/Header'])
66 | }
67 |
68 | # need correct inputs
69 | if (len(sys.argv) < 2):
70 | print __usage__
71 | exit()
72 |
73 | # get output path
74 | path = sys.argv[1]
75 |
76 | if path[-1] == "/":
77 | path = path[0:-1]
78 | print "\nExporting to %s" % path
79 |
80 | rospack = rospkg.RosPack()
81 |
82 | # Create rosserial_esp32 component folder if it doesn't exists
83 | if not os.path.exists(path+"/rosserial_esp32/"):
84 | os.makedirs(path+"/rosserial_esp32/include/")
85 | with open(path+"/rosserial_esp32/component.mk", "w") as file:
86 | pass
87 |
88 | # copy ros_lib stuff in
89 | rosserial_esp32_dir = rospack.get_path(THIS_PACKAGE)
90 | files = os.listdir(rosserial_esp32_dir+"/src/ros_lib")
91 | for f in files:
92 | if os.path.isfile(rosserial_esp32_dir+"/src/ros_lib/"+f):
93 | if f.endswith(".h"):
94 | shutil.copy(rosserial_esp32_dir+"/src/ros_lib/"+f, path+"/rosserial_esp32/include/")
95 | else:
96 | shutil.copy(rosserial_esp32_dir+"/src/ros_lib/"+f, path+"/rosserial_esp32/")
97 |
98 | rosserial_client_copy_files(rospack, path+"/rosserial_esp32/include/")
99 |
100 | # generate messages
101 | rosserial_generate(rospack, path+"/rosserial_esp32/include/", ROS_TO_EMBEDDED_TYPES)
102 |
103 | # Move source files to parent directory
104 | src_files = os.listdir(path+"/rosserial_esp32/include/")
105 | for f in src_files:
106 | if f.endswith(".cpp"):
107 | shutil.move(path+"/rosserial_esp32/include/"+f, path+"/rosserial_esp32/")
108 |
--------------------------------------------------------------------------------