C
Qt Quick Ultralite Motorcycle Cluster Demo
/****************************************************************************** ** ** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Quick Ultralite module. ** ** $QT_BEGIN_LICENSE:COMM$ ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see http://www.qt.io/terms-conditions. For further ** information use the contact form at http://www.qt.io/contact-us. ** ** $QT_END_LICENSE$ ** ******************************************************************************/#include "simulation/normaldrivestate.h" #include "simulation/drivetrain.h" #include "MotorCluster/TellTalesModel.h" #include "MotorCluster/MainModel.h" #include "MotorCluster/NavigationModel.h" using namespace MotorCluster; namespace { const uint8_t StateUpdatePeriod = 100; const uint16_t ExtraTimeToFinishState = 1000; const uint16_t LongExtraTimeToFinishState = 3000; MainModel &mainModel = MainModel::instance(); NavigationModel &navigationModel = NavigationModel::instance(); TellTalesModel &tellTalesModel = TellTalesModel::instance(); static Simulation::Drivetrain::Config drivetrainConfig = {17000, // float maxRpm; 0, // float minRpm; 14000, // float shiftUpAtRpm; 5500, // float shiftDownAtRpm; 207.3f, // float tireCircumference; // cm for 225/45/R18 12.f, // float diffRatio; 7, // int gearNum; {10000.f, 2.97f, 2.07f, 1.43f, 1.00f, 0.84f, 0.56f}}; Simulation::Drivetrain drivetrain(drivetrainConfig); template<class T, class U> void updateIfChanged(T &modelElement, const U &newValue) { if (modelElement.value() != newValue) { modelElement.setValue(newValue); } } } // namespace namespace Simulation { NormalDriveState::NormalDriveState(StateId nextState) : _step(Step_Start) , _timeToFinishStepWhenTargetSpeedWasMet(0) , _wasSpeedToFinishStepMet(true) , _nextState(nextState) {} void NormalDriveState::onEnter(const StateId &, const Layer &layer, Machine &sm) { _step = Step_Start; drivetrain.reset(); updateModel(); mainModel.rpmAnimationTime.setValue(500); setNavigation(NavigationModel::Navigating, NavigationModel::LeftTurn, 0.55f); sm.requestUpdate(StateUpdatePeriod, true, layer); } void NormalDriveState::onLeave(const StateId &, const Layer &layer, Machine &sm) { sm.dismissUpdate(layer); tellTalesModel.engineFailure.setValue(false); tellTalesModel.engineOil.setValue(false); tellTalesModel.battery.setValue(false); tellTalesModel.highBeamsActive.setValue(false); setNavigation(NavigationModel::Hidden, NavigationModel::RightTurn, 7.2f); } void NormalDriveState::onUpdate(const uint32_t tick, const Layer &layer, Machine &sm) { if (_timeToFinishStepWhenTargetSpeedWasMet <= 0 && _wasSpeedToFinishStepMet) { moveToNextStep(layer, sm); } else if (_wasSpeedToFinishStepMet) { _timeToFinishStepWhenTargetSpeedWasMet -= tick; } else if (drivetrain.isTargetSpeedReached()) { _wasSpeedToFinishStepMet = true; } calculateDriveData(tick); updateModel(); } void NormalDriveState::moveToNextStep(const Layer &layer, Machine &sm) { _step = static_cast<Step>(_step + 1); _wasSpeedToFinishStepMet = false; _timeToFinishStepWhenTargetSpeedWasMet = ExtraTimeToFinishState; switch (_step) { case Step_GoingOut: setSpeedTarget(60.f); setFuelTarget(27.f, 0.02f); break; case Step_FirstCorner: setSpeedTarget(30.f); break; case Step_FirstStright: mainModel.isDayMode.setValue(mainModel.isDayMode.value() ? false : true); setSpeedTarget(70.f); break; case Step_SecondCorner: setSpeedTarget(40.f); _timeToFinishStepWhenTargetSpeedWasMet = LongExtraTimeToFinishState; mainModel.leftTurnSignal.setValue(true); break; case Step_BeginnigOfLongStright: setSpeedTarget(200.f); setFuelTarget(25.f, 0.3f); setNavigation(NavigationModel::Navigating, NavigationModel::RightTurn, 2.7f); mainModel.leftTurnSignal.setValue(false); break; case Step_OilProblems: setSpeedTarget(210.f); _timeToFinishStepWhenTargetSpeedWasMet = LongExtraTimeToFinishState; tellTalesModel.engineOil.setValue(true); break; case Step_SlowingDownToPetrolStation: setSpeedTarget(110.f); setFuelTarget(2.f, 0.3f); break; case Step_TurningToPetrolStation: setSpeedTarget(20.f); _timeToFinishStepWhenTargetSpeedWasMet = LongExtraTimeToFinishState; mainModel.rightTurnSignal.setValue(true); break; case Step_PetrolStation: setSpeedTarget(0.f, false); mainModel.rightTurnSignal.setValue(false); setNavigation(NavigationModel::Paused, NavigationModel::TwoStright, 0.f); break; case Step_FillingTheTank: drivetrain.forceNeutraulGear(true); setFuelTarget(80.f, 5.f); _timeToFinishStepWhenTargetSpeedWasMet = LongExtraTimeToFinishState; mainModel.rightTurnSignal.setValue(false); tellTalesModel.engineOil.setValue(false); break; case Step_ShowStatistics: mainModel.showStatistics.setValue(true); setNavigation(NavigationModel::Paused, NavigationModel::TwoStright, 0.f); _timeToFinishStepWhenTargetSpeedWasMet = LongExtraTimeToFinishState; break; case Step_TurnOffNavigation: setNavigation(NavigationModel::Off, NavigationModel::TwoStright, 0.f); _timeToFinishStepWhenTargetSpeedWasMet = LongExtraTimeToFinishState; break; case Step_TypeDestination: mainModel.showKeyboard.setValue(true); _timeToFinishStepWhenTargetSpeedWasMet = LongExtraTimeToFinishState * 2; break; case Step_backToDriveMode: mainModel.showKeyboard.setValue(false); mainModel.showStatistics.setValue(false); _timeToFinishStepWhenTargetSpeedWasMet = LongExtraTimeToFinishState; setNavigation(NavigationModel::Navigating, NavigationModel::RightTurn, 42.f); break; case Step_LeavingPetrolStation: drivetrain.forceNeutraulGear(false); setSpeedTarget(110.f); setFuelTarget(80.f, .0f); tellTalesModel.highBeamsActive.setValue(true); break; case Step_SecondStright: setSpeedTarget(280.f); break; case Step_BatteryProblems: tellTalesModel.battery.setValue(true); break; case Step_EngineProblems: tellTalesModel.engineFailure.setValue(true); break; case Step_EndOfSecondStright: mainModel.rightTurnSignal.setValue(true); mainModel.leftTurnSignal.setValue(true); setSpeedTarget(200.f); setFuelTarget(20.f, .15f); break; case Step_MoveToNextState: mainModel.rightTurnSignal.setValue(false); mainModel.leftTurnSignal.setValue(false); sm.changeState(_nextState, layer, 10); break; default: break; } } void NormalDriveState::updateModel() { const Drivetrain::DriveData &data = drivetrain.getDriveData(); updateIfChanged(mainModel.rpm, std::max(data.rpm - data.rpm % 1000, 1000)); updateIfChanged(mainModel.speedValue, data.speed); updateIfChanged(mainModel.gear, data.gear); updateIfChanged(mainModel.fuelLevel, int(data.fuelLevel)); updateIfChanged(mainModel.odoValue, int(data.odometer)); updateIfChanged(mainModel.tripValue, int(data.tripDistance)); updateIfChanged(navigationModel.distanceToTarget, int(data.distanceToTarget * 1000)); } void NormalDriveState::calculateDriveData(const uint32_t tick) { drivetrain.update(tick); } void NormalDriveState::setSpeedTarget(const int targetSpeed, const bool withRandomAccChanges) { drivetrain.setSpeedTarget(targetSpeed, withRandomAccChanges); } void NormalDriveState::setFuelTarget(const float fuelTarget, const float fuelSpeed) { drivetrain.setFuelTarget(fuelTarget, fuelSpeed); } void NormalDriveState::setDistanceToTarget(const float distance) { drivetrain.setDistanceToTarget(distance); } void NormalDriveState::setNavigation(const NavigationModel::NaviState state, const NavigationModel::ArrowsState arrowsConfiguration, const float distance) { updateIfChanged(navigationModel.naviState, state); updateIfChanged(navigationModel.arrowsState, arrowsConfiguration); setDistanceToTarget(distance); } } // namespace Simulation