>[!quote] In a Nutshell >Framework for asynchronous communication, e.g. for #Robotics and embedded systems. In #Networks , it an be considered part of the **Application Layer** of the [[OSI Model - Open Systems Interconnection|OSI]] or [[Internet Protocol Suite (TCP-IP)|TCP-IP]] models. --- #### Features 1. **Serialization / Marshalling** - LCM converts structured data into compact binary forms for space-efficient transmission 2. **Language Independence** - LCM files can be used to generate source code in multiple languages 3. **Lightweight** - low latency and high throughput, enabling e.g. real-time control 4. **Event-Driven** - subscribers don't actively poll for messages, system notifies when new messages available 5. **Various [[Internet Protocol Suite (TCP-IP)|Transport Layer Mechanisms]]** - can use shared memory (local), [[UDP - User Datagram Protocol|UDP]] or (less common) [[TCP - Transmission Control Protocol|TCP]] --- #### LCM Files and Serialization / Marshalling An LCM file is used to describe the schema for a message in human readable form as a struct with fields and data types. This is then used as a blueprint to generate code in other languages ```lcm package example # defines namespace struct ExampleMessage { int32 id; float value; string name; int length; float numberlist[length]; } ``` LCM supports a number of primitive types: | type | Description | | ------- | -------------------------------- | | int8_t | 8-bit signed integer | | int16_t | 16-bit signed integer | | int32_t | 32-bit signed integer | | int64_t | 64-bit signed integer | | float | 32-bit IEEE floating point value | | double | 64-bit IEEE floating point value | | string | UTF-8 string | | boolean | true/false logical value | | byte | 8-bit value | The LCM workflow is the following 1. **Definition** - define `.lcm` file 2. **Code Generation** - use a code generation tool to generate source code for targeted programming language ```shell lcm-gen -p example.lcm ``` 3. **Serialization and Communication** - the generated code above provides functions for serializing, de-serializing and message handling 4. **Integration** - Use generated code in application to exchange messages --- #### LCM and its Event Loop in Python The lcm structs defined and generated above can be imported as python classes. IN the code, we use lcm instances to handle channels ```python lc = lcm.LCM() ``` We can use the following methods: | Method | Description | | --------------------------------- | ----------------------------------------------------------------------------------------- | | `subscribe(channel, callback)` | Subscribe to a channel and register a callback. | | `publish(channel, message)` | Publish a message to a specified channel. | | `get_info()` | Retrieve information about the LCM instance. | | `unsubscribe(channel)` | Unsubscribe from a channel. | | `get_subscription_count(channel)` | Get the number of subscribers for a channel. | | `set_blocking(timeout)` | Set the blocking timeout for `handle()`. | | `get_timestamp()` | Get the current LCM timestamp. | | `is_valid()` | Check if the LCM instance is in a valid state. | | `set_queue_capacity()` | Maximum number of received but unhandled messages to store (discards unhandled messages). | In order to trigger message processing (typically checking and reading out [[UDP - User Datagram Protocol|UDP]] [[Network Socket|socket]] buffer), we can use ... | Method | Description | | ------------------------- | --------------------------------------------------- | | `handle()` | Block (wait) and process incoming messages. | | `handle_timeout(timeout)` | Block with a timeout and process incoming messages. | --- #### How it Works Underneath LCM acts as the library/interface that serializes, deserializes, and publishes messages. The serialized message data (binary format) is handed off to the LCM framework, which determines the transport mechanism (e.g., UDP, multicast, shared memory). ###### Network - UDP or Multicast If LCM is configured to use UDP or multicast, it creates a socket on the operating system to send messages over the network stack. - **Physical Path**: - Messages are encapsulated in IP packets and [[UDP - User Datagram Protocol|UDP]] datagrams. - Packets travel through your NIC (Network Interface Card) if multicast is used over a physical network. - For local communication, the messages are looped back within the OS (via the loopback interface, typically `127.0.0.1`). ###### Local - Shared Memory If LCM is configured to use shared memory for local processes, the message is written directly into a shared memory segment. - **Physical Path**: - Shared memory resides in the RAM of the system. - LCM maps a portion of the RAM into the address space of both the sending and receiving processes. --- #### Installation with Windows and MSYS2 1. Install MYSYS2 as shown in https://www.msys2.org/ (`.msi` !), make sure to do update at the end (https://www.msys2.org/docs/updating/) ```bash pacman -Suy pacman -Su ``` 2. Install required tools ```bash # pacman -S base-devel git mingw-w64-x86_64-gcc mingw-w64-x86_64-cmake # pacman -S mingw-w64-x86_64-python3 mingw-w64-x86_64-python3-pip # pacman -S mingw-w64-x86_64-glib2 ``` 3. Double-Check if pip, python, cmake, make and ninja are installed ```bash make --version cmake --version ninja --version which python # global path, not usr which pip # global path, not usr ``` 4. Download lcm ```bash git clone https://github.com/lcm-proj/lcm.git ``` 5. Create new build directory, cd into it and run ```bash cd lcm mkdir build cd build cmake -S . -G Ninja .. -DCMAKE_BUILD_TYPE=Release -DLCM_ENABLE_GO=OFF -DLCM_ENABLE_LUA=OFF ``` 6. In the `build` dir run ```bash ninja ``` 7. Go back up to the `.lcm` dir and install it via pip ``` # look for pyptoject.toml file cd .. pip install . ``` 8. Try basic example in https://lcm-proj.github.io/lcm/content/tutorial-python.html ##### Problems you might run into ... 1. **GLIB** ```bash pacman -S mingw-w64-x86_64-glib2 ``` 2. **Java** Install on your machine via https://learn.microsoft.com/en-us/java/openjdk/download ```bash nano ~/.bashrc ``` In your file, add (`<your-actual-path>` in windows dir) ... ```bash export JAVA_HOME="/c/Program Files/Microsoft/<your-actual-path>" export PATH="$JAVA_HOME/bin:$PATH" ``` Save and close, reload profile ```bash source ~/.bashrc ```