>[!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
```