Merge pull request #461 from jjofre/master

Fixes to properly resume plotting after calibration
This commit is contained in:
Mark Liversedge
2013-01-24 13:13:13 -08:00
2 changed files with 119 additions and 100 deletions

View File

@@ -88,10 +88,19 @@ ComputrainerController::getRealtimeData(RealtimeData &rtData)
parent->Stop(1);
return;
}
// get latest telemetry
myComputrainer->getTelemetry(Power, HeartRate, Cadence, Speed,
RRC, calibration, Buttons, ss, Status);
// Check CT if F3 has been pressed for Calibration mode FIRST befoire we do anything else
if (Buttons&CT_F3) {
parent->Calibrate();
}
// ignore other buttons and anything else if calibrating
if (parent->calibrating) return;
//
// PASS BACK TELEMETRY
//
@@ -114,14 +123,6 @@ ComputrainerController::getRealtimeData(RealtimeData &rtData)
// BUTTONS
//
// toggle calibration
if (Buttons&CT_F3) {
parent->Calibrate();
}
// ignore other buttons if calibrating
if (parent->calibrating) return;
// ADJUST LOAD
Load = myComputrainer->getLoad();
if ((Buttons&CT_PLUS) && !(Buttons&CT_F3)) {

View File

@@ -699,7 +699,9 @@ void TrainTool::Start() // when start button is pressed
load_period.restart();
if (status & RT_WORKOUT) load_timer->start(LOADRATE);
#if defined Q_OS_MAC || defined GC_HAVE_VLC
mediaTree->setEnabled(false);
#endif
// tell the world
main->notifyUnPause();
@@ -869,7 +871,9 @@ void TrainTool::Pause() // pause capture to recalibrate
load_msecs += load_period.restart();
// enable media tree so we can change movie
#if defined Q_OS_MAC || defined GC_HAVE_VLC
mediaTree->setEnabled(true);
#endif
// tell the world
main->notifyPause();
@@ -999,116 +1003,123 @@ void TrainTool::guiUpdate() // refreshes the telemetry
// get latest telemetry from devices
if (status&RT_RUNNING) {
if(calibrating) {
foreach(int dev, devices()) { // Do for Computrainers only. Need to check with other devices
RealtimeData local = rtData;
if (Devices[dev].type == DEV_CT)
Devices[dev].controller->getRealtimeData(local); // See if the F3 button has been pressed
}
// and exit. Nothing else to do until we finish calibrating
return;
} else {
rtData.setLoad(load); // always set load..
rtData.setSlope(slope); // always set load..
rtData.setLoad(load); // always set load..
rtData.setSlope(slope); // always set load..
// fetch the right data from each device...
foreach(int dev, devices()) {
// fetch the right data from each device...
foreach(int dev, devices()) {
RealtimeData local = rtData;
Devices[dev].controller->getRealtimeData(local);
RealtimeData local = rtData;
Devices[dev].controller->getRealtimeData(local);
// get spinscan data from a computrainer?
if (Devices[dev].type == DEV_CT) {
memcpy((uint8_t*)rtData.spinScan, (uint8_t*)local.spinScan, 24);
rtData.setLoad(local.getLoad()); // and get load in case it was adjusted
// to within defined limits
}
// get spinscan data from a computrainer?
if (Devices[dev].type == DEV_CT) {
memcpy((uint8_t*)rtData.spinScan, (uint8_t*)local.spinScan, 24);
rtData.setLoad(local.getLoad()); // and get load in case it was adjusted
// to within defined limits
}
// what are we getting from this one?
if (dev == bpmTelemetry) rtData.setHr(local.getHr());
if (dev == rpmTelemetry) rtData.setCadence(local.getCadence());
if (dev == kphTelemetry) {
rtData.setSpeed(local.getSpeed());
rtData.setDistance(local.getDistance());
}
if (dev == wattsTelemetry) {
rtData.setWatts(local.getWatts());
rtData.setAltWatts(local.getAltWatts());
}
}
// what are we getting from this one?
if (dev == bpmTelemetry) rtData.setHr(local.getHr());
if (dev == rpmTelemetry) rtData.setCadence(local.getCadence());
if (dev == kphTelemetry) {
rtData.setSpeed(local.getSpeed());
rtData.setDistance(local.getDistance());
}
if (dev == wattsTelemetry) {
rtData.setWatts(local.getWatts());
rtData.setAltWatts(local.getAltWatts());
}
}
// Distance assumes current speed for the last second. from km/h to km/sec
displayDistance += displaySpeed / (5 * 3600); // XXX assumes 200ms refreshrate
displayWorkoutDistance += displaySpeed / (5 * 3600); // XXX assumes 200ms refreshrate
rtData.setDistance(displayDistance);
// Distance assumes current speed for the last second. from km/h to km/sec
displayDistance += displaySpeed / (5 * 3600); // XXX assumes 200ms refreshrate
displayWorkoutDistance += displaySpeed / (5 * 3600); // XXX assumes 200ms refreshrate
rtData.setDistance(displayDistance);
// time
total_msecs = session_elapsed_msec + session_time.elapsed();
lap_msecs = lap_elapsed_msec + lap_time.elapsed();
// time
if (!calibrating) { // freeze time whilst calibrating
total_msecs = session_elapsed_msec + session_time.elapsed();
lap_msecs = lap_elapsed_msec + lap_time.elapsed();
rtData.setMsecs(total_msecs);
rtData.setLapMsecs(lap_msecs);
rtData.setMsecs(total_msecs);
rtData.setLapMsecs(lap_msecs);
long lapTimeRemaining;
if (ergFile) lapTimeRemaining = ergFile->nextLap(load_msecs) - load_msecs;
else lapTimeRemaining = 0;
long lapTimeRemaining;
if (ergFile) lapTimeRemaining = ergFile->nextLap(load_msecs) - load_msecs;
else lapTimeRemaining = 0;
if(lapTimeRemaining < 0)
{
if (ergFile) lapTimeRemaining = ergFile->Duration - load_msecs;
if(lapTimeRemaining < 0)
lapTimeRemaining = 0;
}
rtData.setLapMsecsRemaining(lapTimeRemaining);
if(lapTimeRemaining < 0)
{
if (ergFile) lapTimeRemaining = ergFile->Duration - load_msecs;
if(lapTimeRemaining < 0)
lapTimeRemaining = 0;
}
rtData.setLapMsecsRemaining(lapTimeRemaining);
}
// local stuff ...
displayPower = rtData.getWatts();
displayCadence = rtData.getCadence();
displayHeartRate = rtData.getHr();
displaySpeed = rtData.getSpeed();
load = rtData.getLoad();
// local stuff ...
displayPower = rtData.getWatts();
displayCadence = rtData.getCadence();
displayHeartRate = rtData.getHr();
displaySpeed = rtData.getSpeed();
load = rtData.getLoad();
// virtual speed
double crr = 0.004f; // typical for asphalt surfaces
double g = 9.81; // g constant 9.81 m/s
double weight = appsettings->cvalue(main->cyclist, GC_WEIGHT, 0.0).toDouble();
double m = weight ? weight + 8 : 83; // default to 75kg weight, plus 8kg bike
double sl = slope / 100; // 10% = 0.1
double ad = 1.226f; // default air density at sea level
double cdA = 0.5f; // typical
double pw = rtData.getWatts();
// virtual speed
double crr = 0.004f; // typical for asphalt surfaces
double g = 9.81; // g constant 9.81 m/s
double weight = appsettings->cvalue(main->cyclist, GC_WEIGHT, 0.0).toDouble();
double m = weight ? weight + 8 : 83; // default to 75kg weight, plus 8kg bike
double sl = slope / 100; // 10% = 0.1
double ad = 1.226f; // default air density at sea level
double cdA = 0.5f; // typical
double pw = rtData.getWatts();
// algorithm supplied by Tom Compton
// from www.AnalyticCycling.com
// 3.6 * ... converts from meters per second to kph
double vs = 3.6f * (
// algorithm supplied by Tom Compton
// from www.AnalyticCycling.com
// 3.6 * ... converts from meters per second to kph
double vs = 3.6f * (
(-2*pow(2,0.3333333333333333)*(crr*m + g*m*sl)) /
pow(54*pow(ad,2)*pow(cdA,2)*pw +
sqrt(2916*pow(ad,4)*pow(cdA,4)*pow(pw,2) +
864*pow(ad,3)*pow(cdA,3)*pow(crr*m +
g*m*sl,3)),0.3333333333333333) +
pow(54*pow(ad,2)*pow(cdA,2)*pw +
sqrt(2916*pow(ad,4)*pow(cdA,4)*pow(pw,2) +
864*pow(ad,3)*pow(cdA,3)*pow(crr*m +
g*m*sl,3)),0.3333333333333333)/
(3.*pow(2,0.3333333333333333)*ad*cdA));
pow(54*pow(ad,2)*pow(cdA,2)*pw +
sqrt(2916*pow(ad,4)*pow(cdA,4)*pow(pw,2) +
864*pow(ad,3)*pow(cdA,3)*pow(crr*m +
g*m*sl,3)),0.3333333333333333) +
pow(54*pow(ad,2)*pow(cdA,2)*pw +
sqrt(2916*pow(ad,4)*pow(cdA,4)*pow(pw,2) +
864*pow(ad,3)*pow(cdA,3)*pow(crr*m +
g*m*sl,3)),0.3333333333333333)/
(3.*pow(2,0.3333333333333333)*ad*cdA));
// just in case...
if (isnan(vs) || isinf(vs)) vs = 0.00f;
// just in case...
if (isnan(vs) || isinf(vs)) vs = 0.00f;
rtData.setVirtualSpeed(vs);
rtData.setVirtualSpeed(vs);
// go update the displays...
main->notifyTelemetryUpdate(rtData); // signal everyone to update telemetry
// go update the displays...
main->notifyTelemetryUpdate(rtData); // signal everyone to update telemetry
// set now to current time when not using a workout
// but limit to almost every second (account for
// slight timing errors of 100ms or so)
// set now to current time when not using a workout
// but limit to almost every second (account for
// slight timing errors of 100ms or so)
// Do some rounding to the hundreds because as time goes by, rtData.getMsecs() drifts just below and then it does not pass the mod 1000 < 100 test
// For example: msecs = 42199. Mod 1000 = 199 versus msecs = 42000. Mod 1000 = 0
// With this, it will now call tick just about every second
long rmsecs = round((rtData.getMsecs() + 99) / 100) * 100;
// Test for <= 100ms
if (!(status&RT_WORKOUT) && ((rmsecs % 1000) <= 100)) {
main->notifySetNow(rtData.getMsecs());
}
}
// Do some rounding to the hundreds because as time goes by, rtData.getMsecs() drifts just below and then it does not pass the mod 1000 < 100 test
// For example: msecs = 42199. Mod 1000 = 199 versus msecs = 42000. Mod 1000 = 0
// With this, it will now call tick just about every second
long rmsecs = round((rtData.getMsecs() + 99) / 100) * 100;
// Test for <= 100ms
if (!(status&RT_WORKOUT) && ((rmsecs % 1000) <= 100)) {
main->notifySetNow(rtData.getMsecs());
}
}
}
}
// can be called from the controller - when user presses "Lap" button
@@ -1282,6 +1293,8 @@ void TrainTool::Calibrate()
lap_time.start();
load_period.restart();
if (status & RT_WORKOUT) load_timer->start(LOADRATE);
if (status & RT_STREAMING) stream_timer->start(STREAMRATE);
if (status & RT_RECORDING) disk_timer->start(SAMPLERATE);
main->notifyUnPause(); // get video started again, amongst other things
// back to ergo/slope mode
@@ -1302,11 +1315,16 @@ void TrainTool::Calibrate()
}
bar->show();
// pause gui/load but keep recording!
// pause gui/load, streaming and recording
// but keep the gui ticking so we get realtime telemetry to detect the F3 keypad =button press
session_elapsed_msec += session_time.elapsed();
lap_elapsed_msec += lap_time.elapsed();
if (status & RT_STREAMING) stream_timer->stop();
if (status & RT_RECORDING) disk_timer->stop();
if (status & RT_WORKOUT) load_timer->stop();
load_msecs += load_period.restart();
main->notifyPause(); // get video started again, amongst other things
// only do this for computrainers!