cagnulein / qdomyos-zwift

Zwift bridge for smart treadmills and bike/cyclette
https://www.qzfitness.com/
GNU General Public License v3.0
351 stars 107 forks source link

Matching QZ Speed to Zwift Speed using Zwift Workout files (.zwo) #1209

Closed victorypoint closed 1 year ago

victorypoint commented 1 year ago

I'm testing a Zwift Run workout file loaded and started in Zwift and QZ at the same time. The idea is to have QZ control TM speed while the workout runs in Zwift.

I've loaded this custom Zwift workout into both Zwift (Windows 11) and QZ (Android) - https://whatsonzwift.com/workouts/ai-endurance/run-anaerobic-run

First workout entry in file is a ramp: Warmup Duration="620" PowerLow="0.65" PowerHigh="0.8" pace="1" /

Expected initial workout speed based on 5K pace (pace 1) of 21:34 = 13.91 kph x 0.65 = 9.04 kph (rounded to 9.0 kph)

Zwift displays initial workout speed as 9.0 kph and then progresses to 9.1, 9,2, 9.3, etc.. QZ (when configured with exact paces as Zwift) displays initial workout speed as 8.7 kph and then progresses to 9.2, 9.3, etc

QZ initial speed appears to be incorrect (8.7kph) and the ramp speeds appear to be 0.1 kph ahead of Zwift

Attached is QZ log of a test session where the TM starts at 2.0 kph, then the Zwift workout file is loaded and started. Treadmill/QZ speed starts at 8.7, 9.2 ... 9.5 then manually stopped

debug-Tue_Jan_24_15_47_34_2023.log

cagnulein commented 1 year ago

i was checking the log from the phone and the first change from the workout sent to the companion is

Tue Jan 24 15:48:09 2023 1674589689522 Debug: ../src/trainprogram.cpp void trainprogram::scheduler() "trainprogram change speed9.04173"

in which tile do you see the 8.7?

victorypoint commented 1 year ago

The speed tile showed 8.7. Here's the progression of speed from the same QZ log:

Line  7952: Tue Jan 24 15:48:12 2023 1674589692233 Debug: ../src/bluetooth.cpp void bluetooth::debug(const QString &) "Current Speed: 2"
Line  7961: Tue Jan 24 15:48:12 2023 1674589692247 Debug: ../src/bluetooth.cpp void bluetooth::debug(const QString &) "Current Speed: 8.69"
Line 11674: Tue Jan 24 15:48:43 2023 1674589723570 Debug: ../src/bluetooth.cpp void bluetooth::debug(const QString &) "Current Speed: 9.2"
Line 11755: Tue Jan 24 15:48:44 2023 1674589724170 Debug: ../src/bluetooth.cpp void bluetooth::debug(const QString &) "Current Speed: 9.19"
Line 15098: Tue Jan 24 15:49:12 2023 1674589752768 Debug: ../src/bluetooth.cpp void bluetooth::debug(const QString &) "Current Speed: 9.3"
Line 18750: Tue Jan 24 15:49:43 2023 1674589783160 Debug: ../src/bluetooth.cpp void bluetooth::debug(const QString &) "Current Speed: 9.4"
Line 22467: Tue Jan 24 15:50:12 2023 1674589812979 Debug: ../src/bluetooth.cpp void bluetooth::debug(const QString &) "Current Speed: 9.5"
Line 23776: Tue Jan 24 15:50:24 2023 1674589824945 Debug: ../src/bluetooth.cpp void bluetooth::debug(const QString &) "Current Speed: 0"
cagnulein commented 1 year ago

it seems a problem in the companion app for the first change more than a bug on the qz for workout

now i'm going to bed, i will check deeply tomorrow

victorypoint commented 1 year ago

Interesting. Here's a logcat of the same workout starting at 8.7kph...

logcat.txt

cagnulein commented 1 year ago

ok @victorypoint it's for sure a companion app issue in the calculation of the coordinates for your treadmill. probably it's because there is a huge jump from the 2km/h to the 9km/h

this is the current implementation for your treadmill

y1Speed = 807 - (int) ((QZService.lastSpeedFloat - 1) * 29.78);
//set speed slider to target position
y2 = y1Speed - (int) ((reqSpeed - QZService.lastSpeedFloat) * 29.78);

so let's check manually on your treadmill, put the speed to 2 and then

y1Speed = 807 - (int) ((2 - 1) * 29.78);
//set speed slider to target position
y2 = y1Speed - (int) ((9 - 2) * 29.78);

input swipe 1845 y1Speed 1845 y2 200

I guess you will see the same behaviour. If so it means that we have to play with this formula again. Let me know

victorypoint commented 1 year ago

@cagnulein , so I must apologize. I just finished testing the calculations extensively and came up with new pixel scaling factors for both speed and incline. The previous values didn't work for jumping from min to max speeds and incline. This is strange because I remember testing for this before. I thought maybe an iFit update could have caused the screen dimensions or placements to shift but no, all pixels are identical to where they were before.

So here's the new scaling factors that absolutely work. The old scaling values of speed 29.98, and incline 29.9 no longer work.

speedscale = 31.0 inclinescale = 31.1

cagnulein commented 1 year ago

no problem at all! i will update this tomorrow!

cagnulein commented 1 year ago

done!

victorypoint commented 1 year ago

done!

Awesome! Thank-you. So test 3.2.14?

cagnulein commented 1 year ago

@victorypoint yes!

victorypoint commented 1 year ago

Ok, much better. The .zwo file started at 9.0 kph this time but still a bit of strange behavior after - likely due to speed rounding. After 9.0, next speed jumped to 9.2 and progressed to 9.5kph where I stopped the test.

Test starts at 01-26 11:50:20

logcat.txt

debug-Thu_Jan_26_11_50_00_2023.log

cagnulein commented 1 year ago

from the qz thing is ok (i'm sending all the possibile speed variations, maybe we should limit for your treadmill to 0.1 changes?) also in the qz companions seems fine, i see 9.0, 9.1, 9.2, 9.3, 9.4

in the last companion log, i added the input swipe commands that i'm sending

01-26 11:50:22.260 9109 9669 I QZ:UDPListenerService: input swipe 1845 776 1845 556 200 01-26 11:50:52.357 9109 25397 I QZ:UDPListenerService: input swipe 1845 559 1845 553 200 01-26 11:51:21.237 9109 21061 I QZ:UDPListenerService: input swipe 1845 554 1845 551 200 01-26 11:51:51.351 9109 28807 I QZ:UDPListenerService: input swipe 1845 550 1845 547 200 01-26 11:52:21.454 9109 30658 I QZ:UDPListenerService: input swipe 1845 547 1845 544 200

could you try them?

victorypoint commented 1 year ago

@cagnulein , I'm starting to narrow down the problem. I did a sucessull test or the ramp portion of the workout and all speeds and timing seemed to match the Zwift interpretation exactly. Speed started at 2.0, then went from 9.0 - 11.1 (11.07) in 10min 20sec. No problem with any of the speeds.

Where it looks like the speeds got messed up in earlier tests is because I let the TM idle for several minutes. This appears to make the internal ADB remote sleep, drop connection, and miss swipes. I think this ADB remote sleep problem is new as I've not experienced it before in several builds.

Attached is a few adblogs:

full-ramp-test.log - TM just rebooted and awake and went into manual workout mode. Full ramp test worked perfectly sleep-test.log - TM was idle for about 5 minutes then went into manual workout mode. ADB remote looses connection

ramp-tests.zip

cagnulein commented 1 year ago

oh this is new. i will check tomorrow with a fresh brain :)

thanks for this deep debug session

victorypoint commented 1 year ago

oh this is new. i will check tomorrow with a fresh brain :)

thanks for this deep debug session

@cagnulein , hold off on this for now. The problem may be caused by me swiping back and forth between QZC and iFit apps. I just retested by rebooting TM, running .zwo workout, then waiting 5 minutes, then running .zwo workout again. ADB Remote did not go to sleep. Let me test longer periods of idle time in the morning to confirm this.

cagnulein commented 1 year ago

ok thanks for the feedback!

victorypoint commented 1 year ago

Okay, ran a test this morning. Reboot TM, start manual workout and QZ, send speed changes - working good. Let TM sit idle for 30 minutes and repeated procedure - no response to QZ speed changes and QZC app crashed. Seems to be a problem with Companion wakelock. Using latest Companion v3.2.14. Attached logcats:

logcat1.txt - showing swipes sent between 10:23 - 10:25am, then keep capturing while TM idle. Logcat buffer filled and stopped capturing at 10:32am.

logcat2.txt - logcat capture started at 10:59am, swipes not captured as ADB remote was no longer connected. TM displayed message on screen - "QZ Companion NordicTrack has stopped"

logcat1.txt logcat2.txt

cagnulein commented 1 year ago

ok @victorypoint I will take a look, thanks! if you instead do a long run session don't you have this issue?

victorypoint commented 1 year ago

ok @victorypoint I will take a look, thanks! if you instead do a long run session don't you have this issue?

I will test that soon with the latest version. I suspect it will continue to work because the TM is not going idle during the workout but will let you know.

cagnulein commented 1 year ago

hah so idle means that also the screen for example is dimming?

victorypoint commented 1 year ago

hah so idle means that also the screen for example is dimming?

The iFit app (which is in foreground) has a screensaver that kicks in after about 5 min idle.

So just tested auto-inclination in a running tour de Zwift event. Absolutely no issues. Will test a .zwo workout next synced between Zwift and QZ to test auto-speed.

victorypoint commented 1 year ago

So just tested auto-inclination in a running tour de Zwift event. Absolutely no issues.

Sorry, 1 minor issue popped up. About 55 minutes into the event, that same message appeared on screen - "QZ Companion NordicTrack has stopped". But speed and inclination metrics between all apps continued to work. Weird.

cagnulein commented 1 year ago

is not possible to disable the screen saver from the settings? for the 55 minutes error, probably it restarts with the wakelock mechanism

victorypoint commented 1 year ago

is not possible to disable the screen saver from the settings? for the 55 minutes error, probably it restarts with the wakelock mechanism

Doesn't look like screensaver disable is an option within iFit app.

victorypoint commented 1 year ago

Ok, just did a .zwo workout synced between Zwift and QZ to test auto-speed.

  1. Rebooted TM, Start Zwift (Windows) and QZ (Android). Got all 3 apps talking to each other regarding speed and incline metrics.
  2. Started the .zwo workout in Zwift and QZ and exactly the same time. Well, I got within 2 seconds of each other so Zwift was 2 seconds ahead in the elapsed time.
  3. QZ was controlling speed fine for the first 8 minutes then ADB Remote lost connection.
  4. Discovered that both Zwift and QZ interpret workout ramps differently. QZ increased speeds by 0.1 kph increments over the ramp time, while Zwift started with 0.1 increments then would increase by 0.2, 0.3, 0.4. The timing of the increments was different for each app but QZ was often 0.1 kph ahead of the Zwift speed prompt. At 10.7 kph they were both synced for speed.

Looking through the logcat (attached):

logcat.txt

cagnulein commented 1 year ago

Thanks for the detailed log, I will check probably on Sunday (tomorrow I have to stay with the baby full time)

victorypoint commented 1 year ago

I retested the above using QZC v3.0.7 which is a very reliable build I used to do many auto-incline runs. No ADB remote or UDPListenerService problems at all. I let the QZ .zwo workout run well into about 15 minutes with no problems (except the swipes were incorrect as we just fixed that in v 3.2.14.

cagnulein commented 1 year ago

I retested the above using QZC v3.0.7 which is a very reliable build I used to do many auto-incline runs. No ADB remote or UDPListenerService problems at all. I let the QZ .zwo workout run well into about 15 minutes with no problems (except the swipes were incorrect as we just fixed that in v 3.2.14.

this is the changes compare from the current and the 3.0.7 https://github.com/cagnulein/QZCompanionNordictrackTreadmill/compare/7859dbc463067b7c8d0dca6e04d551239e8c1282..bce00bfa054badfb76c6f7024b6a2c5ab1accd44

I will check tomorrow. Of course if you can bisect the version somehow will be great

victorypoint commented 1 year ago

Nothing stands out to me with the change of code. I think the best I can do is help narrow down which version caused the problem. So I did more testing and found out that version 3.0.17 also works well with no problems with ADB remote and UDPListenerService. That gets us a bit closer at least.

victorypoint commented 1 year ago

@cagnulein , I just finished testing QZC v3.1.3 and it performed solid as well with the entire .zwo file. No ADB remote or UDPListenerService problems. I'll stop here as versions 3.2.2 and above have the navigation stall problem which is of course fixed in v3.2.11.

cagnulein commented 1 year ago

ok so these are the changes https://github.com/cagnulein/QZCompanionNordictrackTreadmill/compare/3.1.3...master I'm checking them

cagnulein commented 1 year ago

ok @victorypoint i guess the only relevant modification is this one https://github.com/cagnulein/QZCompanionNordictrackTreadmill/commit/5eb5244b0f299c30fcbb45d4324e2f0df4080ae0

let me create a separate branch from the master so you can try the actual version withot this one

cagnulein commented 1 year ago

done @victorypoint https://github.com/cagnulein/QZCompanionNordictrackTreadmill/suites/10656093380/artifacts/532588584

victorypoint commented 1 year ago

done @victorypoint https://github.com/cagnulein/QZCompanionNordictrackTreadmill/suites/10656093380/artifacts/532588584

@cagnulein , this build works good with no adb remote or listener problems. I ran the full 30 minute .zwo workout in QZ. The only minor issue I noticed is that the speed goes from 2.0 to 9.0 initially which is expected, but then about 2 seconds later jumps to 9.1 kph. Attaching a logcat for that behavior. Note that I did a manual incline test from 0 to 0.5 before loading and running the .zwo.

Workout ramp is:

logcat.txt

cagnulein commented 1 year ago

so since @jdh65 didn't answer me here https://github.com/cagnulein/QZCompanionNordictrackTreadmill/issues/33 i'm reverting this.

cagnulein commented 1 year ago

but then about 2 seconds later jumps to 9.1 kph

yes because qz app sends first 9.0451 then after 2 seconds 9.05183 with the rounding the first is 9.0 and the second is 9.1

so this will lead more to the way how qz is doing the ramp. Qz is doing it linear, if I remember well you were saying that Zwift doesn't?

victorypoint commented 1 year ago

but then about 2 seconds later jumps to 9.1 kph

yes because qz app sends first 9.0451 then after 2 seconds 9.05183 with the rounding the first is 9.0 and the second is 9.1

so this will lead more to the way how qz is doing the ramp. Qz is doing it linear, if I remember well you were saying that Zwift doesn't?

Right. Swift appears to interpret the workout so that each speed change is about the same separation.

cagnulein commented 1 year ago

@victorypoint

QZ increased speeds by 0.1 kph increments over the ramp time, while Zwift started with 0.1 increments then would increase by 0.2, 0.3, 0.4. The timing of the increments was different for each app but QZ was often 0.1 kph ahead of the Zwift speed prompt. At 10.7 kph they were both synced for speed.

could you describe me this better. I mean reading again your words i don't see any differences between qz and zwift.

What I'm doing is: divide the ramp in seconds. So if the ramps last 100 seconds, and i have to increment 1 km/h, i'm adding 0.01 km/h each seconds.

Which is the behaviour of zwift instead in this scenario?

victorypoint commented 1 year ago

Yes I will describe better. I think what I'll do is record video of both running at the same time

victorypoint commented 1 year ago

@cagnulein , Oh and quick question about elapsed time in QZ. After confirming that auto speed and incline work with some plus minus button presses, I'd like to be able to reset a lapse time in QZ so that I can just hit the start button to start the .zwo workout. How would I reset a lapse time?

cagnulein commented 1 year ago

elapsed time it's reset when you press stop. just start qz in pause mode, load the program and then press start when you are ready

victorypoint commented 1 year ago

@cagnulein , ok using the latest QZ Android 2.12.55, "pause when app starts" doesn't seem to be working. When toggled on and QZ is restarted, the app is not in pause mode. Is there another setting required?

cagnulein commented 1 year ago

are you using the setting under treadmill section?

victorypoint commented 1 year ago

are you using the setting under treadmill section?

Ah ha! Sorry no I was using that one under general options. I didn't realize there was another one under treadmill options. Okay good it's working now

cagnulein commented 1 year ago

yeah it's confusing, i noticed now

victorypoint commented 1 year ago

What I'm doing is: divide the ramp in seconds. So if the ramps last 100 seconds, and i have to increment 1 km/h, i'm adding 0.01 km/h each seconds.

Which is the behaviour of zwift instead in this scenario?

@cagnulein , I compared the ramp timings between Zwift and QZ again in detail. Both programs are very close to the same speed during the ramp. So in 620 seconds (10 min 20 sec), both went from 9 to 11.1 kph. Both made a 0.1 kph speed change about every 30 seconds. The only strange behavior as I mentioned earlier is QZ went from 9.0 to 9.1 in the first 2-3 seconds instead of a 30 second interval. I suspect this starting behavior is what made the QZ speeds to be 0.1 ahead of Zwift.

After the ramp at 620 seconds, Zwift jumped to 16 kph for 20 seconds as per the next interval:

QZ also jumped to 16 kph but stayed there for 40 seconds instead of 20.

I haven't compared the timings of the entire workout between the two but this is a good start.

cagnulein commented 1 year ago

QZ also jumped to 16 kph but stayed there for 40 seconds instead of 20.

do you have a debug log for this? because in the last debug log that you sent me i saw the right behaviour (at least during the zwo loading).

The only strange behavior as I mentioned earlier is QZ went from 9.0 to 9.1 in the first 2-3 seconds

for this one, the only thing that I can do is to truncate the number instead of rounding, do you agree?

victorypoint commented 1 year ago

QZ also jumped to 16 kph but stayed there for 40 seconds instead of 20.

do you have a debug log for this? because in the last debug log that you sent me i saw the right behaviour (at least during the zwo loading).

The only strange behavior as I mentioned earlier is QZ went from 9.0 to 9.1 in the first 2-3 seconds

for this one, the only thing that I can do is to truncate the number instead of rounding, do you agree?

@cagnulein , the ramp issue is very minor and doesn't bother me. As long as it starts and ends at correct durations and speeds it's all fine.

I'll do more testing today with more .zwo files and save logcats as well.

cagnulein commented 1 year ago

ok for the 20-40 seconds issue, i just need the qz debug log, it's enough

victorypoint commented 1 year ago

but then about 2 seconds later jumps to 9.1 kph

yes because qz app sends first 9.0451 then after 2 seconds 9.05183 with the rounding the first is 9.0 and the second is 9.1

so this will lead more to the way how qz is doing the ramp. Qz is doing it linear, if I remember well you were saying that Zwift doesn't?

@cagnulein , I'm not sure I understand the QZ ramp logic here. If QZ is doing it linear, the first speed should be 9.0 and then 9.1 to follow about 30 seconds later. Why is 9.1 sent a few seconds after 9.0?