Works with T-Beam Exercise 25_motioncal

This commit is contained in:
jlpoole 2026-04-26 08:41:59 -07:00
commit 9c410dae0c
7 changed files with 744 additions and 54 deletions

111
gui.cpp
View file

@ -4,6 +4,17 @@
wxString port_name;
static bool show_calibration_confirmed = false;
static bool calibration_saved = false;
static int valid_mag_point_count(void)
{
int i, count=0;
for (i=0; i < MAGBUFFSIZE; i++) {
if (magcal.valid[i]) count++;
}
return count;
}
wxBEGIN_EVENT_TABLE(MyCanvas, wxGLCanvas)
@ -90,7 +101,7 @@ MyFrame::MyFrame(wxWindow *parent, wxWindowID id, const wxString &title,
menuBar = new wxMenuBar;
menu = new wxMenu;
menu->Append(ID_SENDCAL_MENU, wxT("Send Calibration"));
menu->Append(ID_SENDCAL_MENU, wxT("Save Calibration"));
m_sendcal_menu = menu;
m_sendcal_menu->Enable(ID_SENDCAL_MENU, false);
menu->Append(wxID_EXIT, wxT("Quit"));
@ -115,12 +126,13 @@ MyFrame::MyFrame(wxWindow *parent, wxWindowID id, const wxString &title,
vsizer = new wxBoxSizer(wxVERTICAL);
leftsizer->Add(vsizer, 0, wxALL, 8);
leftsizer->SetMinSize(wxSize(170, -1));
text = new wxStaticText(panel, wxID_ANY, "Port");
vsizer->Add(text, 0, wxTOP|wxBOTTOM, 4);
m_port_list = new wxComboBox(panel, ID_PORTLIST, "",
wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_READONLY);
wxDefaultPosition, wxSize(140, -1), 0, NULL, wxCB_READONLY);
m_port_list->SetMinSize(wxSize(140, -1));
m_port_list->Append("(none)");
m_port_list->Append(SAMPLE_PORT_NAME); // never seen, only for initial size
m_port_list->SetSelection(0);
vsizer->Add(m_port_list, 1, wxEXPAND, 0);
@ -130,7 +142,7 @@ MyFrame::MyFrame(wxWindow *parent, wxWindowID id, const wxString &title,
m_button_clear = new wxButton(panel, ID_CLEAR_BUTTON, "Clear");
m_button_clear->Enable(false);
vsizer->Add(m_button_clear, 1, wxEXPAND, 0);
m_button_sendcal = new wxButton(panel, ID_SENDCAL_BUTTON, "Send Cal");
m_button_sendcal = new wxButton(panel, ID_SENDCAL_BUTTON, "Save Cal");
vsizer->Add(m_button_sendcal, 1, wxEXPAND, 0);
m_button_sendcal->Enable(false);
vsizer->AddSpacer(16);
@ -240,7 +252,7 @@ MyFrame::MyFrame(wxWindow *parent, wxWindowID id, const wxString &title,
raw_data_reset();
//open_port(PORT);
m_timer = new wxTimer(this, ID_TIMER);
m_timer->Start(14, wxTIMER_CONTINUOUS);
m_timer->Start(33, wxTIMER_CONTINUOUS);
}
void MyFrame::OnTimer(wxTimerEvent &event)
@ -248,42 +260,48 @@ void MyFrame::OnTimer(wxTimerEvent &event)
static int firstrun=1;
float gaps, variance, wobble, fiterror;
char buf[32];
int i, j;
int i, j, bytes_read, saveable;
//printf("OnTimer\n");
if (port_is_open()) {
read_serial_data();
bytes_read = read_serial_data();
if (firstrun && m_canvas->IsShown()) {
//int h, w;
//m_canvas->GetSize(&w, &h);
//printf("Canvas initial size = %d, %d\n", w, h);
firstrun = 0;
}
m_canvas->Refresh();
gaps = quality_surface_gap_error();
variance = quality_magnitude_variance_error();
wobble = quality_wobble_error();
fiterror = quality_spherical_fit_error();
if (gaps < 15.0f && variance < 4.5f && wobble < 4.0f && fiterror < 5.0f) {
if (!m_sendcal_menu->IsEnabled(ID_SENDCAL_MENU) || !m_button_sendcal->IsEnabled()) {
m_sendcal_menu->Enable(ID_SENDCAL_MENU, true);
m_button_sendcal->Enable(true);
if (bytes_read > 0) {
m_canvas->Refresh(false);
}
gaps = quality_surface_gap_error();
variance = quality_magnitude_variance_error();
wobble = quality_wobble_error();
fiterror = quality_spherical_fit_error();
saveable = (magcal.ValidMagCal > 0 &&
valid_mag_point_count() >= 120 &&
fiterror < 20.0f);
if (m_sendcal_menu->IsEnabled(ID_SENDCAL_MENU) != saveable) {
m_sendcal_menu->Enable(ID_SENDCAL_MENU, saveable);
}
if (m_button_sendcal->IsEnabled() != saveable) {
m_button_sendcal->Enable(saveable);
}
if (!saveable) {
calibration_saved = false;
m_confirm_icon->SetBitmap(MyBitmap("checkemptygray.png"));
} else if (calibration_saved) {
m_confirm_icon->SetBitmap(MyBitmap("checkgreen.png"));
} else {
m_confirm_icon->SetBitmap(MyBitmap("checkempty.png"));
}
} else if (gaps > 20.0f && variance > 5.0f && wobble > 5.0f && fiterror > 6.0f) {
if (m_sendcal_menu->IsEnabled(ID_SENDCAL_MENU) || m_button_sendcal->IsEnabled()) {
m_sendcal_menu->Enable(ID_SENDCAL_MENU, false);
m_button_sendcal->Enable(false);
m_confirm_icon->SetBitmap(MyBitmap("checkemptygray.png"));
}
}
snprintf(buf, sizeof(buf), "%.1f%%", quality_surface_gap_error());
m_err_coverage->SetLabelText(buf);
snprintf(buf, sizeof(buf), "%.1f%%", quality_magnitude_variance_error());
m_err_variance->SetLabelText(buf);
snprintf(buf, sizeof(buf), "%.1f%%", quality_wobble_error());
m_err_wobble->SetLabelText(buf);
snprintf(buf, sizeof(buf), "%.1f%%", quality_spherical_fit_error());
snprintf(buf, sizeof(buf), "%.1f%%", gaps);
m_err_coverage->SetLabelText(buf);
snprintf(buf, sizeof(buf), "%.1f%%", variance);
m_err_variance->SetLabelText(buf);
snprintf(buf, sizeof(buf), "%.1f%%", wobble);
m_err_wobble->SetLabelText(buf);
snprintf(buf, sizeof(buf), "%.1f%%", fiterror);
m_err_fit->SetLabelText(buf);
for (i=0; i < 3; i++) {
snprintf(buf, sizeof(buf), "%.2f", magcal.V[i]);
@ -311,7 +329,8 @@ void MyFrame::OnTimer(wxTimerEvent &event)
m_sendcal_menu->Enable(ID_SENDCAL_MENU, false);
m_button_clear->Enable(false);
m_button_sendcal->Enable(false);
m_confirm_icon->SetBitmap(MyBitmap("checkemptygray.png"));
m_confirm_icon->SetBitmap(MyBitmap("checkemptygray.png"));
calibration_saved = false;
m_port_list->Clear();
m_port_list->Append("(none)");
m_port_list->SetSelection(0);
@ -328,21 +347,23 @@ void MyFrame::OnClear(wxCommandEvent &event)
{
//printf("OnClear\n");
raw_data_reset();
calibration_saved = false;
m_confirm_icon->SetBitmap(MyBitmap("checkemptygray.png"));
}
void MyFrame::OnSendCal(wxCommandEvent &event)
{
/*printf("OnSendCal\n");
printf("Magnetic Calibration: (%.1f%% fit error)\n", magcal.FitError);
printf(" %7.2f %6.3f %6.3f %6.3f\n",
magcal.V[0], magcal.invW[0][0], magcal.invW[0][1], magcal.invW[0][2]);
printf(" %7.2f %6.3f %6.3f %6.3f\n",
magcal.V[1], magcal.invW[1][0], magcal.invW[1][1], magcal.invW[1][2]);
printf(" %7.2f %6.3f %6.3f %6.3f\n",
magcal.V[2], magcal.invW[2][0], magcal.invW[2][1], magcal.invW[2][2]);
*/
m_confirm_icon->SetBitmap(MyBitmap("checkempty.png"));
send_calibration();
char filename[128];
if (save_calibration(filename, sizeof(filename))) {
calibration_saved = true;
m_confirm_icon->SetBitmap(MyBitmap("checkgreen.png"));
fprintf(stderr, "MotionCal saved calibration to %s\n", filename);
} else {
calibration_saved = false;
m_confirm_icon->SetBitmap(MyBitmap("checkemptygray.png"));
fprintf(stderr, "MotionCal failed to save calibration\n");
}
}
void calibration_confirmed(void)
@ -392,6 +413,7 @@ void MyFrame::OnPortMenu(wxCommandEvent &event)
wxString name = m_port_menu->FindItem(id)->GetItemLabelText();
close_port();
calibration_saved = false;
//printf("OnPortMenu, id = %d, name = %s\n", id, (const char *)name);
port_name = name;
m_port_list->Clear();
@ -410,6 +432,7 @@ void MyFrame::OnPortList(wxCommandEvent& event)
wxString name = m_port_list->GetString(selected);
//printf("OnPortList, %s\n", (const char *)name);
close_port();
calibration_saved = false;
port_name = name;
if (name == "(none)") return;
raw_data_reset();
@ -472,7 +495,3 @@ int MyApp::OnExit()
{
return 0;
}