Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug] ev3 loop time issues with v3.X #1035

Open
kai-morich opened this issue Apr 17, 2023 · 38 comments · Fixed by pybricks/pybricks-micropython#161
Open

[Bug] ev3 loop time issues with v3.X #1035

kai-morich opened this issue Apr 17, 2023 · 38 comments · Fixed by pybricks/pybricks-micropython#161
Labels
bug Something isn't working platform: EV3 Issues related to LEGO MINDSTORMS EV3 software: pybricks-micropython Issues with Pybricks MicroPython firmware (or EV3 runtime)

Comments

@kai-morich
Copy link

kai-morich commented Apr 17, 2023

looks like some initialization is still ongoing, when the program is started

  • the first beep takes ~ 1 sec.
  • without the beep, the first drive.straight() drives for ~ 1 sec instead of the target distance
  • with print or wait before first beep the issue could be circumvented

the issue does not occur with v2.3.2 or with prime-hub at v3.3.0b3 or v2.3.2

#!/usr/bin/env pybricks-micropython
from pybricks.hubs import EV3Brick
from pybricks.ev3devices import Motor
from pybricks.parameters import Port, Stop, Direction
from pybricks.tools import wait
from pybricks.robotics import DriveBase

hub = EV3Brick()
left_motor = Motor(Port.C, positive_direction=Direction.COUNTERCLOCKWISE)
right_motor = Motor(Port.D)
drive = DriveBase(left_motor, right_motor, wheel_diameter=63, axle_track=91)

#print()
#wait(10)
hub.speaker.beep()
drive.straight(100, then=Stop.NONE)
drive.curve(150, -20, then=Stop.NONE)
drive.straight(100, then=Stop.NONE)
drive.curve(150, 20, then=Stop.NONE)
drive.straight(100)
hub.speaker.beep()
@kai-morich kai-morich added the triage Issues that have not been triaged yet label Apr 17, 2023
@dlech dlech added bug Something isn't working platform: EV3 Issues related to LEGO MINDSTORMS EV3 software: pybricks-micropython Issues with Pybricks MicroPython firmware (or EV3 runtime) and removed triage Issues that have not been triaged yet labels Apr 17, 2023
@laurensvalk
Copy link
Member

laurensvalk commented Apr 17, 2023

This is due to pybricks/pybricks-micropython#146.

We can open a new issue if timing becomes an issue elsewhere. (like the beep mentioned above)

Originally posted by @laurensvalk in pybricks/pybricks-micropython#146 (comment)

So thanks for opening this issue, @kai-morich :)

@kai-morich
Copy link
Author

I also noticed other strange behavior in a more complex program used for WRO 23 season when using v3.3b instead of v3.2.
I will try to isolate and create a testcase. Can the timing issue also affect the later program execution?

@kai-morich
Copy link
Author

this test programm

#!/usr/bin/env pybricks-micropython
from pybricks.hubs import EV3Brick
from pybricks.ev3devices import Motor
from pybricks.parameters import Port, Direction
from pybricks.tools import wait, StopWatch
from pybricks.robotics import DriveBase

ev3 = EV3Brick()
left_motor = Motor(Port.C, Direction.COUNTERCLOCKWISE)
right_motor = Motor(Port.D, Direction.CLOCKWISE)
robot = DriveBase(left_motor, right_motor, wheel_diameter=62, axle_track=195)
stopwatch = StopWatch()

# drive forward, e.g. with line / wall follower
print('a', stopwatch.time(), robot.distance())
robot.reset()
print('b', stopwatch.time(), robot.distance())
while robot.distance() < 100:
    print('c', stopwatch.time(), robot.distance())
    robot.drive(200, 0)
    print('d', stopwatch.time(), robot.distance())
    wait(10)
print('e', stopwatch.time(), robot.distance())
robot.stop()
print('f', stopwatch.time(), robot.distance())

works well with v.3.2.3 and produces this output

Starting: brickrun --directory="/home/robot/drive_test" "/home/robot/drive_test/main.py"
----------
a 0 0
b 13 0
c 23 0
d 26 0
c 39 0
d 40 0
c 58 0
d 61 0
c 80 2
d 82 2
c 99 4
d 102 4
c 115 4
d 121 5
c 137 5
d 139 5
c 156 7
d 158 7
c 170 9
d 172 9
c 186 11
d 192 11
c 206 13
d 208 14
c 223 15
d 226 16
c 240 18
d 242 18
c 267 22
d 270 23
c 283 25
d 288 26
c 307 29
d 309 29
c 321 31
d 323 32
c 340 35
d 343 35
c 361 39
d 363 39
c 377 42
d 384 43
c 406 47
d 407 48
c 421 50
d 423 51
c 441 54
d 443 54
c 457 57
d 459 58
c 473 60
d 476 61
c 493 64
d 495 65
c 513 68
d 518 69
c 535 72
d 537 73
c 554 76
d 559 77
c 578 80
d 580 81
c 592 83
d 595 84
c 613 87
d 622 89
c 635 91
d 637 92
c 657 95
d 659 96
c 673 98
d 676 99
e 693 101
f 694 102
----------
Completed successfully.

but is basically unusable with v3.3.0b3 and produces this output

Starting: brickrun --directory="/home/robot/drive_test" "/home/robot/drive_test/main.py"
----------
a 0 0
b 1722 0
c 1722 0
d 1727 0
c 1823 0
d 1824 0
c 1924 8
d 1927 9
c 2103 46
d 2104 47
c 2154 59
d 2154 59
c 2334 99
d 2334 100
e 2644 156
f 2647 156
----------
Completed successfully.

even with adding some longish wait or beep or drive.straight before, it doesn't get better

dlech added a commit to dlech/pybricks-micropython that referenced this issue Apr 28, 2023
This adds an extra check to make sure the motor poll timer hasn't
fallen too far behind.

Before this change, if calling the motor process was blocked for too
long, it would cause the motor contiki process to never yield until the
wall clock caught up. This would also cause motor updates to be called
with a time delta of 0 which probably caused unexpected conditions in
some of the calculations.

We can avoid this by checking to see if we have a condition that would
trigger the unwanted behavior and reset the timer to a larger interval.
This could cause a hiccup in the observer calculations but is a
significant improvement over the alternative.

Fixes: pybricks/support#1035
dlech added a commit to dlech/pybricks-micropython that referenced this issue Apr 28, 2023
This adds an extra check to make sure the motor poll timer hasn't
fallen too far behind.

Before this change, if calling the motor process was blocked for too
long, it would cause the motor contiki process to never yield until the
wall clock caught up. This would also cause motor updates to be called
with a time delta of 0 which probably caused unexpected conditions in
some of the calculations.

We can avoid this by checking to see if we have a condition that would
trigger the unwanted behavior and reset the timer to a larger interval.
This could cause a hiccup in the observer calculations but is a
significant improvement over the alternative.

Fixes: pybricks/support#1035
@dlech
Copy link
Member

dlech commented Apr 28, 2023

Hi @kai-morich

Can you please try pybricks-micropython-build-2735.zip and see if it fixes the issue?

@kai-morich
Copy link
Author

thanks for the fix, works again!

Starting: brickrun --directory="/home/robot/drive_test" "/home/robot/drive_test/main.py"
----------
a 0 0
b 15 0
c 21 0
d 22 0
c 34 0
d 35 0
c 52 0
d 54 0
c 65 1
d 72 1
c 84 1
d 84 1
c 99 3
d 101 3
c 112 3
d 113 3
c 125 4
d 127 4
c 145 5
d 146 5
c 161 6
d 162 6
c 179 7
d 179 7
c 195 8
d 196 8
c 212 10
d 218 11
c 231 13
d 232 13
c 244 14
d 245 14
c 264 17
d 265 18
c 279 20
d 284 20
c 295 22
d 296 22
c 313 24
d 314 24
c 332 27
d 334 28
c 349 30
d 349 30
c 361 32
d 362 32
c 375 34
d 379 35
c 392 37
d 393 37
c 405 38
d 408 39
c 421 41
d 426 41
c 439 43
d 440 44
c 452 45
d 453 45
c 469 48
d 469 48
c 481 50
d 486 50
c 498 52
d 499 52
c 511 54
d 520 55
c 532 57
d 533 57
c 549 59
d 551 60
c 564 62
d 565 62
c 580 64
d 582 64
c 595 66
d 598 67
c 610 69
d 611 69
c 622 70
d 624 71
c 636 73
d 638 73
c 657 76
d 662 77
c 680 80
d 681 80
c 693 82
d 694 82
c 708 84
d 709 84
c 721 86
d 722 87
c 734 89
d 735 89
c 752 92
d 754 92
c 772 95
d 774 95
c 788 98
d 789 98
e 801 100
f 802 100
----------
Completed successfully.

dlech added a commit to dlech/pybricks-micropython that referenced this issue May 1, 2023
This adds an extra check to make sure the motor poll timer hasn't
fallen too far behind.

Before this change, if calling the motor process was blocked for too
long, it would cause the motor contiki process to never yield until the
wall clock caught up. This would also cause motor updates to be called
with a time delta of 0 which probably caused unexpected conditions in
some of the calculations.

We can avoid this by checking to see if we have a condition that would
trigger the unwanted behavior and reset the timer to a larger interval.
This could cause a hiccup in the observer calculations but is a
significant improvement over the alternative.

Fixes: pybricks/support#1035
@dlech
Copy link
Member

dlech commented May 1, 2023

FYI, build 2735 had some issues.

I've made a 2nd attempt.

See pybricks/pybricks-micropython#161 (comment) for latest builds.

laurensvalk added a commit to pybricks/pybricks-micropython that referenced this issue May 2, 2023
This reduces the load on the rest of the program.

See: pybricks/support#1035
laurensvalk added a commit to pybricks/pybricks-micropython that referenced this issue May 2, 2023
This reduces the load on the rest of the program.

See: pybricks/support#1035
@kai-morich
Copy link
Author

with build-2738 runs much smoother than build-2735

dlech pushed a commit to pybricks/pybricks-micropython that referenced this issue May 2, 2023
This reduces the load on the rest of the program.

See: pybricks/support#1035
@dlech
Copy link
Member

dlech commented May 2, 2023

We've also made pybricks/pybricks-micropython#164 which should improve the control even more.

@dlech
Copy link
Member

dlech commented May 2, 2023

Build for testing: pybricks/pybricks-micropython#164 (comment) (includes both changes)

@kai-morich
Copy link
Author

kai-morich commented May 2, 2023

build 2756 has a new issue:

@laurensvalk laurensvalk reopened this May 2, 2023
laurensvalk added a commit to pybricks/pybricks-micropython that referenced this issue May 2, 2023
This reduces the load on the rest of the program.

See: pybricks/support#1035
@laurensvalk
Copy link
Member

test at #1056 fails with:
File "/home/robot/reverse_test/main.py", line 15, in set_speed
OSError: [Errno 1] EPERM:

That program doesn't seem quite right:

from pybricks.hubs import EV3Brick
from pybricks.pupdevices import Motor


hub = EV3Brick()
left_motor = Motor(Port.E, positive_direction=Direction.COUNTERCLOCKWISE)
right_motor = Motor(Port.F)

Which hub is this? EV3 has no pupdevices or port E and F.

Can you share the program that reproduces an error on EV3?

@kai-morich
Copy link
Author

I remember to have seen EPERM also with v2.0.0 when i tested #1056. For that old version I moved the set_speed() to the beginning of the program.

with stop() before set_speed() the new version works.

@laurensvalk
Copy link
Member

#!/usr/bin/env pybricks-micropython
from pybricks.hubs import EV3Brick
from pybricks.ev3devices import Motor
from pybricks.parameters import Port, Direction, Color
from pybricks.robotics import DriveBase
from pybricks.tools import wait

hub = EV3Brick()
left_motor = Motor(Port.C, Direction.COUNTERCLOCKWISE)
right_motor = Motor(Port.D, Direction.CLOCKWISE)
robot = DriveBase(left_motor, right_motor, wheel_diameter=62, axle_track=195)

def set_speed(speed):
    robot.settings(speed, speed*8, speed//2, speed*5 )

# drive forward with line / wall follower controlled turn_rate
hub.light.on(Color.YELLOW)
robot.reset()
while robot.distance() < 100:
    robot.drive(300, 0)
    wait(10)

# stop
hub.light.on(Color.GREEN)
#robot.stop() # <---
#wait(100)    # <---

# drive back
hub.light.on(Color.RED)
set_speed(100)
robot.straight(-100)

@laurensvalk
Copy link
Member

I remember to have seen EPERM also with v2.0.0

Yes, back in 2.0.0 changing the settings was not allowed while driving. This is allowed now. So we can skip that issue then.

@laurensvalk
Copy link
Member

That leaves us with:

test at this issue has very bumpy drive speed

Is the following better? Can you describe bumpy drive speed?

pybricks-micropython-build-2763

laurensvalk added a commit to pybricks/pybricks-micropython that referenced this issue May 2, 2023
This reduces the load on the rest of the program.

See: pybricks/support#1035
@kai-morich
Copy link
Author

2763 works again

bumpy: never reached normal speed. accelerated + deacellerated 2-3 times with 1 second period

@laurensvalk
Copy link
Member

Could I kindly ask for video? Thanks in advance.

@kai-morich
Copy link
Author

ok

@laurensvalk
Copy link
Member

laurensvalk commented May 2, 2023

Can you modify the following program to reproduce your issue?

from pybricks.ev3devices import Motor
from pybricks.tools import wait
from pybricks.parameters import Port, Direction
from pybricks.robotics import DriveBase
from pybricks import version

print(version)

# Initialize.
left_motor = Motor(Port.C, Direction.COUNTERCLOCKWISE)
right_motor = Motor(Port.D, Direction.CLOCKWISE)
robot = DriveBase(left_motor, right_motor, wheel_diameter=62, axle_track=195)

# Allocate logs for motors and controller signals.
DURATION = 6000
left_motor.log.start(DURATION)
right_motor.log.start(DURATION)
drive_base.distance_control.log.start(DURATION)
drive_base.heading_control.log.start(DURATION)

#
#
# Add some code here to make some moves that reproduce your problem. For example:
drive_base.straight(500)
drive_base.straight(-500)
#
#



drive_base.stop()

# Save data logs.
print("Saving data on the EV3...")
left_motor.log.save("servo_left.txt")
right_motor.log.save("servo_right.txt")
drive_base.distance_control.log.save("control_distance.txt")
drive_base.heading_control.log.save("control_heading.txt")
print("Done")

This will produce a few text files on your EV3. If you want to share them here, we can find out what is going on.

@kai-morich
Copy link
Author

sorry, too many test programs.

bumpy happened with the second test program:

#!/usr/bin/env pybricks-micropython
from pybricks.hubs import EV3Brick
from pybricks.ev3devices import Motor
from pybricks.parameters import Port, Direction
from pybricks.tools import wait, StopWatch
from pybricks.robotics import DriveBase

ev3 = EV3Brick()
left_motor = Motor(Port.C, Direction.COUNTERCLOCKWISE)
right_motor = Motor(Port.D, Direction.CLOCKWISE)
robot = DriveBase(left_motor, right_motor, wheel_diameter=62, axle_track=195)
stopwatch = StopWatch()


# drive forward, e.g. with line / wall follower
print('a', stopwatch.time(), robot.distance())
robot.reset()
print('b', stopwatch.time(), robot.distance())
while robot.distance() < 100:
    print('c', stopwatch.time(), robot.distance())
    robot.drive(200, 0)
    print('d', stopwatch.time(), robot.distance())
    wait(10)
print('e', stopwatch.time(), robot.distance())
robot.stop()
print('f', stopwatch.time(), robot.distance())
bumpy.mp4

will test the other programm and then add logs to the bumpier one

@kai-morich
Copy link
Author

kai-morich commented May 2, 2023

build 2756 looks incomplete:
ImportError: no module named 'pybricks.version'
AttributeError: 'Control' object has no attribute 'log'

older + newer builds are not bumpy

@laurensvalk
Copy link
Member

Thanks. I can reproduce one form of "bumpy" behavior. It looks like some loops are still taking too long.

image

@kai-morich
Copy link
Author

👍

@dlech
Copy link
Member

dlech commented May 5, 2023

I think it was a glitch that this was automatically closed. There are still some issues as shown in the plot by Laruens.

@dlech dlech reopened this May 5, 2023
@laurensvalk laurensvalk changed the title [Bug] ev3 initialization issue with v3.3.0b3 [Bug] ev3 loop time issues with v3.X Aug 28, 2023
@jaguilar
Copy link

jaguilar commented Aug 28, 2023

There is some commentary here or there that there are plans to try to get ev3 back to supported status in the next release of pybricks. However I'm told in #1215 that this is no longer the case. I wonder if we should add a warning to the console to make this clearer on initialization if someone is using a firmware that is not only not-yet-supported, but also actively never-gonna-be-supported.

For example #1075 suggests that getting a v3 firmware onto an ev3 is a thing that someone might want to do, but given there are no plans to make v3 work on ev3, it probably doesn't actually make sense for people to go through the trouble of testing it.

If this makes sense to people I could send a pull request.

@laurensvalk
Copy link
Member

Instead of modifying the build, I think we can just add a note to those (somewhat outdated) instructions.

And it looks like you have done so, so thanks for that!

It would certainly be nice to see the EV3 version continue to be supported. See also https://github.com/orgs/pybricks/discussions/1171#discussioncomment-6516689 for additional context.

@jaguilar
Copy link

Sure, that makes sense. And I totally understand the constraints involved with no supporting v3 on ev3 -- y'all have a limited amount of time to spend on the project and it definitely makes more sense to spend it on whatever is being used most today.

It does look like the _thread module will help with most of the things that I wanted to upgrade to v3 for -- the multitasking stuff. It's a little unfortunate that if/when I upgrade to spike prime, I'll need to change my code a bit to maximize efficiency, but it's definitely manageable.

@winklerp
Copy link

I would also highly appreciate if EV3 would be supported again by v3.3 since I have a lot of 3rd party sensors and add ons for it! Also communication between different hubs EV3 <-> Spike, … would be very nice! 👍

@winklerp
Copy link

winklerp commented Nov 4, 2023

Any chance to get this fixed vor v3.3?

@laurensvalk
Copy link
Member

No, this is not planned for V3.3 I'm afraid.

We don't seem to have enough EV3 users / sponsors / volunteers at the moment to work on this.

I would rather work on a revised firmware (either bare metal or non-SD-card-Linux), and get all the new features supported there, instead of patching the existing 2.0 edition that seems to work well enough for most users.

That way, the EV3 edition can eventually blend in with the rest of Pybricks (including web IDE) instead of treating it separately. Although not actively requested here on Github, this is requested a lot by people/teachers who would like a good and simple solution for EV3.

Then the stable 2.0 edition with vscode and all ev3dev iOT capabilities can continue to exist with its existing documentation, and hosting / support from LEGO Education, without ever making any breaking changes.

@BertLindeman
Copy link

No, this is not planned for V3.3 I'm afraid.

We don't seem to have enough EV3 users / sponsors / volunteers at the moment to work on this.

I would rather work on a revised firmware (either bare metal or non-SD-card-Linux), and get all the new features supported there, instead of patching the existing 2.0 edition that seems to work well enough for most users.

That way, the EV3 edition can eventually blend in with the rest of Pybricks (including web IDE) instead of treating it separately. Although not actively requested here on Github, this is requested a lot by people/teachers who would like a good and simple solution for EV3.

Then the stable 2.0 edition with vscode and all ev3dev iOT capabilities can continue to exist with its existing documentation, and hosting / support from LEGO Education, without ever making any breaking changes.

Keeping 2.0 version stable and to add EV3 to the code.pybricks.com family would be very nice.
Would really like that.

I have the EV3 still running as linux host, but it's just running for fun.
The linux version (ev3dev-stretch) is lagging behind a bit. Stretch went out of support June 2022.

@winklerp
Copy link

winklerp commented Nov 5, 2023

I would rather work on a revised firmware (either bare metal or non-SD-card-Linux), and get all the new features supported there, instead of patching the existing 2.0 edition that seems to work well enough for most users.

That way, the EV3 edition can eventually blend in with the rest of Pybricks (including web IDE) instead of treating it separately. Although not actively requested here on Github, this is requested a lot by people/teachers who would like a good and simple solution for EV3.

That would be an awesome solution but sounds like way more work and might also take longer than getting the current version running again even if not "officially" supported.

@laurensvalk
Copy link
Member

laurensvalk commented Nov 5, 2023

I don't think there's a quick fix/hack available if that's what you're asking.

The current iteration of motor drivers were designed for bare metal systems with simple timing, so it is not expected to work as-is on EV3 (Linux). That is to say, this isn't just some random bug.

This was intentional / by design: the drivers have been a huge step forward on all platforms that have ongoing releases.

And nothing is really broken on 2.0 either, it just didn't get all the new features.

While it's probably technically possible to revise the control algorithms for non-rt systems, it doesn't seem worth investing a lot of time that could be used elsewhere.

Perhaps taking a step back, what are the main use cases for V3.3? Is it only certain drive functions? Could they be implemented using a Python class?

Due to the nature of the hardware, control precision is quite good on EV3 in 2.0, both for single and dual motors. So it shouldn't be too hard to implement things like curve with a radius, and make them non-blocking with the wait=False paradigm used elsewhere.

@kai-morich
Copy link
Author

I like the curve function and then=Stop.* options introduced after V2.0. Both could very likely be implemented in python on top of V2.0.

What is the latest version you can seriously recommend for EV3?

When were the new motor drivers introduced? In V3.3 or earlier? I used V3.2 quite succefully, besides bug #1056 that happened sometimes when reversing the direction.

@laurensvalk
Copy link
Member

What is the latest version you can seriously recommend for EV3?

I would recommend the official version hosted by LEGO Education, so Pybricks 2.0.

I like the curve function and then=Stop.* options introduced after V2.0. (...) When were the new motor drivers introduced?

These features were introduced alongside the new drivers in 3.3.

Both could very likely be implemented in python on top of V2.0.

👍

Rest assured, we won't forget about EV3. Just trying to keep expectations realistic 😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working platform: EV3 Issues related to LEGO MINDSTORMS EV3 software: pybricks-micropython Issues with Pybricks MicroPython firmware (or EV3 runtime)
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants