void AppStage_ComputeTrackerPoses::renderUI() { const float k_panel_width = 300.f; const char *k_window_title = "Compute Tracker Poses"; const ImGuiWindowFlags window_flags = ImGuiWindowFlags_ShowBorders | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoCollapse; switch (m_menuState) { case eMenuState::inactive: break; case eMenuState::pendingControllerListRequest: case eMenuState::pendingControllerStartRequest: case eMenuState::pendingTrackerListRequest: case eMenuState::pendingTrackerStartRequest: { ImGui::SetNextWindowPos(ImVec2(ImGui::GetIO().DisplaySize.x / 2.f - k_panel_width / 2.f, 20.f)); ImGui::SetNextWindowSize(ImVec2(k_panel_width, 80)); ImGui::Begin(k_window_title, nullptr, window_flags); ImGui::Text("Pending device initialization..."); if (ImGui::Button("Return to Tracker Settings")) { request_exit_to_app_stage(AppStage_TrackerSettings::APP_STAGE_NAME); } ImGui::End(); } break; case eMenuState::failedControllerListRequest: case eMenuState::failedControllerStartRequest: case eMenuState::failedTrackerListRequest: case eMenuState::failedTrackerStartRequest: { ImGui::SetNextWindowPosCenter(); ImGui::SetNextWindowSize(ImVec2(k_panel_width, 180)); ImGui::Begin(k_window_title, nullptr, window_flags); switch (m_menuState) { case eMenuState::failedControllerListRequest: ImGui::Text("Failed controller list retrieval!"); break; case eMenuState::failedControllerStartRequest: ImGui::Text("Failed controller stream start!"); break; case eMenuState::failedTrackerListRequest: ImGui::Text("Failed tracker list retrieval!"); break; case eMenuState::failedTrackerStartRequest: ImGui::Text("Failed tracker stream start!"); break; } if (ImGui::Button("Ok")) { request_exit_to_app_stage(AppStage_TrackerSettings::APP_STAGE_NAME); } if (ImGui::Button("Return to Main Menu")) { request_exit_to_app_stage(AppStage_MainMenu::APP_STAGE_NAME); } ImGui::End(); } break; case eMenuState::verifyTrackers: { ImGui::SetNextWindowPos(ImVec2(ImGui::GetIO().DisplaySize.x / 2.f - 500.f / 2.f, 20.f)); ImGui::SetNextWindowSize(ImVec2(500.f, (m_trackerViews.size() > 0) ? 150.f : 100.f)); ImGui::Begin(k_window_title, nullptr, window_flags); ImGui::Text("Verify that your tracking cameras can see the tracking origin"); ImGui::Separator(); if (m_trackerViews.size() > 1) { ImGui::Text("Tracker #%d", m_renderTrackerIndex + 1); if (ImGui::Button("Previous Tracker")) { go_previous_tracker(); } ImGui::SameLine(); if (ImGui::Button("Next Tracker")) { go_next_tracker(); } } if (ImGui::Button("Looks Good!")) { setState(eMenuState::calibrateWithMat); } if (ImGui::Button("Hmm... Something is wrong.")) { request_exit_to_app_stage(AppStage_TrackerSettings::APP_STAGE_NAME); } ImGui::End(); } break; case eMenuState::calibrateWithMat: { m_pCalibrateWithMat->renderUI(); } break; case eMenuState::testTracking: { ImGui::SetNextWindowPos(ImVec2(20.f, 20.f)); ImGui::SetNextWindowSize(ImVec2(250.f, 260.f)); ImGui::Begin("Test Tracking", nullptr, window_flags); // display per tracker UI for (t_tracker_state_map_iterator iter = m_trackerViews.begin(); iter != m_trackerViews.end(); ++iter) { const ClientTrackerView *trackerView = iter->second.trackerView; ImGui::PushItemWidth(125.f); if (does_tracker_see_any_controller(trackerView)) { ImGui::Text("Tracker #%d: OK", trackerView->getTrackerId()); } else { ImGui::Text("Tracker #%d: FAIL", trackerView->getTrackerId()); } ImGui::PopItemWidth(); ImGui::SameLine(); ImGui::PushItemWidth(100.f); ImGui::PushID(trackerView->getTrackerId()); if (ImGui::Button("Tracker Video")) { m_renderTrackerIter = iter; setState(eMenuState::showTrackerVideo); } ImGui::PopID(); ImGui::PopItemWidth(); } ImGui::Separator(); if (!m_bSkipCalibration) { ImGui::Text("Calibration Complete"); if (ImGui::Button("Redo Calibration")) { setState(eMenuState::verifyTrackers); } } if (ImGui::Button("Exit")) { m_app->setAppStage(AppStage_TrackerSettings::APP_STAGE_NAME); } ImGui::End(); } break; case eMenuState::showTrackerVideo: { ImGui::SetNextWindowPos(ImVec2(20.f, 20.f)); ImGui::SetNextWindowSize(ImVec2(200, 100)); ImGui::Begin("Tracker Video Feed", nullptr, window_flags); ImGui::Text("Tracker ID: #%d", m_renderTrackerIter->second.trackerView->getTrackerId()); if (ImGui::Button("Return")) { setState(eMenuState::testTracking); } ImGui::End(); } break; case eMenuState::calibrateStepFailed: { ImGui::SetNextWindowPosCenter(); ImGui::SetNextWindowSize(ImVec2(k_panel_width, 130)); ImGui::Begin(k_window_title, nullptr, window_flags); ImGui::Text("Calibration Failed"); if (ImGui::Button("Restart Calibration")) { setState(eMenuState::verifyTrackers); } if (ImGui::Button("Cancel")) { m_app->setAppStage(AppStage_TrackerSettings::APP_STAGE_NAME); } ImGui::End(); } break; default: assert(0 && "unreachable"); } }
void AppStage_TestRumble::renderUI() { const float k_panel_width = 500; const char *k_window_title = "Controller Settings"; const ImGuiWindowFlags window_flags = ImGuiWindowFlags_ShowBorders | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoCollapse; switch (m_menuState) { case eMenuState::waitingForStreamStartResponse: { ImGui::SetNextWindowPosCenter(); ImGui::SetNextWindowSize(ImVec2(k_panel_width, 130)); ImGui::Begin(k_window_title, nullptr, window_flags); ImGui::Text("Waiting for controller stream to start..."); ImGui::End(); } break; case eMenuState::failedStreamStart: { ImGui::SetNextWindowPosCenter(); ImGui::SetNextWindowSize(ImVec2(k_panel_width, 130)); ImGui::Begin(k_window_title, nullptr, window_flags); ImGui::Text("Failed to start controller stream!"); if (ImGui::Button("Ok")) { request_exit_to_app_stage(AppStage_ControllerSettings::APP_STAGE_NAME); } ImGui::SameLine(); if (ImGui::Button("Return to Main Menu")) { request_exit_to_app_stage(AppStage_MainMenu::APP_STAGE_NAME); } ImGui::End(); } break; case eMenuState::idle: { ImGui::SetNextWindowPosCenter(); ImGui::SetNextWindowSize(ImVec2(k_panel_width, 130)); ImGui::Begin(k_window_title, nullptr, window_flags); ImGui::Text("Press trigger to test rumble"); if (ImGui::Button("Return to Controller Settings")) { request_exit_to_app_stage(AppStage_ControllerSettings::APP_STAGE_NAME); } if (ImGui::Button("Return to Main Menu")) { request_exit_to_app_stage(AppStage_MainMenu::APP_STAGE_NAME); } ImGui::End(); } break; default: assert(0 && "unreachable"); } }
void AppStage_ComputeTrackerPoses::renderUI() { const float k_panel_width = 300.f; const char *k_window_title = "Compute Tracker Poses"; const ImGuiWindowFlags window_flags = ImGuiWindowFlags_ShowBorders | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoCollapse; switch (m_menuState) { case eMenuState::inactive: break; case eMenuState::pendingControllerListRequest: case eMenuState::pendingControllerStartRequest: case eMenuState::pendingTrackerListRequest: case eMenuState::pendingTrackerStartRequest: { ImGui::SetNextWindowPos(ImVec2(ImGui::GetIO().DisplaySize.x / 2.f - k_panel_width / 2.f, 20.f)); ImGui::SetNextWindowSize(ImVec2(k_panel_width, 80)); ImGui::Begin(k_window_title, nullptr, window_flags); ImGui::Text("Pending device initialization..."); if (ImGui::Button("Return to Tracker Settings")) { request_exit_to_app_stage(AppStage_TrackerSettings::APP_STAGE_NAME); } ImGui::End(); } break; case eMenuState::failedControllerListRequest: case eMenuState::failedControllerStartRequest: case eMenuState::failedTrackerListRequest: case eMenuState::failedTrackerStartRequest: { ImGui::SetNextWindowPosCenter(); ImGui::SetNextWindowSize(ImVec2(k_panel_width, 180)); ImGui::Begin(k_window_title, nullptr, window_flags); switch (m_menuState) { case eMenuState::failedControllerListRequest: ImGui::Text("Failed controller list retrieval!"); break; case eMenuState::failedControllerStartRequest: ImGui::Text("Failed controller stream start!"); break; case eMenuState::failedTrackerListRequest: ImGui::Text("Failed tracker list retrieval!"); break; case eMenuState::failedTrackerStartRequest: ImGui::Text("Failed tracker stream start!"); break; } if (ImGui::Button("Ok")) { request_exit_to_app_stage(AppStage_TrackerSettings::APP_STAGE_NAME); } if (ImGui::Button("Return to Main Menu")) { request_exit_to_app_stage(AppStage_MainMenu::APP_STAGE_NAME); } ImGui::End(); } break; case eMenuState::verifyHMD: { ImGui::SetNextWindowPosCenter(); ImGui::SetNextWindowSize(ImVec2(k_panel_width, 180)); ImGui::Begin(k_window_title, nullptr, window_flags); if (m_hmdView != nullptr) { ImGui::Text("Verify that your HMD is tracking correctly"); ImGui::Separator(); if (ImGui::Button("Looks Good!")) { setState(eMenuState::verifyTrackers); } if (ImGui::Button("Hmm... Something is wrong.")) { request_exit_to_app_stage(AppStage_HMDSettings::APP_STAGE_NAME); } } ImGui::End(); } break; case eMenuState::verifyTrackers: { // const int trackerCount = static_cast<int>(m_trackerViews.size()); ImGui::SetNextWindowPos(ImVec2(ImGui::GetIO().DisplaySize.x / 2.f - 500.f / 2.f, 20.f)); ImGui::SetNextWindowSize(ImVec2(500.f, (m_trackerViews.size() > 0) ? 150.f : 100.f)); ImGui::Begin(k_window_title, nullptr, window_flags); ImGui::Text("Verify that your tracking cameras can see the tracking origin"); ImGui::Separator(); if (m_trackerViews.size() > 1) { ImGui::Text("Tracker #%d", m_renderTrackerIndex + 1); if (ImGui::Button("Previous Tracker")) { go_previous_tracker(); } ImGui::SameLine(); if (ImGui::Button("Next Tracker")) { go_next_tracker(); } } if (ImGui::Button("Looks Good!")) { setState(eMenuState::selectCalibrationType); } if (ImGui::Button("Hmm... Something is wrong.")) { request_exit_to_app_stage(AppStage_TrackerSettings::APP_STAGE_NAME); } ImGui::End(); } break; case eMenuState::selectCalibrationType: { ImGui::SetNextWindowPosCenter(); ImGui::SetNextWindowSize(ImVec2(k_panel_width, 130)); ImGui::Begin(k_window_title, nullptr, window_flags); ImGui::Text("Select a camera pose estimation method"); if (m_hmdView != nullptr && ImGui::Button("Attach PSMove To HMD")) { setState(eMenuState::calibrateWithHMD); } if (ImGui::Button("Use Calibration Mat")) { setState(eMenuState::calibrateWithMat); } if (ImGui::Button("Cancel")) { m_app->setAppStage(AppStage_TrackerSettings::APP_STAGE_NAME); } ImGui::End(); } break; case eMenuState::calibrateWithHMD: { m_pCalibrateWithHMD->renderUI(); } break; case eMenuState::calibrateWithMat: { m_pCalibrateWithMat->renderUI(); } break; case eMenuState::testTracking: { ImGui::SetNextWindowPos(ImVec2(ImGui::GetIO().DisplaySize.x / 2.f - k_panel_width / 2.f, 20.f)); ImGui::SetNextWindowSize(ImVec2(k_panel_width, 130)); ImGui::Begin(k_window_title, nullptr, window_flags); ImGui::Text("Calibration Complete"); if (ImGui::Button("Redo Calibration")) { setState(eMenuState::selectCalibrationType); } if (ImGui::Button("Exit")) { m_app->setAppStage(AppStage_TrackerSettings::APP_STAGE_NAME); } ImGui::End(); } break; case eMenuState::calibrateStepFailed: { ImGui::SetNextWindowPosCenter(); ImGui::SetNextWindowSize(ImVec2(k_panel_width, 130)); ImGui::Begin(k_window_title, nullptr, window_flags); ImGui::Text("Calibration Failed"); if (ImGui::Button("Restart Calibration")) { setState(eMenuState::selectCalibrationType); } if (ImGui::Button("Cancel")) { m_app->setAppStage(AppStage_TrackerSettings::APP_STAGE_NAME); } ImGui::End(); } break; default: assert(0 && "unreachable"); } }
void AppStage_MagnetometerCalibration::renderUI() { const float k_panel_width= 500; const char *k_window_title= "Controller Settings"; const ImGuiWindowFlags window_flags = ImGuiWindowFlags_ShowBorders | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoCollapse; switch (m_menuState) { case eCalibrationMenuState::waitingForStreamStartResponse: { ImGui::SetNextWindowPosCenter(); ImGui::SetNextWindowSize(ImVec2(k_panel_width, 130)); ImGui::Begin(k_window_title, nullptr, window_flags); ImGui::Text("Waiting for controller stream to start..."); ImGui::End(); } break; case eCalibrationMenuState::failedStreamStart: { ImGui::SetNextWindowPosCenter(); ImGui::SetNextWindowSize(ImVec2(k_panel_width, 130)); ImGui::Begin(k_window_title, nullptr, window_flags); ImGui::Text("Failed to start controller stream!"); if (ImGui::Button("Ok")) { request_exit_to_app_stage(AppStage_ControllerSettings::APP_STAGE_NAME); } ImGui::SameLine(); if (ImGui::Button("Return to Main Menu")) { request_exit_to_app_stage(AppStage_MainMenu::APP_STAGE_NAME); } ImGui::End(); } break; case eCalibrationMenuState::failedBadCalibration: { ImGui::SetNextWindowPosCenter(); ImGui::SetNextWindowSize(ImVec2(k_panel_width, 130)); ImGui::Begin(k_window_title, nullptr, window_flags); ImGui::TextWrapped( "Bad controller hardware calibration!\n" \ "Try un-pairing and re-pairing the controller."); if (ImGui::Button("Ok")) { request_exit_to_app_stage(AppStage_ControllerSettings::APP_STAGE_NAME); } ImGui::SameLine(); if (ImGui::Button("Return to Main Menu")) { request_exit_to_app_stage(AppStage_MainMenu::APP_STAGE_NAME); } ImGui::End(); } break; case eCalibrationMenuState::measureBExtents: { { ImGui::SetNextWindowPos(ImVec2(ImGui::GetIO().DisplaySize.x / 2.f - k_panel_width / 2.f, 20.f)); ImGui::SetNextWindowSize(ImVec2(k_panel_width, 130)); ImGui::Begin(k_window_title, nullptr, window_flags); if (m_sampleCount < k_max_magnetometer_samples) { ImGui::TextWrapped( "Calibrating Controller ID #%d\n" \ "[Step 1 of 2: Measuring extents of the magnetometer]\n" \ "Rotate the controller in all directions.", m_controllerView->GetControllerID()); } else { ImGui::TextWrapped( "Calibrating Controller ID #%d\n" \ "[Step 1 of 2: Measuring extents of the magnetometer - Complete!]\n" \ "Press OK to continue", m_controllerView->GetControllerID()); } if (m_samplePercentage < 100) { ImGui::ProgressBar(static_cast<float>(m_samplePercentage) / 100.f, ImVec2(250, 20)); if ((m_samplePercentage > 60) && ImGui::Button("Force Accept")) { m_controllerView->GetPSMoveViewMutable().SetLEDOverride(0, 0, 0); m_menuState = waitForGravityAlignment; } ImGui::SameLine(); } else { if (ImGui::Button("Ok")) { m_controllerView->GetPSMoveViewMutable().SetLEDOverride(0, 0, 0); m_menuState = waitForGravityAlignment; } ImGui::SameLine(); } if (ImGui::Button("Cancel")) { request_exit_to_app_stage(AppStage_ControllerSettings::APP_STAGE_NAME); } ImGui::End(); } { ImGui::SetNextWindowPos(ImVec2(10.f, 450.f)); ImGui::SetNextWindowSize(ImVec2(170.f, 80.f)); ImGui::Begin("Ellipse Fitting Mode", nullptr, window_flags); if (ImGui::RadioButton("Bounds Fitting", &m_ellipseFitMethod, _ellipse_fit_method_box)) { // Refit to a box eigen_alignment_fit_bounding_box_ellipsoid( m_alignedSamples->magnetometerEigenSamples, m_sampleCount, m_sampleFitEllipsoid); } if (ImGui::RadioButton("Min Volume Fitting", &m_ellipseFitMethod, _ellipse_fit_method_min_volume)) { // Re-fit using min bounds eigen_alignment_fit_min_volume_ellipsoid( m_alignedSamples->magnetometerEigenSamples, m_sampleCount, 0.0001f, m_sampleFitEllipsoid); } ImGui::End(); } } break; case eCalibrationMenuState::waitForGravityAlignment: { ImGui::SetNextWindowPos(ImVec2(ImGui::GetIO().DisplaySize.x/2.f - k_panel_width/2.f, 20.f)); ImGui::SetNextWindowSize(ImVec2(k_panel_width, 200)); ImGui::Begin(k_window_title, nullptr, window_flags); ImGui::TextWrapped( "[Step 2 of 2: Measuring reference magnetic field direction]\n" \ "Stand the controller on a level surface with the Move button facing you.\n" \ "This will be the default orientation of the move controller.\n" \ "Measurement will start once the controller is aligned with gravity and stable."); if (m_bIsStable) { std::chrono::time_point<std::chrono::high_resolution_clock> now= std::chrono::high_resolution_clock::now(); std::chrono::duration<double, std::milli> stableDuration = now - m_stableStartTime; float fraction = static_cast<float>(stableDuration.count() / k_stabilize_wait_time_ms); ImGui::ProgressBar(fraction, ImVec2(250, 20)); ImGui::Spacing(); } else { ImGui::Text("Move Destabilized! Waiting for stabilization.."); } if (ImGui::Button("Cancel")) { request_exit_to_app_stage(AppStage_ControllerSettings::APP_STAGE_NAME); } ImGui::End(); } break; case eCalibrationMenuState::measureBDirection: { ImGui::SetNextWindowPos(ImVec2(ImGui::GetIO().DisplaySize.x/2.f - k_panel_width/2.f, 20.f)); ImGui::SetNextWindowSize(ImVec2(k_panel_width, 200)); ImGui::Begin(k_window_title, nullptr, window_flags); ImGui::TextWrapped( "[Step 2 of 2: Measuring reference magnetic field direction]\n" \ "Stand the controller on a level surface with the Move button facing you.\n" "This will be the default orientation of the move controller.\n" "Measurement will start once the controller is aligned with gravity and stable."); ImGui::ProgressBar( static_cast<float>(m_identityPoseSampleCount) / static_cast<float>(k_desired_magnetometer_sample_count), ImVec2(250, 20)); ImGui::Spacing(); if (ImGui::Button("Cancel")) { request_exit_to_app_stage(AppStage_ControllerSettings::APP_STAGE_NAME); } ImGui::End(); } break; case eCalibrationMenuState::waitForSetCalibrationResponse: { ImGui::SetNextWindowPosCenter(); ImGui::SetNextWindowSize(ImVec2(k_panel_width, 130)); ImGui::Begin(k_window_title, nullptr, window_flags); ImGui::Text("Sending final calibration to server..."); ImGui::End(); } break; case eCalibrationMenuState::failedSetCalibration: { ImGui::SetNextWindowPosCenter(); ImGui::SetNextWindowSize(ImVec2(k_panel_width, 130)); ImGui::Begin(k_window_title, nullptr, window_flags); ImGui::Text("Failed to set calibration!"); if (ImGui::Button("Ok")) { request_exit_to_app_stage(AppStage_ControllerSettings::APP_STAGE_NAME); } ImGui::SameLine(); if (ImGui::Button("Return to Main Menu")) { request_exit_to_app_stage(AppStage_MainMenu::APP_STAGE_NAME); } ImGui::End(); } break; case eCalibrationMenuState::complete: { ImGui::SetNextWindowPos(ImVec2(ImGui::GetIO().DisplaySize.x / 2.f - k_panel_width / 2.f, 20.f)); ImGui::SetNextWindowSize(ImVec2(k_panel_width, 80)); ImGui::Begin(k_window_title, nullptr, window_flags); if (m_bBypassCalibration) { ImGui::Text("Testing Calibration of Controller ID #%d", m_controllerView->GetControllerID()); } else { ImGui::Text("Calibration of Controller ID #%d complete!", m_controllerView->GetControllerID()); } if (ImGui::Button("Ok")) { request_exit_to_app_stage(AppStage_ControllerSettings::APP_STAGE_NAME); } ImGui::SameLine(); if (ImGui::Button("Return to Main Menu")) { request_exit_to_app_stage(AppStage_MainMenu::APP_STAGE_NAME); } ImGui::End(); } break; case eCalibrationMenuState::pendingExit: { ImGui::SetNextWindowPosCenter(); ImGui::SetNextWindowSize(ImVec2(k_panel_width, 130)); ImGui::Begin(k_window_title, nullptr, window_flags); ImGui::Text("Waiting for controller stream to stop..."); ImGui::End(); } break; default: assert(0 && "unreachable"); } }
void AppStage_GyroscopeCalibration::renderUI() { const float k_panel_width = 500; const char *k_window_title = "Gyroscope Calibration"; const ImGuiWindowFlags window_flags = ImGuiWindowFlags_ShowBorders | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoCollapse; switch (m_menuState) { case eCalibrationMenuState::pendingTrackingSpaceSettings: case eCalibrationMenuState::waitingForStreamStartResponse: { ImGui::SetNextWindowPosCenter(); ImGui::SetNextWindowSize(ImVec2(k_panel_width, 130)); ImGui::Begin(k_window_title, nullptr, window_flags); ImGui::Text("Waiting for server response..."); ImGui::End(); } break; case eCalibrationMenuState::failedStreamStart: case eCalibrationMenuState::failedTrackingSpaceSettings: { ImGui::SetNextWindowPosCenter(); ImGui::SetNextWindowSize(ImVec2(k_panel_width, 130)); ImGui::Begin(k_window_title, nullptr, window_flags); ImGui::Text("Failed server request!"); if (ImGui::Button("Ok")) { request_exit_to_app_stage(AppStage_ControllerSettings::APP_STAGE_NAME); } ImGui::SameLine(); if (ImGui::Button("Return to Main Menu")) { request_exit_to_app_stage(AppStage_MainMenu::APP_STAGE_NAME); } ImGui::End(); } break; case eCalibrationMenuState::waitForStable: { ImGui::SetNextWindowPos(ImVec2(ImGui::GetIO().DisplaySize.x / 2.f - k_panel_width / 2.f, 20.f)); ImGui::SetNextWindowSize(ImVec2(k_panel_width, 140)); ImGui::Begin(k_window_title, nullptr, window_flags); ImGui::TextWrapped( "[Step 1 of 2: Measuring gyroscope drift and bias]\n" \ "Set the controller down on a level surface.\n" \ "Measurement will start once the controller is aligned with gravity and stable."); if (m_bIsStable || m_bForceControllerStable) { std::chrono::time_point<std::chrono::high_resolution_clock> now= std::chrono::high_resolution_clock::now(); std::chrono::duration<double, std::milli> stableDuration = now - m_stableStartTime; float fraction = static_cast<float>(stableDuration.count() / k_stabilize_wait_time_ms); ImGui::ProgressBar(fraction, ImVec2(250, 20)); ImGui::Spacing(); } else { ImGui::Text("Controller Destabilized! Waiting for stabilization.."); } if (ImGui::Button("Trust me, it's stable")) { m_bForceControllerStable= true; } ImGui::SameLine(); if (ImGui::Button("Cancel")) { request_exit_to_app_stage(AppStage_ControllerSettings::APP_STAGE_NAME); } ImGui::End(); } break; case eCalibrationMenuState::measureBiasAndDrift: { ImGui::SetNextWindowPos(ImVec2(ImGui::GetIO().DisplaySize.x / 2.f - k_panel_width / 2.f, 20.f)); ImGui::SetNextWindowSize(ImVec2(k_panel_width, 130)); ImGui::Begin(k_window_title, nullptr, window_flags); std::chrono::time_point<std::chrono::high_resolution_clock> now= std::chrono::high_resolution_clock::now(); std::chrono::duration<double, std::milli> stableDuration = now - m_gyroNoiseSamples->sampleStartTime; float timeFraction = static_cast<float>(stableDuration.count() / k_desired_drift_sampling_time); const float sampleFraction = static_cast<float>(m_gyroNoiseSamples->sample_count) / static_cast<float>(k_desired_noise_sample_count); ImGui::TextWrapped( "[Step 1 of 2: Measuring gyroscope drift and bias]\n" \ "Sampling Gyroscope..."); ImGui::ProgressBar(fminf(sampleFraction, timeFraction), ImVec2(250, 20)); if (ImGui::Button("Cancel")) { request_exit_to_app_stage(AppStage_ControllerSettings::APP_STAGE_NAME); } ImGui::End(); } break; case eCalibrationMenuState::measureComplete: { ImGui::SetNextWindowPos(ImVec2(ImGui::GetIO().DisplaySize.x / 2.f - k_panel_width / 2.f, 20.f)); ImGui::SetNextWindowSize(ImVec2(k_panel_width, 130)); ImGui::Begin(k_window_title, nullptr, window_flags); ImGui::TextWrapped( "Sampling complete.\n" \ "Press OK to continue or Redo to recalibration."); if (ImGui::Button("Ok")) { PSM_SetControllerLEDOverrideColor(m_controllerView->ControllerID, 0, 0, 0); setState(eCalibrationMenuState::test); } ImGui::SameLine(); if (ImGui::Button("Redo")) { m_gyroNoiseSamples->clear(); setState(eCalibrationMenuState::waitForStable); } ImGui::SameLine(); if (ImGui::Button("Cancel")) { request_exit_to_app_stage(AppStage_ControllerSettings::APP_STAGE_NAME); } ImGui::End(); } break; case eCalibrationMenuState::test: { ImGui::SetNextWindowPos(ImVec2(ImGui::GetIO().DisplaySize.x / 2.f - k_panel_width / 2.f, 20.f)); ImGui::SetNextWindowSize(ImVec2(k_panel_width, 140)); ImGui::Begin("Test Orientation", nullptr, window_flags); if (m_bBypassCalibration) { ImGui::Text("Testing Calibration of Controller ID #%d", m_controllerView->ControllerID); } else { ImGui::Text("Calibration of Controller ID #%d complete!", m_controllerView->ControllerID); } PSMQuatf controllerQuat; if (PSM_GetControllerOrientation(m_controllerView->ControllerID, &controllerQuat) == PSMResult_Success) { const Eigen::Quaternionf eigen_quat = psm_quatf_to_eigen_quaternionf(controllerQuat); const Eigen::EulerAnglesf euler_angles = eigen_quaternionf_to_euler_angles(eigen_quat); ImGui::Text("Pitch(x): %.2f, Yaw(y): %.2f, Roll(z): %.2f", m_lastCalibratedGyroscope.x * k_radians_to_degreees, m_lastCalibratedGyroscope.y * k_radians_to_degreees, m_lastCalibratedGyroscope.z * k_radians_to_degreees); ImGui::Text("Attitude: %.2f, Heading: %.2f, Bank: %.2f", euler_angles.get_attitude_degrees(), euler_angles.get_heading_degrees(), euler_angles.get_bank_degrees()); } if (m_controllerView->ControllerType == PSMController_DualShock4) { ImGui::TextWrapped( "[Press the Options button with controller pointed straight forward\n" \ "to recenter the controller]"); } else if (m_controllerView->ControllerType == PSMController_Move) { ImGui::TextWrapped( "[Hold the Select button with controller pointed forward\n" \ "to recenter the controller]"); } if (ImGui::Button("Ok")) { request_exit_to_app_stage(AppStage_ControllerSettings::APP_STAGE_NAME); } ImGui::SameLine(); if (ImGui::Button("Return to Main Menu")) { request_exit_to_app_stage(AppStage_MainMenu::APP_STAGE_NAME); } ImGui::End(); } break; default: assert(0 && "unreachable"); } }