Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add UDP transport (backport #134) #135

Merged
merged 1 commit into from
Dec 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 27 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@ This tool aims to ease the micro-ROS integration in a STM32CubeMX/IDE project.
- [Middlewares available](#middlewares-available)
- [Using this package with STM32CubeMX](#using-this-package-with-stm32cubemx)
- [Using this package with STM32CubeIDE](#using-this-package-with-stm32cubeide)
- [Windows 11 (Community Contributed)](#STM32CubeIDE-Win11)
- [Windows 11 (Community Contributed)](#windows-11-community-contributed)
- [Transport configuration](#transport-configuration)
- [U(S)ART with DMA](#usart-with-dma)
- [U(S)ART with Interrupts](#usart-with-interrupts)
- [USB CDC](#usb-cdc)
- [UDP](#udp)
- [Customizing the micro-ROS library](#customizing-the-micro-ros-library)
- [Adding custom packages](#adding-custom-packages)
- [Purpose of the Project](#purpose-of-the-project)
Expand Down Expand Up @@ -134,6 +135,31 @@ Steps to configure:

**Note: The micro-ROS transport will override the autogenerated `USB_DEVICE/App/usbd_cdc_if.c` methods.**

### UDP

Steps to configure:
- Enable Ethernet in your STM32CubeMX/IDE `Connectivity` tab.
- Enable LwIP in your STM32CubeMX/IDE `Middleware` tab.
- Make sure that LwIP has the following configuration:

```
Platform Setting according to your own board
LwIP -> General Settings -> LWIP_DHCP -> Disabled
LwIP -> General Settings -> IP Address Settings (Set here the board address and mask)
LwIP -> General Settings -> LWIP UDP -> Enabled
LwIP -> General Settings -> Procols Options -> MEMP_NUM_UDP_PCB -> 15
LwIP -> Key Options -> LWIP_SO_RCVTIMEO -> Enable
```

**Note: Ensure your board and Agent are within the same LAN. The default port is 8888. You can modify it in `udp_transport.c`.If you are using a board from the STM32H7 series, please set up the MPU correctly.**

- Use `sample_main_udp.c` as a reference for writing your application code.
- Start the micro-ROS Agent with the following arguments:

```
ros2 run micro_ros_agent micro_ros_agent udp4 --port 8888 -v 6
```

## Customizing the micro-ROS library

All the micro-ROS configuration can be done in `colcon.meta` file before step 3. You can find detailed information about how to tune the static memory usage of the library in the [Middleware Configuration tutorial](https://micro.ros.org/docs/tutorials/advanced/microxrcedds_rmw_configuration/).
Expand Down
79 changes: 79 additions & 0 deletions extra_sources/microros_transports/udp_transport.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#include <uxr/client/transport.h>

#include <rmw_microxrcedds_c/config.h>

#include "main.h"
#include "cmsis_os.h"

#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>

// --- LWIP ---
#include "lwip/opt.h"
#include "lwip/sys.h"
#include "lwip/api.h"
#include <lwip/sockets.h>

#ifdef RMW_UXRCE_TRANSPORT_CUSTOM

// --- micro-ROS Transports ---
#define UDP_PORT 8888
static int sock_fd = -1;

bool cubemx_transport_open(struct uxrCustomTransport * transport){
sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(UDP_PORT);
addr.sin_addr.s_addr = htonl(INADDR_ANY);

if (bind(sock_fd, (struct sockaddr *)&addr, sizeof(addr)) == -1)
{
return false;
}

return true;
}

bool cubemx_transport_close(struct uxrCustomTransport * transport){
if (sock_fd != -1)
{
closesocket(sock_fd);
sock_fd = -1;
}
return true;
}

size_t cubemx_transport_write(struct uxrCustomTransport* transport, uint8_t * buf, size_t len, uint8_t * err){
if (sock_fd == -1)
{
return 0;
}
const char * ip_addr = (const char*) transport->args;
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(UDP_PORT);
addr.sin_addr.s_addr = inet_addr(ip_addr);
int ret = 0;
ret = sendto(sock_fd, buf, len, 0, (struct sockaddr *)&addr, sizeof(addr));
size_t writed = ret>0? ret:0;

return writed;
}

size_t cubemx_transport_read(struct uxrCustomTransport* transport, uint8_t* buf, size_t len, int timeout, uint8_t* err){

int ret = 0;
//set timeout
struct timeval tv_out;
tv_out.tv_sec = timeout / 1000;
tv_out.tv_usec = (timeout % 1000) * 1000;
setsockopt(sock_fd, SOL_SOCKET, SO_RCVTIMEO,&tv_out, sizeof(tv_out));
ret = recv(sock_fd, buf, len, MSG_WAITALL);
size_t readed = ret > 0 ? ret : 0;
return readed;
}

#endif
Loading