diff --git a/CHANGELOG.rst b/CHANGELOG.rst new file mode 100644 index 0000000..094c072 --- /dev/null +++ b/CHANGELOG.rst @@ -0,0 +1,58 @@ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Changelog for package micro_ros_stmcube +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +3.0.2 (2024-06-03) +------------------ +* Add UDP transport (`#134 `_) (`#136 `_) + * Add UDP transport + * Apply suggestions from code review + Co-authored-by: Pablo Garrido + * Update README and modify recv flag + * Update udp_transport.c + * Apply suggestions from code review + Co-authored-by: Pablo Garrido + * Update udp_transport.c + * Minor fixes on readme + --------- + Co-authored-by: Pablo Garrido + (cherry picked from commit 0dbe8b656cf48ef6b8194f047029711fc09cc9bb) + Co-authored-by: Lion Hao +* Workaround to use STMCubeIDE in Windows 11 (backport `#127 `_) (`#128 `_) + Co-authored-by: Pablo Garrido + Co-authored-by: Leonardo +* Contributors: mergify[bot] + +3.0.1 (2023-06-12) +------------------ +* Add USB CDC transport (`#89 `_) +* Improved repository clarity (`#74 `_) +* Fix USER_CUSTOM_PACKAGES_DIR (`#67 `_) (`#70 `_) +* microros_component/extra_packages support (`#63 `_) (`#65 `_) + +3.0.0 (2022-05-25) +------------------ +* Humble release (`#61 `_) +* Update banner (`#56 `_) +* Fix include paths (`#47 `_) +* Add check for NULL input pointer (`#53 `_) (`#55 `_) +* Fix broken pvPortReallocMicroROS() implementation (`#48 `_) (`#49 `_) +* Update STM32CubeMX micro-ROS library paths (backport `#42 `_) (`#43 `_) +* Fix embeddedRTPS build (`#38 `_) +* Fix embeddedRTPS repo (backport `#33 `_) (`#34 `_) +* Fix meta file selection and change rtps branch (backport `#31 `_) (`#32 `_) +* Add embeddedRTPS as experimental middleware (backport `#29 `_) (`#30 `_) +* Update library_generation.sh (`#26 `_) (`#27 `_) +* apt to apt-get (`#20 `_) (`#22 `_) +* multichange tool (`#10 `_) (`#12 `_) +* Initial Rolling port +* Suggested absolute path in step 4 (`#9 `_) +* multichange tool (`#6 `_) +* Add automated IDE support (`#4 `_) +* Add serial interrupt transport (`#2 `_) +* Update +* Update +* Update dockerfile +* Update +* Initial commit +* Initial commit diff --git a/README.md b/README.md index 127e789..6b49a63 100644 --- a/README.md +++ b/README.md @@ -9,9 +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)](#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) @@ -31,43 +34,44 @@ This package support the usage of micro-ROS on top of two different middlewares: 4. Configure the transport interface on the STM32CubeMX project, check the [Transport configuration](#Transport-configuration) section for instructions on the custom transports provided. 5. Modify the generated `Makefile` to include the following code **before the `build the application` section**: - + -```makefile -####################################### -# micro-ROS addons -####################################### -LDFLAGS += micro_ros_stm32cubemx_utils/microros_static_library/libmicroros/libmicroros.a -C_INCLUDES += -Imicro_ros_stm32cubemx_utils/microros_static_library/libmicroros/microros_include + ```makefile + ####################################### + # micro-ROS addons + ####################################### + LDFLAGS += micro_ros_stm32cubemx_utils/microros_static_library/libmicroros/libmicroros.a + C_INCLUDES += -Imicro_ros_stm32cubemx_utils/microros_static_library/libmicroros/microros_include -# Add micro-ROS utils -C_SOURCES += micro_ros_stm32cubemx_utils/extra_sources/custom_memory_manager.c -C_SOURCES += micro_ros_stm32cubemx_utils/extra_sources/microros_allocators.c -C_SOURCES += micro_ros_stm32cubemx_utils/extra_sources/microros_time.c + # Add micro-ROS utils + C_SOURCES += micro_ros_stm32cubemx_utils/extra_sources/custom_memory_manager.c + C_SOURCES += micro_ros_stm32cubemx_utils/extra_sources/microros_allocators.c + C_SOURCES += micro_ros_stm32cubemx_utils/extra_sources/microros_time.c -# Set here the custom transport implementation -C_SOURCES += micro_ros_stm32cubemx_utils/extra_sources/microros_transports/dma_transport.c + # Set here the custom transport implementation + C_SOURCES += micro_ros_stm32cubemx_utils/extra_sources/microros_transports/dma_transport.c -print_cflags: - @echo $(CFLAGS) -``` + print_cflags: + @echo $(CFLAGS) + ``` 6. Execute the static library generation tool. Compiler flags will retrieved automatically from your `Makefile` and user will be prompted to check if they are correct. -```bash -docker pull microros/micro_ros_static_library_builder:rolling -docker run -it --rm -v $(pwd):/project --env MICROROS_LIBRARY_FOLDER=micro_ros_stm32cubemx_utils/microros_static_library microros/micro_ros_static_library_builder:rolling -``` + ```bash + docker pull microros/micro_ros_static_library_builder:humble + docker run -it --rm -v $(pwd):/project --env MICROROS_LIBRARY_FOLDER=micro_ros_stm32cubemx_utils/microros_static_library microros/micro_ros_static_library_builder:humble + ``` 1. Modify your `main.c` to use micro-ROS. An example application can be found in `sample_main.c`. 2. Continue your usual workflow building your project and flashing the binary: -```bash -make -j$(nproc) -``` + ```bash + make -j$(nproc) + ``` + ## Using this package with STM32CubeIDE micro-ROS can be used with SMT32CubeIDE following these steps: @@ -75,9 +79,9 @@ micro-ROS can be used with SMT32CubeIDE following these steps: 1. Clone this repository in your STM32CubeIDE project folder 2. Go to `Project -> Settings -> C/C++ Build -> Settings -> Build Steps Tab` and in `Pre-build steps` add: -```bash -docker pull microros/micro_ros_static_library_builder:rolling && docker run --rm -v ${workspace_loc:/${ProjName}}:/project --env MICROROS_LIBRARY_FOLDER=micro_ros_stm32cubemx_utils/microros_static_library_ide microros/micro_ros_static_library_builder:rolling -``` + ```bash + docker pull microros/micro_ros_static_library_builder:humble && docker run --rm -v ${workspace_loc:/${ProjName}}:/project --env MICROROS_LIBRARY_FOLDER=micro_ros_stm32cubemx_utils/microros_static_library_ide microros/micro_ros_static_library_builder:humble + ``` 3. Add micro-ROS include directory. In `Project -> Settings -> C/C++ Build -> Settings -> Tool Settings Tab -> MCU GCC Compiler -> Include paths` add `micro_ros_stm32cubemx_utils/microros_static_library_ide/libmicroros/include` 4. Add the micro-ROS precompiled library. In `Project -> Settings -> C/C++ Build -> Settings -> MCU GCC Linker -> Libraries` @@ -91,6 +95,21 @@ docker pull microros/micro_ros_static_library_builder:rolling && docker run --rm 6. Make sure that if you are using FreeRTOS, the micro-ROS task **has more than 10 kB of stack**: [Detail](.images/Set_freertos_stack.jpg) 7. Configure the transport interface on the STM32CubeMX project, check the [Transport configuration](#Transport-configuration) section for instructions on the custom transports provided. 8. Build and run your project + +### Windows 11 (Community Contributed) + +micro-ROS can be used with SMT32CubeIDE in Windows 11 OS, following these steps: + +1. Install Docker Desktop and open it +2. Clone this repository in your STM32CubeIDE project folder +3. Open a terminal in the project folder and run: + ```bash + docker pull microros/micro_ros_static_library_builder:humble + docker run --rm -v :/project --env MICROROS_LIBRARY_FOLDER=micro_ros_stm32cubemx_utils/microros_static_library_ide microros/micro_ros_static_library_builder:humble + ``` +Follow steps 4 to 8. +Noticed that thist steps where tested with ROS 2 Humble, but should work on any distribution. micro-ROS Agent could be build and run in Ubuntu using WSL. + ## Transport configuration Available transport for this platform are: @@ -109,12 +128,45 @@ Steps to configure: - Enable U(S)ART in your STM32CubeMX - For the selected USART, enable `global interrupt` under `NVIC Settings`: [Detail](.images/Set_UART_IT.jpg) +### USB CDC + +Steps to configure: + - Enable the USB in your STM32CubeMX `Connectivity` tab. + - Select the `Communication Device Class (Virtual Port Com)` mode on the `Middleware -> USB_DEVICE` configuration. + + **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/). ## Adding custom packages -Note that folders added to `microros_component/extra_packages` and entries added to `microros_component/extra_packages/extra_packages.repos` will be taken into account by this build system. +Note that folders added to `microros_static_library/library_generation/extra_packages/` and entries added to `/microros_static_library/library_generation/extra_packages/extra_packages.repos` will be taken into account by this build system. ## Purpose of the Project diff --git a/embeddedrtps.md b/embeddedrtps.md index 279ad96..bfef068 100644 --- a/embeddedrtps.md +++ b/embeddedrtps.md @@ -42,7 +42,7 @@ This instructions are an approach to a [STMCubeIDE v1.7.0](https://www.st.com/en 10. Go to `Project -> Settings -> C/C++ Build -> Settings -> Build Steps Tab` and in `Pre-build steps` add: ```bash -docker pull microros/micro_ros_static_library_builder:galactic && docker run --rm -v ${workspace_loc:/${ProjName}}:/project --env MICROROS_USE_EMBEDDEDRTPS=ON --env MICROROS_LIBRARY_FOLDER=micro_ros_stm32cubemx_utils/microros_static_library_ide microros/micro_ros_static_library_builder:galactic +docker pull microros/micro_ros_static_library_builder:humble && docker run --rm -v ${workspace_loc:/${ProjName}}:/project --env MICROROS_USE_EMBEDDEDRTPS=ON --env MICROROS_LIBRARY_FOLDER=micro_ros_stm32cubemx_utils/microros_static_library_ide microros/micro_ros_static_library_builder:humble ``` 12. Add the following source code files to your project, dragging them to source folder: diff --git a/extra_sources/microros_transports/udp_transport.c b/extra_sources/microros_transports/udp_transport.c new file mode 100644 index 0000000..4427a51 --- /dev/null +++ b/extra_sources/microros_transports/udp_transport.c @@ -0,0 +1,79 @@ +#include + +#include + +#include "main.h" +#include "cmsis_os.h" + +#include +#include +#include +#include + +// --- LWIP --- +#include "lwip/opt.h" +#include "lwip/sys.h" +#include "lwip/api.h" +#include + +#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 \ No newline at end of file diff --git a/extra_sources/microros_transports/usb_cdc_transport.c b/extra_sources/microros_transports/usb_cdc_transport.c new file mode 100644 index 0000000..24e61b9 --- /dev/null +++ b/extra_sources/microros_transports/usb_cdc_transport.c @@ -0,0 +1,163 @@ +#include + +#include "main.h" +#include "cmsis_os.h" +#include "usbd_cdc_if.h" +#include "usbd_cdc.h" + +#include +#include +#include +#include + +#ifdef RMW_UXRCE_TRANSPORT_CUSTOM + +// --- USB CDC Handles --- +extern USBD_CDC_ItfTypeDef USBD_Interface_fops_FS; +extern USBD_HandleTypeDef hUsbDeviceFS; + +// --- Reimplemented USB CDC callbacks --- +static int8_t CDC_TransmitCplt_FS(uint8_t *Buf, uint32_t *Len, uint8_t epnum); +static int8_t CDC_Control_FS(uint8_t cmd, uint8_t* pbuf, uint16_t length); +static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len); + +// Line coding: Rate: 115200bps; CharFormat: 1 Stop bit; Parity: None; Data: 8 bits +static uint8_t line_coding[7] = {0x00, 0xC2, 0x01, 0x00, 0x00, 0x00, 0x08}; + +// --- micro-ROS Transports --- +#define USB_BUFFER_SIZE 2048 +#define WRITE_TIMEOUT_MS 100U + +volatile uint8_t storage_buffer[USB_BUFFER_SIZE] = {0}; +volatile size_t it_head = 0; +volatile size_t it_tail = 0; +volatile bool g_write_complete = false; +bool initialized = false; + +// Transmission completed callback +static int8_t CDC_TransmitCplt_FS(uint8_t *Buf, uint32_t *Len, uint8_t epnum) +{ + (void) Buf; + (void) Len; + (void) epnum; + + g_write_complete = true; + return USBD_OK; +} + +// USB CDC requests callback +static int8_t CDC_Control_FS(uint8_t cmd, uint8_t* pbuf, uint16_t length) +{ + switch(cmd) + { + case CDC_SET_LINE_CODING: + memcpy(line_coding, pbuf, sizeof(line_coding)); + break; + + case CDC_GET_LINE_CODING: + memcpy(pbuf, line_coding, sizeof(line_coding)); + break; + + case CDC_SEND_ENCAPSULATED_COMMAND: + case CDC_GET_ENCAPSULATED_RESPONSE: + case CDC_SET_COMM_FEATURE: + case CDC_GET_COMM_FEATURE: + case CDC_CLEAR_COMM_FEATURE: + case CDC_SET_CONTROL_LINE_STATE: + case CDC_SEND_BREAK: + default: + break; + } + + return USBD_OK; +} + +// Data received callback +static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len) +{ + USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]); + + // Circular buffer + if ((it_tail + *Len) > USB_BUFFER_SIZE) + { + size_t first_section = USB_BUFFER_SIZE - it_tail; + size_t second_section = *Len - first_section; + + memcpy((void*) &storage_buffer[it_tail] , Buf, first_section); + memcpy((void*) &storage_buffer[0] , Buf, second_section); + it_tail = second_section; + } + else + { + memcpy((void*) &storage_buffer[it_tail] , Buf, *Len); + it_tail += *Len; + } + + USBD_CDC_ReceivePacket(&hUsbDeviceFS); + + return (USBD_OK); +} + +bool cubemx_transport_open(struct uxrCustomTransport * transport){ + + if (!initialized) + { + // USB is initialized on generated main code: Replace default callbacks here + USBD_Interface_fops_FS.Control = CDC_Control_FS; + USBD_Interface_fops_FS.Receive = CDC_Receive_FS; + USBD_Interface_fops_FS.TransmitCplt = CDC_TransmitCplt_FS; + initialized = true; + } + + return true; +} + +bool cubemx_transport_close(struct uxrCustomTransport * transport){ + return true; +} + +size_t cubemx_transport_write(struct uxrCustomTransport* transport, uint8_t * buf, size_t len, uint8_t * err){ + uint8_t ret = CDC_Transmit_FS(buf, len); + + if (USBD_OK != ret) + { + return 0; + } + + int64_t start = uxr_millis(); + while(!g_write_complete && (uxr_millis() - start) < WRITE_TIMEOUT_MS) + { + vTaskDelay( 1 / portTICK_PERIOD_MS); + } + + size_t writed = g_write_complete ? len : 0; + g_write_complete = false; + + return writed; +} + +size_t cubemx_transport_read(struct uxrCustomTransport* transport, uint8_t* buf, size_t len, int timeout, uint8_t* err){ + + int64_t start = uxr_millis(); + size_t readed = 0; + + do + { + if (it_head != it_tail) + { + while ((it_head != it_tail) && (readed < len)){ + buf[readed] = storage_buffer[it_head]; + it_head = (it_head + 1) % USB_BUFFER_SIZE; + readed++; + } + + break; + } + + vTaskDelay( 1 / portTICK_PERIOD_MS ); + } while ((uxr_millis() - start) < timeout); + + return readed; +} + +#endif \ No newline at end of file diff --git a/microros_static_library/library_generation/library_generation.sh b/microros_static_library/library_generation/library_generation.sh index 620d313..13f4ad4 100755 --- a/microros_static_library/library_generation/library_generation.sh +++ b/microros_static_library/library_generation/library_generation.sh @@ -19,13 +19,20 @@ ros2 run micro_ros_setup create_firmware_ws.sh generate_lib pushd firmware/mcu_ws > /dev/null # Workaround: Copy just tf2_msgs - git clone -b ros2 https://github.com/ros2/geometry2 + git clone -b humble https://github.com/ros2/geometry2 cp -R geometry2/tf2_msgs ros2/tf2_msgs rm -rf geometry2 # Import user defined packages mkdir extra_packages pushd extra_packages > /dev/null + USER_CUSTOM_PACKAGES_DIR=$BASE_PATH/../../microros_component/extra_packages + if [ -d "$USER_CUSTOM_PACKAGES_DIR" ]; then + cp -R $USER_CUSTOM_PACKAGES_DIR/* . + fi + if [ -f $USER_CUSTOM_PACKAGES_DIR/extra_packages.repos ]; then + vcs import --input $USER_CUSTOM_PACKAGES_DIR/extra_packages.repos + fi cp -R $BASE_PATH/library_generation/extra_packages/* . vcs import --input extra_packages.repos popd > /dev/null diff --git a/microros_static_library_ide/library_generation/colcon.meta b/microros_static_library_ide/library_generation/colcon.meta index dd24e96..f42d968 100644 --- a/microros_static_library_ide/library_generation/colcon.meta +++ b/microros_static_library_ide/library_generation/colcon.meta @@ -43,11 +43,11 @@ "-DRMW_UXRCE_MAX_NODES=1", "-DRMW_UXRCE_MAX_PUBLISHERS=10", "-DRMW_UXRCE_MAX_SUBSCRIPTIONS=5", - "-DRMW_UXRCE_MAX_SERVICES=1", + "-DRMW_UXRCE_MAX_SERVICES=2", "-DRMW_UXRCE_MAX_CLIENTS=1", "-DRMW_UXRCE_MAX_HISTORY=4", "-DRMW_UXRCE_TRANSPORT=custom" ] } } -} \ No newline at end of file +} diff --git a/microros_static_library_ide/library_generation/extra_packages/imu_interfaces/CMakeLists.txt b/microros_static_library_ide/library_generation/extra_packages/imu_interfaces/CMakeLists.txt new file mode 100644 index 0000000..af64f9c --- /dev/null +++ b/microros_static_library_ide/library_generation/extra_packages/imu_interfaces/CMakeLists.txt @@ -0,0 +1,34 @@ +cmake_minimum_required(VERSION 3.8) +project(imu_interfaces) + +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) +endif() + +# find dependencies +find_package(ament_cmake REQUIRED) +# uncomment the following section in order to fill in +# further dependencies manually. +# find_package( REQUIRED) + +find_package(rosidl_default_generators REQUIRED) +find_package(sensor_msgs REQUIRED) + +rosidl_generate_interfaces(${PROJECT_NAME} + "srv/ImuCalibration.srv" + DEPENDENCIES sensor_msgs + ) + +if(BUILD_TESTING) + find_package(ament_lint_auto REQUIRED) + # the following line skips the linter which checks for copyrights + # comment the line when a copyright and license is added to all source files + set(ament_cmake_copyright_FOUND TRUE) + # the following line skips cpplint (only works in a git repo) + # comment the line when this package is in a git repo and when + # a copyright and license is added to all source files + set(ament_cmake_cpplint_FOUND TRUE) + ament_lint_auto_find_test_dependencies() +endif() + +ament_package() diff --git a/microros_static_library_ide/library_generation/extra_packages/imu_interfaces/package.xml b/microros_static_library_ide/library_generation/extra_packages/imu_interfaces/package.xml new file mode 100644 index 0000000..744eba7 --- /dev/null +++ b/microros_static_library_ide/library_generation/extra_packages/imu_interfaces/package.xml @@ -0,0 +1,25 @@ + + + + imu_interfaces + 0.0.0 + TODO: Package description + teety + TODO: License declaration + + ament_cmake + + rosidl_default_generators + + rosidl_default_runtime + sensor_msgs + + rosidl_interface_packages + + ament_lint_auto + ament_lint_common + + + ament_cmake + + diff --git a/microros_static_library_ide/library_generation/extra_packages/imu_interfaces/srv/ImuCalibration.srv b/microros_static_library_ide/library_generation/extra_packages/imu_interfaces/srv/ImuCalibration.srv new file mode 100644 index 0000000..928be14 --- /dev/null +++ b/microros_static_library_ide/library_generation/extra_packages/imu_interfaces/srv/ImuCalibration.srv @@ -0,0 +1,3 @@ +sensor_msgs/Imu imu_calib +--- +bool success \ No newline at end of file diff --git a/microros_static_library_ide/library_generation/library_generation.sh b/microros_static_library_ide/library_generation/library_generation.sh index 5d4efc8..f7ade0b 100755 --- a/microros_static_library_ide/library_generation/library_generation.sh +++ b/microros_static_library_ide/library_generation/library_generation.sh @@ -45,6 +45,13 @@ pushd firmware/mcu_ws > /dev/null # Import user defined packages mkdir extra_packages pushd extra_packages > /dev/null + USER_CUSTOM_PACKAGES_DIR=$BASE_PATH/../../microros_component/extra_packages + if [ -d "$USER_CUSTOM_PACKAGES_DIR" ]; then + cp -R $USER_CUSTOM_PACKAGES_DIR/* . + fi + if [ -f $USER_CUSTOM_PACKAGES_DIR/extra_packages.repos ]; then + vcs import --input $USER_CUSTOM_PACKAGES_DIR/extra_packages.repos + fi cp -R $BASE_PATH/library_generation/extra_packages/* . vcs import --input extra_packages.repos popd > /dev/null diff --git a/package.xml b/package.xml new file mode 100644 index 0000000..ed61a3f --- /dev/null +++ b/package.xml @@ -0,0 +1,9 @@ + + + + micro_ros_stmcube + 3.0.2 + micro-ROS tools for STM Cube IDE/MX + Pablo Garrido + Apache License 2.0 + diff --git a/sample_main_udp.c b/sample_main_udp.c new file mode 100644 index 0000000..2131d82 --- /dev/null +++ b/sample_main_udp.c @@ -0,0 +1,347 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file : main.c + * @brief : Main program body + ****************************************************************************** + * @attention + * + * Copyright (c) 2023 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/* USER CODE END Header */ +/* Includes ------------------------------------------------------------------*/ +#include "main.h" +#include "cmsis_os.h" +#include "lwip.h" + +/* Private includes ----------------------------------------------------------*/ +/* USER CODE BEGIN Includes */ +#include +#include +#include +#include +#include +#include +#include + +#include +/* USER CODE END Includes */ + +/* Private typedef -----------------------------------------------------------*/ +/* USER CODE BEGIN PTD */ + +/* USER CODE END PTD */ + +/* Private define ------------------------------------------------------------*/ +/* USER CODE BEGIN PD */ + +/* USER CODE END PD */ + +/* Private macro -------------------------------------------------------------*/ +/* USER CODE BEGIN PM */ + +/* USER CODE END PM */ + +/* Private variables ---------------------------------------------------------*/ +/* Definitions for defaultTask */ +osThreadId_t defaultTaskHandle; +const osThreadAttr_t defaultTask_attributes = { + .name = "defaultTask", + .priority = (osPriority_t) osPriorityNormal, + .stack_size = 3000 * 4, +}; +/* USER CODE BEGIN PV */ + +/* USER CODE END PV */ + +/* Private function prototypes -----------------------------------------------*/ +void SystemClock_Config(void); +static void MX_GPIO_Init(void); +void StartDefaultTask(void *argument); + +/* USER CODE BEGIN PFP */ + +/* USER CODE END PFP */ + +/* Private user code ---------------------------------------------------------*/ +/* USER CODE BEGIN 0 */ + +/* USER CODE END 0 */ + +/** + * @brief The application entry point. + * @retval int + */ +int main(void) +{ + /* USER CODE BEGIN 1 */ + + /* USER CODE END 1 */ + + /* MCU Configuration--------------------------------------------------------*/ + + /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ + HAL_Init(); + + /* USER CODE BEGIN Init */ + + /* USER CODE END Init */ + + /* Configure the system clock */ + SystemClock_Config(); + + /* USER CODE BEGIN SysInit */ + + /* USER CODE END SysInit */ + + /* Initialize all configured peripherals */ + MX_GPIO_Init(); + /* USER CODE BEGIN 2 */ + + /* USER CODE END 2 */ + + /* Init scheduler */ + osKernelInitialize(); + + /* USER CODE BEGIN RTOS_MUTEX */ + /* add mutexes, ... */ + /* USER CODE END RTOS_MUTEX */ + + /* USER CODE BEGIN RTOS_SEMAPHORES */ + /* add semaphores, ... */ + /* USER CODE END RTOS_SEMAPHORES */ + + /* USER CODE BEGIN RTOS_TIMERS */ + /* start timers, add new ones, ... */ + /* USER CODE END RTOS_TIMERS */ + + /* USER CODE BEGIN RTOS_QUEUES */ + /* add queues, ... */ + /* USER CODE END RTOS_QUEUES */ + + /* Create the thread(s) */ + /* creation of defaultTask */ + defaultTaskHandle = osThreadNew(StartDefaultTask, NULL, &defaultTask_attributes); + + /* USER CODE BEGIN RTOS_THREADS */ + /* add threads, ... */ + /* USER CODE END RTOS_THREADS */ + + /* USER CODE BEGIN RTOS_EVENTS */ + /* add events, ... */ + /* USER CODE END RTOS_EVENTS */ + + /* Start scheduler */ + osKernelStart(); + /* We should never get here as control is now taken by the scheduler */ + /* Infinite loop */ + /* USER CODE BEGIN WHILE */ + while (1) + { + /* USER CODE END WHILE */ + + /* USER CODE BEGIN 3 */ + } + /* USER CODE END 3 */ +} + +/** + * @brief System Clock Configuration + * @retval None + */ +void SystemClock_Config(void) +{ + RCC_OscInitTypeDef RCC_OscInitStruct = {0}; + RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; + + /** Configure the main internal regulator output voltage + */ + __HAL_RCC_PWR_CLK_ENABLE(); + __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); + + /** Initializes the RCC Oscillators according to the specified parameters + * in the RCC_OscInitTypeDef structure. + */ + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; + RCC_OscInitStruct.HSIState = RCC_HSI_ON; + RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; + RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI; + RCC_OscInitStruct.PLL.PLLM = 8; + RCC_OscInitStruct.PLL.PLLN = 168; + RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; + RCC_OscInitStruct.PLL.PLLQ = 4; + if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) + { + Error_Handler(); + } + + /** Initializes the CPU, AHB and APB buses clocks + */ + RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK + |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; + RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; + RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; + RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; + RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; + + if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK) + { + Error_Handler(); + } +} + +/** + * @brief GPIO Initialization Function + * @param None + * @retval None + */ +static void MX_GPIO_Init(void) +{ +/* USER CODE BEGIN MX_GPIO_Init_1 */ +/* USER CODE END MX_GPIO_Init_1 */ + + /* GPIO Ports Clock Enable */ + __HAL_RCC_GPIOC_CLK_ENABLE(); + __HAL_RCC_GPIOA_CLK_ENABLE(); + __HAL_RCC_GPIOB_CLK_ENABLE(); + +/* USER CODE BEGIN MX_GPIO_Init_2 */ +/* USER CODE END MX_GPIO_Init_2 */ +} + +/* USER CODE BEGIN 4 */ + +/* USER CODE END 4 */ + +/* USER CODE BEGIN Header_StartDefaultTask */ +/** + * @brief Function implementing the defaultTask thread. + * @param argument: Not used + * @retval None + */ +/* USER CODE END Header_StartDefaultTask */ +void StartDefaultTask(void *argument) +{ + /* init code for LWIP */ + MX_LWIP_Init(); + /* USER CODE BEGIN 5 */ + + // micro-ROS configuration + + rmw_uros_set_custom_transport( + false, //Framing disable here. Udp should Use Packet-oriented mode. + "192.168.1.121", //your Agent's ip address + cubemx_transport_open, + cubemx_transport_close, + cubemx_transport_write, + cubemx_transport_read); + + rcl_allocator_t freeRTOS_allocator = rcutils_get_zero_initialized_allocator(); + freeRTOS_allocator.allocate = microros_allocate; + freeRTOS_allocator.deallocate = microros_deallocate; + freeRTOS_allocator.reallocate = microros_reallocate; + freeRTOS_allocator.zero_allocate = microros_zero_allocate; + + if (!rcutils_set_default_allocator(&freeRTOS_allocator)) { + printf("Error on default allocators (line %d)\n", __LINE__); + } + + // micro-ROS app + + rcl_publisher_t publisher; + std_msgs__msg__Int32 msg; + rclc_support_t support; + rcl_allocator_t allocator; + rcl_node_t node; + + allocator = rcl_get_default_allocator(); + + //create init_options + rclc_support_init(&support, 0, NULL, &allocator); + + // create node + rclc_node_init_default(&node, "cubemx_node", "", &support); + + // create publisher + rclc_publisher_init_default( + &publisher, + &node, + ROSIDL_GET_MSG_TYPE_SUPPORT(std_msgs, msg, Int32), + "cubemx_publisher"); + + msg.data = 0; + + for(;;) + { + rcl_ret_t ret = rcl_publish(&publisher, &msg, NULL); + if (ret != RCL_RET_OK) + { + printf("Error publishing (line %d)\n", __LINE__); + } + + msg.data++; + osDelay(10); + } + /* USER CODE END 5 */ +} + +/** + * @brief Period elapsed callback in non blocking mode + * @note This function is called when TIM1 interrupt took place, inside + * HAL_TIM_IRQHandler(). It makes a direct call to HAL_IncTick() to increment + * a global variable "uwTick" used as application time base. + * @param htim : TIM handle + * @retval None + */ +void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) +{ + /* USER CODE BEGIN Callback 0 */ + + /* USER CODE END Callback 0 */ + if (htim->Instance == TIM1) { + HAL_IncTick(); + } + /* USER CODE BEGIN Callback 1 */ + + /* USER CODE END Callback 1 */ +} + +/** + * @brief This function is executed in case of error occurrence. + * @retval None + */ +void Error_Handler(void) +{ + /* USER CODE BEGIN Error_Handler_Debug */ + /* User can add his own implementation to report the HAL error return state */ + __disable_irq(); + while (1) + { + } + /* USER CODE END Error_Handler_Debug */ +} + +#ifdef USE_FULL_ASSERT +/** + * @brief Reports the name of the source file and the source line number + * where the assert_param error has occurred. + * @param file: pointer to the source file name + * @param line: assert_param error line source number + * @retval None + */ +void assert_failed(uint8_t *file, uint32_t line) +{ + /* USER CODE BEGIN 6 */ + /* User can add his own implementation to report the file name and line number, + ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ + /* USER CODE END 6 */ +} +#endif /* USE_FULL_ASSERT */ \ No newline at end of file