This project includes three scripts designed to subscribe, generate, exchange, and plot the left and right target RPMs of a differential drive robot. The project consists of two C++ scripts (Script A and Script B) and one Python script (Script C). These scripts interact with each other using shared memory for communication between the C++ scripts and HTTP requests between the C++ and Python scripts. The objective is to calculate and visualize the robot's wheel RPMs in real time, without relying on pub-sub architectures like ROS, DDS, or MQTT.
You can watch the demonstration on YouTube by clicking the video below:
assignment/
├── src/
│ ├── script_a/
│ │ ├── script_a.cpp # C++ Script A - Receives cmd_vel and calculates wheel velocities
│ ├── script_b/
│ │ ├── script_b.cpp # C++ Script B - Fetches shared data and sends it via HTTP request
│ ├── script_c/
│ │ ├── script_c.py # Python Script C - Fetches data via HTTP request and plots wheel RPMs
├── include/
│ ├── shared_data.hpp # Shared memory structure for interprocess communication
│ ├── httplib.hpp # Header file for the HTTP client library to send and receive HTTP requests in C++ scripts
├── CMakeLists.txt # CMake build configuration for C++ scripts
└── package.xml # ROS package metadata (if needed for your setup)
- Functionality: Subscribes to the
cmd_vel
topic and calculates the target left and right wheel RPMs based on received linear and angular velocities. Shares the data with other C++ scripts via shared memory. - Key Calculations: Converts the target linear and angular velocities into wheel RPMs based on the given wheel-to-wheel distance and wheel diameter.
- Data Shared: Target left and right RPMs, input target linear velocity, angular velocity, and a timestamp.
- Functionality: Fetches the shared data from Script A, prints the data, and sends it to Script C via HTTP requests.
- Communication: HTTP GET requests are sent from Script B to Script C to transmit the data.
- Features: Runs in a loop at 10 Hz, fetching data from shared memory, printing it to the console, and making HTTP requests to Script C.
- Functionality: Hosts an HTTP server that listens for requests from Script B. Fetches the wheel RPM data from Script B and generates real-time plots of the left and right wheel RPM values.
- Features: Uses
requests
to make HTTP requests to Script B andmatplotlib
for plotting the RPM data. - API Request: Fetches data from Script B through a
/get_data_from_B
endpoint and processes it for visualization.
- Shared Memory: Script A shares the calculated wheel RPMs and other relevant data with Script B using shared memory.
- HTTP Requests: Script B sends the data to Script C using HTTP GET requests. Script C fetches the data via its
/get_data_from_B
API endpoint.
- Request Type: HTTP GET
- Request URL:
/get_data_from_B
- Request Format: JSON
- Left wheel RPM
- Right wheel RPM
- Input linear velocity (m/s)
- Input angular velocity (rad/s)
- Timestamps generated by Script A and Script B
To compile the C++ scripts, use the following command from the root directory of the project:
colcon build --packages-select your_package_name
Once the build is complete, source the ROS workspace:
source install/setup.bash
-
Run Script A: This script will subscribe to
cmd_vel
messages, perform the necessary calculations, and write data to shared memory.ros2 run your_package_name script_a
-
Run Script B: This script will fetch data from Script A and send it to Script C via HTTP requests.
ros2 run your_package_name script_b
-
Run Script C: The Python script fetches the data from Script B and generates plots.
For Script C (Python):
-
First, navigate to the
script_c
directory:cd assignment/src/script_c/
-
Then, run the Python script:
python3 script_c.py
Note: If the script doesn't run, make sure it's executable by using the following command:
chmod +x script_c.py
-
Once the script is executed, it will fetch the wheel RPM data and plot it in real time.
- Graceful Restart: The system is designed to handle script restarts without losing data or affecting performance. If any script (A, B, or C) is killed, it can be restarted, and the data exchange will continue without disruption.
- Error Handling: The system ensures that if an error occurs during data fetching or communication, the process continues running, and errors are logged appropriately.