Intrepid Ramp Robot Part 2: inter-robot communication
Dec 2023
GOAL: build a robot can communicate with another robot to ascend a ramp at the same speed, making autonomous speed adjustments through HTTP requests to each other
SKILLS: CAD (OnShape), python multithreading, Flask, HTTP request handling, autonomous adjustment, communication between two robots, wiring, assembly, laser cutting, prototyping, testing, PWM motor control, use of single board computer (Raspberry Pi), design, collaboration
For part 2, we modified our robot from part 1 so that it can collaborate with another robot to roll a tube up a pair of ramps as quickly as possible without the tube falling off either ramp. Ideally, our robot would be able to collaborate with any of the other robots in the class, given their IP address.
Design Constraints
our robot should receive only one signal from a human: a command to begin the operation. After starting, the robot should operate autonomously.
our robot should respond to two URLs: /start/<delay> and /target/<speed>
our robot should only make requests where delay is an integer in the range 1-10 seconds, and speed is an integer in the range 1-1000 mm/second.
our robot should never send HTTP requests at a rate of more than 10 Hz, i.e. wait at least 100 ms between requests.
This project expands on the capabilities of Intrepid Ramp Robot Part 1, which was steered by a user via an html page instead of using buttons and a guide to stay on the ramp:
Speed Regulation Strategy
Our robot regulates speed using two buttons. The snow plow shape on the front is sized to be able to support the 3 inch cardboard tube. When the tube begins to tilt, the robot stays straight and the plough rotates.
If our robot is on the right ramp and is going too slow, then the tube will tilt and cause the plow to press the right button. This will either increase our speed or ask the other robot to slow down. When we are going too fast, then the left button is pressed and this will cause us to slow down or ask the other robot to speed up
right button pressed --> speed up or ask other robot to slow down
left button pressed --> slow up or ask other robot to speed up
Testing Videos
multi.py Code

Code Walk-through
First, the main function runs. Inside the main function, we first send a delay request to the other robot.
In the send_delay_request function, the handle_start_request function is called which will decide whether to use our robot’s delay request, or our partner’s delay request.
If our program was run first, this request will get lost in the internet ocean, then this function will do nothing
Back in main, the count thread is started. This thread runs a loop that outputs the speed every five seconds
Next in main, flask is run. Now, our robot is open to receiving HTTP requests.
If our program was run first and our request had nowhere to go, now we can receive their delay and use that one. If our program was run second, then we will have sent out a request and begun waiting for their request as well.
There is a route called start_request that can recognize the format of the start delay request and parse out the integer delay value
The route calls the handle_start_request function which decides whether to use their delay request and whether to reply “ok” or “no.”
If we received their delay request, but have not yet received a response to our request, then we use their delay and return “ok” back into the start_request function if the delay is reasonable, and “no” if not.
Back in the start_request function, if the returned response was “ok,” then the delay is executed and a new thread called button_thread is started.
button_thread targets the button_loop, which controls the main driving and speed regulation operations of the robot.
Concurrently, with the starting of the thread, we return our response to the other robot.
If we received a response to the delay that we sent and haven’t received their request yet, then we know that ours got their first. If they replied “ok”, then we execute the delay and start the button_thread.
Inside button_loop, first, the motor speeds are set to the agreed upon start speed.
We have two functions that control changing our motor speeds: one to calculate the correct PWM percentage based on the linear speed needs, and one to change the duty cycles of the motors
Next, there is a loop that searches for input from the buttons.
The code is set up for if the robot is on the right ramp. So, when the right button is pressure, that means we are behind the other robot.
If we are not at our max speed, we increase our own speed.
If we are at our max speed, then we call the send_target_request function to tell the other robot to slow down.
The function for sending a speed request works similarly to the function for sending a start request
If the left button is pressed, then we are ahead of our partner. If we are not at our minimum speed, then we decrease our own speed. If we are at our minimum speed, then we request the other robot to speed up.
The loop then sleeps briefly to add a buffer to allow the robot to get up to speed and mediate overcorrecting
The last main function that hasn’t been mentioned is the target_request function that executes if we receive a speed request from the other robot. It parses the request for the integer speed, and If the speed is below our max speed, sets our motors to that speed and responds ok to the other robot
More Images
Things to adjust in the future:
Make the code work for if the robot is on the right or left side
Could add a boolean that is true for when the robot is on the right and false for when its not
Make the speed increment and decrement code blocks into functions to be more modular
If on the right, call functions as currently implemented
If on the left, call the decrement function instead of the increment function, etc.
Do more testing with other robots and carefully examine the print statement outputs
use a method capable of proportional control instead of buttons, like a dial or slider
Adjust our logic for how fast to tell the other robot to go. Currently just sends a value that is dependent on our speed, but would be ideal if we could know their speed
Get better values for PWM
Currently, our PWM values are extrapolated and on a linear scale. We would want more accurate values so that whether the other robot tells us to go a certain speed, we will actually go that speed
Split up our giant file into smaller files
Could make a motor control thread that loops and calls the set set_motors_to_target function so that anytime the global my_speed variable is change, the motor speed are automatically adjusted.