Multithreading Attachment Motors While Driving
See original GitHub issue**ev3dev version: 4.14.96-ev3dev-2.3.2-ev3
**ev3dev-lang-python version:
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name Version Architecture Description
+++-==============-============-===================-==========================
ii micropython-ev 2.0.0~beta5 all Python language bindings for ev3d
ii python3-ev3dev 1.2.0 all Python language bindings for ev3d
ii python3-ev3dev 2.0.0~beta5 all Python language bindings for ev3d
WHAT’S GOING ON: My FLL team has a robot that has 2 large drive motors and 1 med and 1 large motor that run an elevator and shuttle (think 2 dimensional forklift). They tried threading the attachment motor operations using _thread library in Micropython, and the FLL robot didn’t behave as intended when attempting to drive straight using MoveSteering.on and instead veered left, consistently about 10-15 cm over a 60 cm move.
BACKGROUND: The kids have programmed “action” functions like Forward(distance=60, speed=40, ramp_up=True, ramp_down=True, brake_on=True) to move the robot forward 50 cm at 40% speed, ramping up and down, and braking at the end, for example.
The function essentially uses a 20ms loop by checking the time since the last motor command, then checks the heading error, computes a steering input using a PID controller and then uses a MoveSteering command to adjust the steering, and ramps up the speed until the set speed, stays at the set speed until a motor position reading is hit, and then ramps down until the final motor position is hit. Then it brakes and then releases the brake.
The function drives the robot nice and straight when Forward is used alone.
At the same time, the kids want to have the attachment motors operate to move forklift shuttle up/down and left/right into position. This function is called MoveLift(move_to_X=5, move_to_y=7, speed=50) to move the lift up 7cm and right 5cm at 50% speed, for example.
The lift function uses LargeMotor/MediumMotor.on_to_position to do the task of moving the lift.
They attempted to thread the lift move (after importing start_new_thread from _threading) while driving to one of the mission models on the table.
This will save valuable seconds if they can use the time driving to move the lift.
The Forward function is pretty much like I described above. The Move_Lift is shorter and is included below:
#*********************************************************************
#************* Move_Lift ************
#*********************************************************************
def Move_Lift(To_X, To_Y, Lift_Speed):
# DESCRIPTION:
# Move_Lift - Moves lift to position X, Y from original position at speed Lift_Speed
# EXAMPLE:
# Move the up/down motor (Large motor - reversed) and let the next command start
Y_Motor.on_to_position(Lift_Speed, position = (144 * To_Y), brake=True, block=False)
# Adjust the medium motor speed down so it moves as fast as the large motor
X_Motor.on_to_position(Lift_Speed * (1050/1560), position = (144 * To_X), brake=True, block=True)
# Let the motors finish their move
Y_Motor.wait_while('running')
X_Motor.wait_while('running')
# Find the final motor positions
Lift_X = X_Motor.position / 144
Lift_Y = Y_Motor.position / 144
return
#enddef
To run the functions at the same time, the kids programmed this (having imported start_new_thread from _thread):
# Start a thread to move the lift - Move_Lift(To_X=5, To_Y=8, Speed=50)
start_new_thread(Move_Lift, (5, 8, 50))
# Drive to the mission model
Robot_State = Forward(Distance=60, Speed=50, Ramp_Up=True, Ramp_Down=True, Brake_On=True, Robot_State)
IGNORANT AMATEUR IDEAS OF WHAT IS GOING ON: Here’s my thoughts on what might be wrong (and I’m just guessing at things - none of what I say is based on much knowledge of Python, threading, EV3DEV or coding in general):
-
The Forward function uses a loop to check the time and not a sleep command, and so the processor is constantly in operation and the threading of functions doesn’t have a time slot to execute and that messes up the command of the motors or the timing of the PID loop.
-
The MoveLift function puts a block=True on the second motor move command so it will wait until that command and prior motor move commands are finished before moving on causing a problem.
-
The LargeMotor/MediumMotor.wait_while(“running”) is causing problems
-
Our 20ms loop is too short and there just isn’t enough processor time.
-
EV3 just can’t multithread well
I’m just looking for thoughts on something obvious we might have done wrong, or what the next step in troubleshooting we might take to figure out what is wrong.
I wanted to have the kids run the program a few times yesterday with full troubleshooting output on, but there wasn’t time. I will get one of them to do it tomorrow so we can see the timing of the motor commands and position of each of the drive motors at each iteration of the loop, as well as what the PID is commanding for steering.
I need to have some idea of what might be going wrong so I can guide the kids in troubleshooting and teach “why things work the way they do.”
Thanks in advance for any ideas to try out.
Issue Analytics
- State:
- Created 4 years ago
- Comments:12 (5 by maintainers)
@rhempel @dwalton76 @dlech @WasabiFan
Update on the end result of the advice in this thread: My team sends their thanks. They just finished their District FLL tournament and are advancing to State and won robot design, in large part to the programming in Python using EV3DEV. At least 2 other teams advancing from our tournament were using Python, but the Lego version.
The kids loosened their loops in their drive functions to 50ms, changed the PID to drive the right wheel directly rather than us MoveSteering, and multithreaded their lift commands and driving moves which bought back enough time to complete every mission but 2 on the table.
Thank you again for your willingness to help them understand how things work.
The kids fixed the Forward function per your suggestions.
Running the motors directly and using the output of the PID to add/subtract speed from the right wheel made the robot drive the straightest it has ever driven.
Reducing the loop to to 50ms didn’t affect the performance negatively and may have improved it.