From 1a6a6f48ee8674f23d54492b53576535f7c2e07f Mon Sep 17 00:00:00 2001 From: PaulStoffregen Date: Sat, 2 Apr 2016 17:12:53 -0700 Subject: [PATCH 01/10] Add more GUI controls (not functional yet...) --- gui.cpp | 151 ++++++++++++++++++++++++++++++++++---------------------- gui.h | 24 +++++---- 2 files changed, 105 insertions(+), 70 deletions(-) diff --git a/gui.cpp b/gui.cpp index f471fb3..e327f51 100644 --- a/gui.cpp +++ b/gui.cpp @@ -2,9 +2,6 @@ #include "imuread.h" - -wxMenu *port_menu; -wxMenu *sendcal_menu; wxString port_name; @@ -61,14 +58,19 @@ void MyCanvas::InitGL() BEGIN_EVENT_TABLE(MyFrame,wxFrame) EVT_MENU(wxID_ABOUT, MyFrame::OnAbout) EVT_MENU(wxID_EXIT, MyFrame::OnQuit) - EVT_MENU(ID_SENDCAL, MyFrame::OnSendCal) + EVT_MENU(ID_SENDCAL_MENU, MyFrame::OnSendCal) + EVT_BUTTON(ID_CLEAR_BUTTON, MyFrame::OnClear) + EVT_BUTTON(ID_SENDCAL_BUTTON, MyFrame::OnSendCal) EVT_TIMER(ID_TIMER, MyFrame::OnTimer) EVT_MENU_RANGE(9000, 9999, MyFrame::OnPort) - EVT_MENU_OPEN(MyMenu::OnShowPortList) - EVT_MENU_HIGHLIGHT(-1, MyMenu::OnHighlight) + EVT_MENU_OPEN(MyFrame::OnShowMenu) + EVT_ACTIVATE(MyFrame::OnActivate) + //EVT_LEFT_DOWN(MyFrame::OnMouse) + EVT_CHOICE(ID_PORTLIST, MyFrame::OnSelect) END_EVENT_TABLE() + MyFrame::MyFrame(wxWindow *parent, wxWindowID id, const wxString &title, const wxPoint &position, const wxSize& size, long style) : wxFrame( parent, id, title, position, size, style ) @@ -77,23 +79,21 @@ MyFrame::MyFrame(wxWindow *parent, wxWindowID id, const wxString &title, wxMenu *menu; wxSizer *hsizer, *vsizer, *calsizer; wxStaticText *text; - //wxMenuItem *item; int i, j; menuBar = new wxMenuBar; menu = new wxMenu; - menu->Append(ID_SENDCAL, wxT("Send Calibration")); - sendcal_menu = menu; - sendcal_menu->Enable(ID_SENDCAL, false); + menu->Append(ID_SENDCAL_MENU, wxT("Send Calibration")); + m_sendcal_menu = menu; + m_sendcal_menu->Enable(ID_SENDCAL_MENU, false); menu->Append(wxID_EXIT, wxT("Quit")); menuBar->Append(menu, wxT("&File")); menu = new wxMenu; menuBar->Append(menu, "Port"); - port_menu = menu; + m_port_menu = menu; menu = new wxMenu; - //item = new wxMenuItem(menu, ID_ABOUT, "About"); menu->Append(wxID_ABOUT, wxT("About")); menuBar->Append(menu, wxT("&Help")); SetMenuBar(menuBar); @@ -107,6 +107,29 @@ MyFrame::MyFrame(wxWindow *parent, wxWindowID id, const wxString &title, topsizer->Add(middlesizer, 1, wxALL | wxEXPAND, 5); topsizer->Add(rightsizer, 0, wxALL | wxEXPAND | wxALIGN_TOP, 5); + + vsizer = new wxBoxSizer(wxVERTICAL); + leftsizer->Add(vsizer, 0, wxALL, 8); + text = new wxStaticText(this, wxID_ANY, "Port"); + vsizer->Add(text, 0, wxTOP|wxBOTTOM, 4); + m_port_list = new wxChoice(this, ID_PORTLIST); + m_port_list->Append("(none)"); + m_port_list->SetSelection(0); + //m_port_list->Connect((wxEventType)wxEVT_LEFT_DOWN, &MyFrame::OnMouse); + //m_port_list->Connect(wxEVT_LEFT_DOWN, &(MyFrame::OnMouse)); + //m_port_list->Bind(wxEVT_LEFT_DOWN, &(MyFrame::OnMouse)); + vsizer->Add(m_port_list, 1, wxEXPAND, 0); + + vsizer->AddSpacer(8); + text = new wxStaticText(this, wxID_ANY, "Actions"); + vsizer->Add(text, 0, wxTOP|wxBOTTOM, 4); + m_button_clear = new wxButton(this, ID_CLEAR_BUTTON, "Clear"); + m_button_clear->Enable(false); + vsizer->Add(m_button_clear, 1, wxEXPAND, 0); + m_button_sendcal = new wxButton(this, ID_SENDCAL_BUTTON, "Send Cal"); + vsizer->Add(m_button_sendcal, 1, wxEXPAND, 0); + m_button_sendcal->Enable(false); + vsizer = new wxBoxSizer(wxVERTICAL); middlesizer->Add(vsizer, 1, wxEXPAND | wxALL, 8); @@ -224,9 +247,9 @@ void MyFrame::OnTimer(wxTimerEvent &event) wobble = quality_wobble_error(); fiterror = quality_spherical_fit_error(); if (gaps < 15.0f && variance < 4.5f && wobble < 4.0f && fiterror < 5.0f) { - sendcal_menu->Enable(ID_SENDCAL, true); + m_sendcal_menu->Enable(ID_SENDCAL_MENU, true); } else if (gaps > 20.0f && variance > 5.0f && wobble > 5.0f && fiterror > 6.0f) { - sendcal_menu->Enable(ID_SENDCAL, false); + m_sendcal_menu->Enable(ID_SENDCAL_MENU, false); } snprintf(buf, sizeof(buf), "%.1f%%", quality_surface_gap_error()); m_err_coverage->SetLabelText(buf); @@ -257,10 +280,15 @@ void MyFrame::OnTimer(wxTimerEvent &event) m_gyro[i]->SetLabelText(buf); } } else { - sendcal_menu->Enable(ID_SENDCAL, false); + m_sendcal_menu->Enable(ID_SENDCAL_MENU, false); } } +void MyFrame::OnClear(wxCommandEvent &event) +{ + printf("OnClear\n"); +} + void MyFrame::OnSendCal(wxCommandEvent &event) { printf("OnSendCal\n"); @@ -274,14 +302,59 @@ void MyFrame::OnSendCal(wxCommandEvent &event) send_calibration(); } +void MyFrame::OnShowMenu(wxMenuEvent &event) +{ + wxMenu *menu; + int any=0; + int num; + + menu = event.GetMenu(); + printf("OnShow Port Menu, %s\n", (const char *)menu->GetTitle()); + if (menu != m_port_menu) return; + while (menu->GetMenuItemCount() > 0) { + menu->Delete(menu->GetMenuItems()[0]); + } + menu->AppendRadioItem(9000, " (none)"); + wxArrayString list = serial_port_list(); + num = list.GetCount(); + bool isopen = port_is_open(); + for (int i=0; i < num; i++) { + //printf("%d: port %s\n", i, (const char *)list[i]); + menu->AppendRadioItem(9001 + i, list[i]); + if (isopen && port_name.IsSameAs(list[i])) { + menu->Check(9001 + i, true); + any = 1; + } + } + if (!any) menu->Check(9000, true); + menu->UpdateUI(); +} + +void MyFrame::OnActivate(wxActivateEvent& event) +{ + if (!event.GetActive()) return; + printf("OnActivate, %s\n", "??"); +} + +void MyFrame::OnMouse(wxMouseEvent& event) +{ + printf("OnMouse\n"); + event.Skip(); +} + +void MyFrame::OnSelect(wxCommandEvent& event) +{ + printf("OnSelect, %s\n", "??"); +} + void MyFrame::OnPort(wxCommandEvent &event) { int id = event.GetId(); - wxString name = port_menu->FindItem(id)->GetItemLabelText(); + wxString name = m_port_menu->FindItem(id)->GetItemLabelText(); close_port(); - //printf("OnPort, id = %d, name = %s\n", id, (const char *)name); - sendcal_menu->Enable(ID_SENDCAL, false); + printf("OnPort, id = %d, name = %s\n", id, (const char *)name); + m_sendcal_menu->Enable(ID_SENDCAL_MENU, false); port_name = name; if (id == 9000) return; raw_data_reset(); @@ -313,48 +386,6 @@ MyFrame::~MyFrame(void) } -/*****************************************************************************/ -// Port Menu - -MyMenu::MyMenu(const wxString& title, long style) : wxMenu(title, style) -{ -} - -void MyMenu::OnShowPortList(wxMenuEvent &event) -{ - wxMenu *menu; - int any=0; - int num; - - menu = event.GetMenu(); - //printf("OnShowPortList, %s\n", (const char *)menu->GetTitle()); - if (menu != port_menu) return; - while (menu->GetMenuItemCount() > 0) { - menu->Delete(menu->GetMenuItems()[0]); - } - menu->AppendRadioItem(9000, " (none)"); - wxArrayString list = serial_port_list(); - num = list.GetCount(); - bool isopen = port_is_open(); - for (int i=0; i < num; i++) { - //printf("%d: port %s\n", i, (const char *)list[i]); - menu->AppendRadioItem(9001 + i, list[i]); - if (isopen && port_name.IsSameAs(list[i])) { - menu->Check(9001 + i, true); - any = 1; - } - } - if (!any) menu->Check(9000, true); - menu->UpdateUI(); -} - -void MyMenu::OnHighlight(wxMenuEvent &event) -{ - //printf("OnHighlight\n"); -} - - - /*****************************************************************************/ IMPLEMENT_APP(MyApp) diff --git a/gui.h b/gui.h index 2d82427..69e657f 100644 --- a/gui.h +++ b/gui.h @@ -24,8 +24,10 @@ #define ID_TIMER 10000 -#define ID_SENDCAL 10001 - +#define ID_SENDCAL_MENU 10001 +#define ID_CLEAR_BUTTON 10002 +#define ID_SENDCAL_BUTTON 10003 +#define ID_PORTLIST 10004 class MyCanvas : public wxGLCanvas { @@ -64,6 +66,7 @@ public: void InitGL(); void OnPort(wxCommandEvent &event); void OnSendCal(wxCommandEvent &event); + void OnClear(wxCommandEvent &event); private: wxStaticText *m_err_coverage; wxStaticText *m_err_variance; @@ -78,20 +81,21 @@ private: MyCanvas *m_canvas; wxTimer *m_timer; + wxButton *m_button_clear; + wxButton *m_button_sendcal; + wxMenu *m_port_menu; + wxChoice *m_port_list; + wxMenu *m_sendcal_menu; + void OnShowMenu(wxMenuEvent &event); + void OnActivate(wxActivateEvent &event); + void OnMouse(wxMouseEvent &event); void OnAbout(wxCommandEvent &event); + void OnSelect(wxCommandEvent& event); void OnQuit(wxCommandEvent &event); void OnTimer(wxTimerEvent &event); DECLARE_EVENT_TABLE() }; -class MyMenu: public wxMenu -{ -public: - MyMenu(const wxString& title = "", long style = 0); - void OnShowPortList(wxMenuEvent &event); - void OnHighlight(wxMenuEvent &event); -}; - class MyApp: public wxApp { From a3a4b7e5049779262689ed1edd70051496a85baa Mon Sep 17 00:00:00 2001 From: PaulStoffregen Date: Sun, 3 Apr 2016 07:04:18 -0700 Subject: [PATCH 02/10] Make new GUI stuff (mostly) work --- gui.cpp | 99 +++++++++++++++++++++++++++++++--------------------- gui.h | 27 ++++++++------ serialdata.c | 4 +-- 3 files changed, 79 insertions(+), 51 deletions(-) diff --git a/gui.cpp b/gui.cpp index e327f51..9f074f2 100644 --- a/gui.cpp +++ b/gui.cpp @@ -62,11 +62,10 @@ BEGIN_EVENT_TABLE(MyFrame,wxFrame) EVT_BUTTON(ID_CLEAR_BUTTON, MyFrame::OnClear) EVT_BUTTON(ID_SENDCAL_BUTTON, MyFrame::OnSendCal) EVT_TIMER(ID_TIMER, MyFrame::OnTimer) - EVT_MENU_RANGE(9000, 9999, MyFrame::OnPort) + EVT_MENU_RANGE(9000, 9999, MyFrame::OnPortMenu) EVT_MENU_OPEN(MyFrame::OnShowMenu) - EVT_ACTIVATE(MyFrame::OnActivate) - //EVT_LEFT_DOWN(MyFrame::OnMouse) - EVT_CHOICE(ID_PORTLIST, MyFrame::OnSelect) + EVT_COMBOBOX(ID_PORTLIST, MyFrame::OnPortList) + EVT_COMBOBOX_DROPDOWN(ID_PORTLIST, MyFrame::OnShowPortList) END_EVENT_TABLE() @@ -107,17 +106,15 @@ MyFrame::MyFrame(wxWindow *parent, wxWindowID id, const wxString &title, topsizer->Add(middlesizer, 1, wxALL | wxEXPAND, 5); topsizer->Add(rightsizer, 0, wxALL | wxEXPAND | wxALIGN_TOP, 5); - vsizer = new wxBoxSizer(wxVERTICAL); leftsizer->Add(vsizer, 0, wxALL, 8); text = new wxStaticText(this, wxID_ANY, "Port"); vsizer->Add(text, 0, wxTOP|wxBOTTOM, 4); - m_port_list = new wxChoice(this, ID_PORTLIST); + m_port_list = new wxComboBox(this, ID_PORTLIST, "", + wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_READONLY); m_port_list->Append("(none)"); + m_port_list->Append(SAMPLE_PORT_NAME); // never seen, only for initial size m_port_list->SetSelection(0); - //m_port_list->Connect((wxEventType)wxEVT_LEFT_DOWN, &MyFrame::OnMouse); - //m_port_list->Connect(wxEVT_LEFT_DOWN, &(MyFrame::OnMouse)); - //m_port_list->Bind(wxEVT_LEFT_DOWN, &(MyFrame::OnMouse)); vsizer->Add(m_port_list, 1, wxEXPAND, 0); vsizer->AddSpacer(8); @@ -248,8 +245,10 @@ void MyFrame::OnTimer(wxTimerEvent &event) fiterror = quality_spherical_fit_error(); if (gaps < 15.0f && variance < 4.5f && wobble < 4.0f && fiterror < 5.0f) { m_sendcal_menu->Enable(ID_SENDCAL_MENU, true); + m_button_sendcal->Enable(true); } else if (gaps > 20.0f && variance > 5.0f && wobble > 5.0f && fiterror > 6.0f) { m_sendcal_menu->Enable(ID_SENDCAL_MENU, false); + m_button_sendcal->Enable(false); } snprintf(buf, sizeof(buf), "%.1f%%", quality_surface_gap_error()); m_err_coverage->SetLabelText(buf); @@ -280,18 +279,28 @@ void MyFrame::OnTimer(wxTimerEvent &event) m_gyro[i]->SetLabelText(buf); } } else { - m_sendcal_menu->Enable(ID_SENDCAL_MENU, false); + if (!port_name.IsEmpty()) { + //printf("port has closed, updating stuff\n"); + m_sendcal_menu->Enable(ID_SENDCAL_MENU, false); + m_button_clear->Enable(false); + m_button_sendcal->Enable(false); + m_port_list->Clear(); + m_port_list->Append("(none)"); + m_port_list->SetSelection(0); + port_name = ""; + } } } void MyFrame::OnClear(wxCommandEvent &event) { - printf("OnClear\n"); + //printf("OnClear\n"); + raw_data_reset(); } void MyFrame::OnSendCal(wxCommandEvent &event) { - printf("OnSendCal\n"); + /*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]); @@ -299,68 +308,80 @@ void MyFrame::OnSendCal(wxCommandEvent &event) 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]); + */ send_calibration(); } + + void MyFrame::OnShowMenu(wxMenuEvent &event) { - wxMenu *menu; - int any=0; - int num; - - menu = event.GetMenu(); - printf("OnShow Port Menu, %s\n", (const char *)menu->GetTitle()); + wxMenu *menu = event.GetMenu(); if (menu != m_port_menu) return; + //printf("OnShow Port Menu, %s\n", (const char *)menu->GetTitle()); while (menu->GetMenuItemCount() > 0) { menu->Delete(menu->GetMenuItems()[0]); } menu->AppendRadioItem(9000, " (none)"); - wxArrayString list = serial_port_list(); - num = list.GetCount(); bool isopen = port_is_open(); + if (!isopen) menu->Check(9000, true); + wxArrayString list = serial_port_list(); + int num = list.GetCount(); for (int i=0; i < num; i++) { - //printf("%d: port %s\n", i, (const char *)list[i]); menu->AppendRadioItem(9001 + i, list[i]); if (isopen && port_name.IsSameAs(list[i])) { menu->Check(9001 + i, true); - any = 1; } } - if (!any) menu->Check(9000, true); menu->UpdateUI(); } -void MyFrame::OnActivate(wxActivateEvent& event) +void MyFrame::OnShowPortList(wxCommandEvent& event) { - if (!event.GetActive()) return; - printf("OnActivate, %s\n", "??"); + //printf("OnShowPortList\n"); + m_port_list->Clear(); + m_port_list->Append("(none)"); + wxArrayString list = serial_port_list(); + int num = list.GetCount(); + for (int i=0; i < num; i++) { + m_port_list->Append(list[i]); + } } -void MyFrame::OnMouse(wxMouseEvent& event) -{ - printf("OnMouse\n"); - event.Skip(); -} -void MyFrame::OnSelect(wxCommandEvent& event) -{ - printf("OnSelect, %s\n", "??"); -} - -void MyFrame::OnPort(wxCommandEvent &event) +void MyFrame::OnPortMenu(wxCommandEvent &event) { int id = event.GetId(); wxString name = m_port_menu->FindItem(id)->GetItemLabelText(); close_port(); - printf("OnPort, id = %d, name = %s\n", id, (const char *)name); - m_sendcal_menu->Enable(ID_SENDCAL_MENU, false); + //printf("OnPortMenu, id = %d, name = %s\n", id, (const char *)name); port_name = name; + m_port_list->Clear(); + m_port_list->Append(port_name); + m_port_list->SetSelection(0); if (id == 9000) return; raw_data_reset(); open_port((const char *)name); + m_button_clear->Enable(true); } +void MyFrame::OnPortList(wxCommandEvent& event) +{ + int selected = m_port_list->GetSelection(); + if (selected == wxNOT_FOUND) return; + wxString name = m_port_list->GetString(selected); + //printf("OnPortList, %s\n", (const char *)name); + close_port(); + port_name = name; + if (name == "(none)") return; + raw_data_reset(); + open_port((const char *)name); + m_button_clear->Enable(true); +} + + + void MyFrame::OnAbout(wxCommandEvent &event) { diff --git a/gui.h b/gui.h index 69e657f..07ab866 100644 --- a/gui.h +++ b/gui.h @@ -63,10 +63,6 @@ public: const wxSize &size = wxDefaultSize, long style = wxDEFAULT_FRAME_STYLE); ~MyFrame(void); - void InitGL(); - void OnPort(wxCommandEvent &event); - void OnSendCal(wxCommandEvent &event); - void OnClear(wxCommandEvent &event); private: wxStaticText *m_err_coverage; wxStaticText *m_err_variance; @@ -84,15 +80,17 @@ private: wxButton *m_button_clear; wxButton *m_button_sendcal; wxMenu *m_port_menu; - wxChoice *m_port_list; + wxComboBox *m_port_list; wxMenu *m_sendcal_menu; + void OnSendCal(wxCommandEvent &event); + void OnClear(wxCommandEvent &event); void OnShowMenu(wxMenuEvent &event); - void OnActivate(wxActivateEvent &event); - void OnMouse(wxMouseEvent &event); - void OnAbout(wxCommandEvent &event); - void OnSelect(wxCommandEvent& event); - void OnQuit(wxCommandEvent &event); + void OnShowPortList(wxCommandEvent &event); + void OnPortList(wxCommandEvent& event); + void OnPortMenu(wxCommandEvent &event); void OnTimer(wxTimerEvent &event); + void OnAbout(wxCommandEvent &event); + void OnQuit(wxCommandEvent &event); DECLARE_EVENT_TABLE() }; @@ -110,5 +108,14 @@ private: // portlist.cpp wxArrayString serial_port_list(); +// sample port name, for initial sizing of left panel +#if defined(LINUX) +#define SAMPLE_PORT_NAME "/dev/ttyACM5." +#elif defined(WINDOWS) +#define SAMPLE_PORT_NAME "COM22:." +#elif defined(MACOSX) +#define SAMPLE_PORT_NAME "/dev/cu.usbmodem2457891..." +#endif + #endif diff --git a/serialdata.c b/serialdata.c index faeb071..1c35dd8 100644 --- a/serialdata.c +++ b/serialdata.c @@ -75,7 +75,7 @@ static int packet_magnetic_cal(const unsigned char *data) magcal.BpFast[1][n] = y; magcal.BpFast[2][n] = z; magcal.valid[n] = 1; - printf("mag cal, n=%3d: %5d %5d %5d\n", n, x, y, z); + //printf("mag cal, n=%3d: %5d %5d %5d\n", n, x, y, z); } return 1; } @@ -340,7 +340,7 @@ static int ascii_parse(const unsigned char *data, int len) } return ret; fail: - printf("ascii FAIL\n"); + //printf("ascii FAIL\n"); ascii_state = ASCII_STATE_WORD; ascii_raw_data_count = 0; ascii_num = 0; From 447bd9e429176cad0d65b1f01c24169821f4da0d Mon Sep 17 00:00:00 2001 From: PaulStoffregen Date: Sun, 3 Apr 2016 13:32:15 -0700 Subject: [PATCH 03/10] Improve appearance, especially on Windows --- Makefile | 26 +++++++----- gui.cpp | 83 ++++++++++++++++++++++---------------- rawdata.c | 2 +- resource.rs => resource.rc | 1 + serialdata.c | 2 +- 5 files changed, 68 insertions(+), 46 deletions(-) rename resource.rs => resource.rc (52%) diff --git a/Makefile b/Makefile index 2153aaf..d9c7390 100644 --- a/Makefile +++ b/Makefile @@ -8,10 +8,11 @@ ALL = MotionCal imuread CC = gcc CXX = g++ CFLAGS = -O2 -Wall -D$(OS) +WXCONFIG = ~/wxwidgets/3.0.2.gtk2-opengl/bin/wx-config +WXFLAGS = `$(WXCONFIG) --cppflags` CXXFLAGS = $(CFLAGS) `$(WXCONFIG) --cppflags` LDFLAGS = SFLAG = -s -WXCONFIG = ~/wxwidgets/3.0.2.gtk2-opengl/bin/wx-config CLILIBS = -lglut -lGLU -lGL -lm MAKEFLAGS = --jobs=12 @@ -20,8 +21,9 @@ ALL = MotionCal.dmg CC = gcc-4.2 CXX = g++-4.2 CFLAGS = -O2 -Wall -D$(OS) -CXXFLAGS = $(CFLAGS) `$(WXCONFIG) --cppflags` WXCONFIG = ~/wxwidgets/3.0.2.mac-opengl/bin/wx-config +WXFLAGS = `$(WXCONFIG) --cppflags` +CXXFLAGS = $(CFLAGS) `$(WXCONFIG) --cppflags` SFLAG = -s CLILIBS = -lglut -lGLU -lGL -lm VERSION = 0.01 @@ -32,6 +34,7 @@ CC = /usr/bin/clang CXX = /usr/bin/clang++ CFLAGS = -O2 -Wall -DMACOSX WXCONFIG = wx-config +WXFLAGS = `$(WXCONFIG) --cppflags` CXXFLAGS = $(CFLAGS) `$(WXCONFIG) --cppflags` SFLAG = CLILIBS = -lglut -lGLU -lGL -lm @@ -39,14 +42,19 @@ VERSION = 0.01 else ifeq ($(OS), WINDOWS) ALL = MotionCal.exe -CC = i686-w64-mingw32-gcc -CXX = i686-w64-mingw32-g++ -WINDRES = i686-w64-mingw32-windres +#MINGW_TOOLCHAIN = i586-mingw32msvc +MINGW_TOOLCHAIN = i686-w64-mingw32 +CC = $(MINGW_TOOLCHAIN)-gcc +CXX = $(MINGW_TOOLCHAIN)-g++ +WINDRES = $(MINGW_TOOLCHAIN)-windres CFLAGS = -O2 -Wall -D$(OS) -CXXFLAGS = $(CFLAGS) `$(WXCONFIG) --cppflags` +WXFLAGS = `$(WXCONFIG) --cppflags` +CXXFLAGS = $(CFLAGS) $(WXFLAGS) LDFLAGS = -static -static-libgcc SFLAG = -s -WXCONFIG = ~/wxwidgets/3.0.2.mingw-opengl/bin/wx-config +#WXCONFIG = ~/wxwidgets/3.0.2.mingw-opengl-i586/bin/wx-config +#WXCONFIG = ~/wxwidgets/3.0.2.mingw-opengl/bin/wx-config +WXCONFIG = ~/wxwidgets/3.1.0.mingw-opengl/bin/wx-config CLILIBS = -lglut32 -lglu32 -lopengl32 -lm MAKEFLAGS = --jobs=12 @@ -64,8 +72,8 @@ MotionCal.exe: resource.o gui.o portlist.o $(OBJS) -pjrcwinsigntool $@ -./cp_windows.sh $@ -resource.o: resource.rs icon.ico - $(WINDRES) -o resource.o resource.rs +resource.o: resource.rc icon.ico + $(WINDRES) $(WXFLAGS) -o resource.o resource.rc MotionCal.app: MotionCal Info.plist icon.icns mkdir -p $@/Contents/MacOS diff --git a/gui.cpp b/gui.cpp index 9f074f2..037c924 100644 --- a/gui.cpp +++ b/gui.cpp @@ -46,9 +46,10 @@ void MyCanvas::OnPaint( wxPaintEvent& WXUNUSED(event) ) void MyCanvas::InitGL() { - //printf("Init\n"); SetCurrent(*m_glRC); visualize_init(); + wxSizeEvent e = wxSizeEvent(GetSize()); + OnSize(e); } @@ -74,12 +75,18 @@ MyFrame::MyFrame(wxWindow *parent, wxWindowID id, const wxString &title, const wxPoint &position, const wxSize& size, long style) : wxFrame( parent, id, title, position, size, style ) { + wxPanel *panel; wxMenuBar *menuBar; wxMenu *menu; + wxSizer *topsizer; + wxSizer *leftsizer, *middlesizer, *rightsizer; wxSizer *hsizer, *vsizer, *calsizer; wxStaticText *text; int i, j; + topsizer = new wxBoxSizer(wxHORIZONTAL); + panel = new wxPanel(this); + menuBar = new wxMenuBar; menu = new wxMenu; menu->Append(ID_SENDCAL_MENU, wxT("Send Calibration")); @@ -97,10 +104,9 @@ MyFrame::MyFrame(wxWindow *parent, wxWindowID id, const wxString &title, menuBar->Append(menu, wxT("&Help")); SetMenuBar(menuBar); - wxBoxSizer *topsizer = new wxBoxSizer(wxHORIZONTAL); - wxBoxSizer *leftsizer = new wxStaticBoxSizer(wxVERTICAL, this, "Communication"); - wxBoxSizer *middlesizer = new wxStaticBoxSizer(wxVERTICAL, this, "Magnetometer"); - wxBoxSizer *rightsizer = new wxStaticBoxSizer(wxVERTICAL, this, "Calibration"); + leftsizer = new wxStaticBoxSizer(wxVERTICAL, panel, "Communication"); + middlesizer = new wxStaticBoxSizer(wxVERTICAL, panel, "Magnetometer"); + rightsizer = new wxStaticBoxSizer(wxVERTICAL, panel, "Calibration"); topsizer->Add(leftsizer, 0, wxALL | wxEXPAND | wxALIGN_TOP, 5); topsizer->Add(middlesizer, 1, wxALL | wxEXPAND, 5); @@ -108,9 +114,9 @@ MyFrame::MyFrame(wxWindow *parent, wxWindowID id, const wxString &title, vsizer = new wxBoxSizer(wxVERTICAL); leftsizer->Add(vsizer, 0, wxALL, 8); - text = new wxStaticText(this, wxID_ANY, "Port"); + text = new wxStaticText(panel, wxID_ANY, "Port"); vsizer->Add(text, 0, wxTOP|wxBOTTOM, 4); - m_port_list = new wxComboBox(this, ID_PORTLIST, "", + m_port_list = new wxComboBox(panel, ID_PORTLIST, "", wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_READONLY); m_port_list->Append("(none)"); m_port_list->Append(SAMPLE_PORT_NAME); // never seen, only for initial size @@ -118,107 +124,107 @@ MyFrame::MyFrame(wxWindow *parent, wxWindowID id, const wxString &title, vsizer->Add(m_port_list, 1, wxEXPAND, 0); vsizer->AddSpacer(8); - text = new wxStaticText(this, wxID_ANY, "Actions"); + text = new wxStaticText(panel, wxID_ANY, "Actions"); vsizer->Add(text, 0, wxTOP|wxBOTTOM, 4); - m_button_clear = new wxButton(this, ID_CLEAR_BUTTON, "Clear"); + 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(this, ID_SENDCAL_BUTTON, "Send Cal"); + m_button_sendcal = new wxButton(panel, ID_SENDCAL_BUTTON, "Send Cal"); vsizer->Add(m_button_sendcal, 1, wxEXPAND, 0); m_button_sendcal->Enable(false); vsizer = new wxBoxSizer(wxVERTICAL); middlesizer->Add(vsizer, 1, wxEXPAND | wxALL, 8); - text = new wxStaticText(this, wxID_ANY, ""); + text = new wxStaticText(panel, wxID_ANY, ""); text->SetLabelMarkup("Ideal calibration is a perfectly centered sphere"); vsizer->Add(text, 0, wxALIGN_CENTER_HORIZONTAL, 0); int gl_attrib[20] = { WX_GL_RGBA, WX_GL_MIN_RED, 1, WX_GL_MIN_GREEN, 1, WX_GL_MIN_BLUE, 1, WX_GL_DEPTH_SIZE, 1, WX_GL_DOUBLEBUFFER, 0}; - m_canvas = new MyCanvas(this, wxID_ANY, gl_attrib); - m_canvas->SetMinSize(wxSize(400,400)); + m_canvas = new MyCanvas(panel, wxID_ANY, gl_attrib); + m_canvas->SetMinSize(wxSize(480,480)); vsizer->Add(m_canvas, 1, wxEXPAND | wxALL, 0); - hsizer = new wxGridSizer(4, 0, 15); middlesizer->Add(hsizer, 0, wxALL | wxALIGN_CENTER_HORIZONTAL, 5); vsizer = new wxBoxSizer(wxVERTICAL); hsizer->Add(vsizer, 1, wxALIGN_CENTER_HORIZONTAL); - text = new wxStaticText(this, wxID_ANY, "Gaps"); + text = new wxStaticText(panel, wxID_ANY, "Gaps"); vsizer->Add(text, 1, wxALIGN_CENTER_HORIZONTAL); - m_err_coverage = new wxStaticText(this, wxID_ANY, "100.0%"); + m_err_coverage = new wxStaticText(panel, wxID_ANY, "100.0%"); vsizer->Add(m_err_coverage, 1, wxALIGN_CENTER_HORIZONTAL); vsizer = new wxBoxSizer(wxVERTICAL); hsizer->Add(vsizer, 1, wxALIGN_CENTER_HORIZONTAL); - text = new wxStaticText(this, wxID_ANY, "Variance"); + text = new wxStaticText(panel, wxID_ANY, "Variance"); vsizer->Add(text, 1, wxALIGN_CENTER_HORIZONTAL); - m_err_variance = new wxStaticText(this, wxID_ANY, "100.0%"); + m_err_variance = new wxStaticText(panel, wxID_ANY, "100.0%"); vsizer->Add(m_err_variance, 1, wxALIGN_CENTER_HORIZONTAL); vsizer = new wxBoxSizer(wxVERTICAL); hsizer->Add(vsizer, 1, wxALIGN_CENTER_HORIZONTAL); - text = new wxStaticText(this, wxID_ANY, "Wobble"); + text = new wxStaticText(panel, wxID_ANY, "Wobble"); vsizer->Add(text, 1, wxALIGN_CENTER_HORIZONTAL); - m_err_wobble = new wxStaticText(this, wxID_ANY, "100.0%"); + m_err_wobble = new wxStaticText(panel, wxID_ANY, "100.0%"); vsizer->Add(m_err_wobble, 1, wxALIGN_CENTER_HORIZONTAL); vsizer = new wxBoxSizer(wxVERTICAL); hsizer->Add(vsizer, 1, wxALIGN_CENTER_HORIZONTAL); - text = new wxStaticText(this, wxID_ANY, "Fit Error"); + text = new wxStaticText(panel, wxID_ANY, "Fit Error"); vsizer->Add(text, 1, wxALIGN_CENTER_HORIZONTAL); - m_err_fit = new wxStaticText(this, wxID_ANY, "100.0%"); + m_err_fit = new wxStaticText(panel, wxID_ANY, "100.0%"); vsizer->Add(m_err_fit, 1, wxALIGN_CENTER_HORIZONTAL); calsizer = new wxBoxSizer(wxVERTICAL); rightsizer->Add(calsizer, 0, wxALL, 8); - text = new wxStaticText(this, wxID_ANY, "Magnetic Offset"); + text = new wxStaticText(panel, wxID_ANY, "Magnetic Offset"); calsizer->Add(text, 0, wxTOP|wxBOTTOM, 4); vsizer = new wxGridSizer(1, 0, 0); calsizer->Add(vsizer, 1, wxLEFT, 20); for (i=0; i < 3; i++) { - m_mag_offset[i] = new wxStaticText(this, wxID_ANY, "0.00"); + m_mag_offset[i] = new wxStaticText(panel, wxID_ANY, "0.00"); vsizer->Add(m_mag_offset[i], 1); } - text = new wxStaticText(this, wxID_ANY, "Magnetic Mapping"); + text = new wxStaticText(panel, wxID_ANY, "Magnetic Mapping"); calsizer->Add(text, 0, wxTOP|wxBOTTOM, 4); vsizer = new wxGridSizer(3, 0, 12); calsizer->Add(vsizer, 1, wxLEFT, 20); for (i=0; i < 3; i++) { for (j=0; j < 3; j++) { - m_mag_mapping[i][j] = new wxStaticText(this, wxID_ANY, + m_mag_mapping[i][j] = new wxStaticText(panel, wxID_ANY, ((i == j) ? "+1.000" : "+0.000")); vsizer->Add(m_mag_mapping[i][j], 1); } } - text = new wxStaticText(this, wxID_ANY, "Magnetic Field"); + text = new wxStaticText(panel, wxID_ANY, "Magnetic Field"); calsizer->Add(text, 0, wxTOP|wxBOTTOM, 4); - m_mag_field = new wxStaticText(this, wxID_ANY, "0.00"); + m_mag_field = new wxStaticText(panel, wxID_ANY, "0.00"); calsizer->Add(m_mag_field, 0, wxLEFT, 20); - text = new wxStaticText(this, wxID_ANY, "Accelerometer"); + text = new wxStaticText(panel, wxID_ANY, "Accelerometer"); calsizer->Add(text, 0, wxTOP|wxBOTTOM, 4); vsizer = new wxGridSizer(1, 0, 0); calsizer->Add(vsizer, 1, wxLEFT, 20); for (i=0; i < 3; i++) { - m_accel[i] = new wxStaticText(this, wxID_ANY, "0.000"); + m_accel[i] = new wxStaticText(panel, wxID_ANY, "0.000"); vsizer->Add(m_accel[i], 1); } - text = new wxStaticText(this, wxID_ANY, "Gyroscope"); + text = new wxStaticText(panel, wxID_ANY, "Gyroscope"); calsizer->Add(text, 0, wxTOP|wxBOTTOM, 4); vsizer = new wxGridSizer(1, 0, 0); calsizer->Add(vsizer, 1, wxLEFT, 20); for (i=0; i < 3; i++) { - m_gyro[i] = new wxStaticText(this, wxID_ANY, "0.000"); + m_gyro[i] = new wxStaticText(panel, wxID_ANY, "0.000"); vsizer->Add(m_gyro[i], 1); } calsizer->AddSpacer(8); - text = new wxStaticText(this, wxID_ANY, ""); + text = new wxStaticText(panel, wxID_ANY, ""); text->SetLabelMarkup("Calibration should be performed\nafter final installation. Presence\nof magnets and ferrous metals\ncan alter magnetic calibration.\nMechanical stress during\nassembly can alter accelerometer\nand gyroscope calibration."); //text->Wrap(200); //calsizer->Add(text, 0, wxEXPAND | wxALIGN_CENTER_HORIZONTAL, 0); calsizer->Add(text, 0, wxALIGN_CENTER_HORIZONTAL, 0); - topsizer->SetSizeHints(this); - SetSizerAndFit(topsizer); + panel->SetSizer(topsizer); + topsizer->SetSizeHints(panel); + Fit(); Show(true); Raise(); @@ -231,6 +237,7 @@ MyFrame::MyFrame(wxWindow *parent, wxWindowID id, const wxString &title, void MyFrame::OnTimer(wxTimerEvent &event) { + static int firstrun=1; float gaps, variance, wobble, fiterror; char buf[32]; int i, j; @@ -238,6 +245,12 @@ void MyFrame::OnTimer(wxTimerEvent &event) //printf("OnTimer\n"); if (port_is_open()) { 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(); diff --git a/rawdata.c b/rawdata.c index 0547248..e230036 100644 --- a/rawdata.c +++ b/rawdata.c @@ -25,7 +25,7 @@ static int choose_discard_magcal(void) int32_t rawx, rawy, rawz; int32_t dx, dy, dz; float x, y, z; - uint64_t distsq, minsum=0xFFFFFFFFFFFFFFFF; + uint64_t distsq, minsum=0xFFFFFFFFFFFFFFFFull; static int runcount=0; int i, j, minindex=0; Point_t point; diff --git a/resource.rs b/resource.rc similarity index 52% rename from resource.rs rename to resource.rc index 6d3784b..ae193a5 100644 --- a/resource.rs +++ b/resource.rc @@ -1 +1,2 @@ MotionCal ICON "icon.ico" +#include "wx/msw/wx.rc" diff --git a/serialdata.c b/serialdata.c index 1c35dd8..0ece385 100644 --- a/serialdata.c +++ b/serialdata.c @@ -622,7 +622,7 @@ int write_serial_data(const void *ptr, int len) void close_port(void) { CloseHandle(port_handle); - port_handle = NULL; + port_handle = INVALID_HANDLE_VALUE; } From d579c0dcf5f010670d6a42fe9540a37a18269136 Mon Sep 17 00:00:00 2001 From: PaulStoffregen Date: Sun, 3 Apr 2016 14:20:27 -0700 Subject: [PATCH 04/10] Detect USB errors on Windows, fixes #3 --- serialdata.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/serialdata.c b/serialdata.c index 0ece385..bdd2695 100644 --- a/serialdata.c +++ b/serialdata.c @@ -491,6 +491,7 @@ int open_port(const char *name) len = sizeof(COMMCONFIG); if (!GetCommConfig(port_handle, &port_cfg, &len)) { CloseHandle(port_handle); + port_handle = INVALID_HANDLE_VALUE; return 0; } port_cfg.dcb.BaudRate = 115200; @@ -512,10 +513,12 @@ int open_port(const char *name) port_cfg.dcb.StopBits = ONESTOPBIT; if (!SetCommConfig(port_handle, &port_cfg, sizeof(COMMCONFIG))) { CloseHandle(port_handle); + port_handle = INVALID_HANDLE_VALUE; return 0; } if (!EscapeCommFunction(port_handle, CLRDTR | CLRRTS)) { CloseHandle(port_handle); + port_handle = INVALID_HANDLE_VALUE; return 0; } timeouts.ReadIntervalTimeout = MAXDWORD; @@ -525,10 +528,12 @@ int open_port(const char *name) timeouts.WriteTotalTimeoutConstant = 0; if (!SetCommTimeouts(port_handle, &timeouts)) { CloseHandle(port_handle); + port_handle = INVALID_HANDLE_VALUE; return 0; } if (!EscapeCommFunction(port_handle, SETDTR)) { CloseHandle(port_handle); + port_handle = INVALID_HANDLE_VALUE; return 0; } return 1; @@ -542,10 +547,17 @@ int read_serial_data(void) unsigned char buf[256]; int r; + if (port_handle == INVALID_HANDLE_VALUE) return -1; while (1) { - if (!ClearCommError(port_handle, &errmask, &st)) return -1; + if (!ClearCommError(port_handle, &errmask, &st)) { + r = -1; + break; + } //printf("Read, %d requested, %lu buffered\n", count, st.cbInQue); - if (st.cbInQue <= 0) return 0; + if (st.cbInQue <= 0) { + r = 0; + break; + } // now do a ReadFile, now that we know how much we can read // a blocking (non-overlapped) read would be simple, but win32 // is all-or-nothing on async I/O and we must have it enabled @@ -585,6 +597,10 @@ int read_serial_data(void) if (r <= 0) break; newdata(buf, r); } + if (r < 0) { + CloseHandle(port_handle); + port_handle = INVALID_HANDLE_VALUE; + } return r; } From f8f279563f9c0c7af34b00fabbf20638c4ab7982 Mon Sep 17 00:00:00 2001 From: PaulStoffregen Date: Mon, 22 Jan 2018 16:10:39 -0800 Subject: [PATCH 05/10] Fix rawdata z axis --- imuread.h | 4 ++-- rawdata.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/imuread.h b/imuread.h index 6bcae6f..5e09d77 100644 --- a/imuread.h +++ b/imuread.h @@ -15,8 +15,8 @@ #if defined(LINUX) #include #include - #include - #include + #include // sudo apt install mesa-common-dev + #include // sudo apt install libglu1-mesa-dev freeglut3-dev #elif defined(WINDOWS) #include #include diff --git a/rawdata.c b/rawdata.c index e230036..c77fec7 100644 --- a/rawdata.c +++ b/rawdata.c @@ -186,10 +186,10 @@ void raw_data(const int16_t *data) z = (float)data[2] * G_PER_COUNT; accel.GpFast[0] = x; accel.GpFast[1] = y; - accel.GpFast[2] = y; + accel.GpFast[2] = z; accel.Gp[0] += x; accel.Gp[1] += y; - accel.Gp[2] += y; + accel.Gp[2] += z; x = (float)data[3] * DEG_PER_SEC_PER_COUNT; y = (float)data[4] * DEG_PER_SEC_PER_COUNT; From dabaaece7d9ed6e291cf3994a1849f8e229d3ece Mon Sep 17 00:00:00 2001 From: PaulStoffregen Date: Mon, 22 Jan 2018 18:59:52 -0800 Subject: [PATCH 06/10] Fix use of uninitialized data in fUpdateCalibration10EIG --- magcal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/magcal.c b/magcal.c index b3496b9..3e80c4b 100644 --- a/magcal.c +++ b/magcal.c @@ -453,7 +453,7 @@ static void fUpdateCalibration10EIG(MagCalibration_t *MagCal) // sum between MINEQUATIONS to MAXEQUATIONS entries into the 10x10 product matrix matA iCount = 0; for (j = 0; j < MAGBUFFSIZE; j++) { - if (MagCal->valid[j] != -1) { + if (MagCal->valid[j]) { // use first valid magnetic buffer entry as estimate for offset // to help solution (bit counts) if (iCount == 0) { From 8ee5e0bf551337c4073ab21b640890b078d04723 Mon Sep 17 00:00:00 2001 From: PaulStoffregen Date: Tue, 23 Jan 2018 06:14:51 -0800 Subject: [PATCH 07/10] Experimental (and ultimately ineffective) fiddling with axes --- imuread.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++ visualize.c | 30 +++++++++++++++++++++++---- 2 files changed, 85 insertions(+), 4 deletions(-) diff --git a/imuread.c b/imuread.c index 68412b2..c55d2ac 100644 --- a/imuread.c +++ b/imuread.c @@ -21,8 +21,67 @@ static void glut_display_callback(void) glutSwapBuffers(); } +extern int invert_q0; +extern int invert_q1; +extern int invert_q2; +extern int invert_q3; +extern int invert_x; +extern int invert_y; +extern int invert_z; + +static void print_invert_state(void) +{ + printf("Invert: %s %s %s %s %s %s %s\n", + (invert_q0 ? "Q0" : " "), + (invert_q1 ? "Q1" : " "), + (invert_q2 ? "Q2" : " "), + (invert_q3 ? "Q3" : " "), + (invert_x ? "x'" : " "), + (invert_y ? "y'" : " "), + (invert_z ? "z'" : " ") + ); +} + + static void glut_keystroke_callback(unsigned char ch, int x, int y) { + if (ch == '0') { + invert_q0 ^= 1; + print_invert_state(); + return; + } + if (ch == '1') { + invert_q1 ^= 1; + print_invert_state(); + return; + } + if (ch == '2') { + invert_q2 ^= 1; + print_invert_state(); + return; + } + if (ch == '3') { + invert_q3 ^= 1; + print_invert_state(); + return; + } + if (ch == 'x') { + invert_x ^= 1; + print_invert_state(); + return; + } + if (ch == 'y') { + invert_y ^= 1; + print_invert_state(); + return; + } + if (ch == 'z') { + invert_z ^= 1; + print_invert_state(); + return; + } + + if (magcal.FitError > 9.0) { printf("Poor Calibration: "); printf("soft iron fit error = %.1f%%\n", magcal.FitError); diff --git a/visualize.c b/visualize.c index 1141686..7fc11ab 100644 --- a/visualize.c +++ b/visualize.c @@ -46,6 +46,14 @@ static void rotate(const Point_t *in, Point_t *out, const float *rmatrix) static GLuint spherelist; static GLuint spherelowreslist; +int invert_q0=0; +int invert_q1=0; +int invert_q2=0; +int invert_q3=1; +int invert_x=0; +int invert_y=0; +int invert_z=0; + void display_callback(void) { int i; @@ -76,11 +84,22 @@ void display_callback(void) memcpy(&orientation, ¤t_orientation, sizeof(orientation)); // TODO: this almost but doesn't perfectly seems to get the // real & screen axes in sync.... - //orientation.q0 *= -1.0f; - //orientation.q1 *= -1.0f; - //orientation.q2 *= -1.0f; - orientation.q3 *= -1.0f; + if (invert_q0) orientation.q0 *= -1.0f; + if (invert_q1) orientation.q1 *= -1.0f; + if (invert_q2) orientation.q2 *= -1.0f; + if (invert_q3) orientation.q3 *= -1.0f; quad_to_rotation(&orientation, rotation); + + //rotation[0] *= -1.0f; + //rotation[1] *= -1.0f; + //rotation[2] *= -1.0f; + //rotation[3] *= -1.0f; + //rotation[4] *= -1.0f; + //rotation[5] *= -1.0f; + //rotation[6] *= -1.0f; + //rotation[7] *= -1.0f; + //rotation[8] *= -1.0f; + for (i=0; i < MAGBUFFSIZE; i++) { if (magcal.valid[i]) { apply_calibration(magcal.BpFast[0][i], magcal.BpFast[1][i], @@ -91,6 +110,9 @@ void display_callback(void) quality_update(&point); rotate(&point, &draw, rotation); glPushMatrix(); + if (invert_x) draw.x *= -1.0f; + if (invert_y) draw.y *= -1.0f; + if (invert_z) draw.z *= -1.0f; glTranslatef( draw.x * xscale + xoff, draw.z * yscale + yoff, From a68ad5a3c3a4c7ae8ac7a91033ebe67e3ec7ccf5 Mon Sep 17 00:00:00 2001 From: PaulStoffregen Date: Tue, 23 Jan 2018 07:06:44 -0800 Subject: [PATCH 08/10] Check sent calibration with incoming cal messages --- gui.cpp | 4 +++ imuread.c | 5 ++++ imuread.h | 1 + rawdata.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++-------- 4 files changed, 83 insertions(+), 12 deletions(-) diff --git a/gui.cpp b/gui.cpp index 037c924..9afa85a 100644 --- a/gui.cpp +++ b/gui.cpp @@ -325,6 +325,10 @@ void MyFrame::OnSendCal(wxCommandEvent &event) send_calibration(); } +void calibration_confirmed(void) +{ + // TODO: show GUI indication of calibration written to EEPROM +} void MyFrame::OnShowMenu(wxMenuEvent &event) diff --git a/imuread.c b/imuread.c index c55d2ac..445afc9 100644 --- a/imuread.c +++ b/imuread.c @@ -97,6 +97,11 @@ static void glut_keystroke_callback(unsigned char ch, int x, int y) send_calibration(); } +void calibration_confirmed(void) +{ + printf("Calibration confirmed!\n"); +} + int main(int argc, char *argv[]) { raw_data_reset(); diff --git a/imuread.h b/imuread.h index 5e09d77..9be6ce1 100644 --- a/imuread.h +++ b/imuread.h @@ -69,6 +69,7 @@ extern void close_port(void); void raw_data_reset(void); void cal1_data(const float *data); void cal2_data(const float *data); +void calibration_confirmed(void); void raw_data(const int16_t *data); int send_calibration(void); void visualize_init(void); diff --git a/rawdata.c b/rawdata.c index c77fec7..caaf063 100644 --- a/rawdata.c +++ b/rawdata.c @@ -6,6 +6,9 @@ static AccelSensor_t accel; static MagSensor_t mag; static GyroSensor_t gyro; +static float cal_data_sent[19]; +static int cal_confirm_needed=0; + void raw_data_reset(void) { rawcount = OVERSAMPLE_RATIO; @@ -120,28 +123,72 @@ static void add_magcal_data(const int16_t *data) magcal.valid[i] = 1; } +static int is_float_ok(float actual, float expected) +{ + float err, maxerr; + + err = fabsf(actual - expected); + maxerr = 0.0001f + fabsf(expected) * 0.00003f; + if (err <= maxerr) return 1; + return 0; +} + void cal1_data(const float *data) { -#if 0 - int i; + int i, ok; - printf("got cal1_data:\n"); - for (i=0; i<10; i++) { - printf(" %.5f\n", data[i]); + if (cal_confirm_needed) { + #if 0 + printf("expected cal1: "); + for (i=0; i<10; i++) { + printf(" %.5f,", cal_data_sent[i]); + } + printf("\ngot cal1_data: "); + for (i=0; i<10; i++) { + printf(" %.5f,", data[i]); + } + printf("\n"); + #endif + ok = 1; + for (i=0; i<10; i++) { + if (!is_float_ok(data[i], cal_data_sent[i])) ok = 0; + } + if (ok) { + cal_confirm_needed &= ~1; // got cal1 confirm + if (cal_confirm_needed == 0) { + calibration_confirmed(); + } + } } -#endif } void cal2_data(const float *data) { -#if 0 - int i; + int i, ok; - printf("got cal2_data:\n"); - for (i=0; i<9; i++) { - printf(" %.5f\n", data[i]); + if (cal_confirm_needed) { + #if 0 + printf("expected cal2: "); + for (i=0; i<9; i++) { + printf(" %.5f,", cal_data_sent[i+10]); + } + printf("\ngot cal2_data: "); + for (i=0; i<9; i++) { + printf(" %.5f,", data[i]); + } + printf("\n"); + #endif + ok = 1; + for (i=0; i<9; i++) { + if (!is_float_ok(data[i], cal_data_sent[i+10])) ok = 0; + } + if (ok) { + cal_confirm_needed &= ~2; // got cal2 confirm + if (cal_confirm_needed == 0) { + calibration_confirmed(); + } + } } -#endif } void raw_data(const int16_t *data) @@ -267,12 +314,15 @@ int send_calibration(void) *p++ = 84; for (i=0; i < 3; i++) { p = copy_lsb_first(p, 0.0f); // accelerometer offsets + cal_data_sent[0+i] = 0.0f; } for (i=0; i < 3; i++) { p = copy_lsb_first(p, 0.0f); // gyroscope offsets + cal_data_sent[3+i] = 0.0f; } for (i=0; i < 3; i++) { p = copy_lsb_first(p, magcal.V[i]); // 12 bytes offset/hardiron + cal_data_sent[6+i] = magcal.V[i]; } p = copy_lsb_first(p, magcal.B); // field strength p = copy_lsb_first(p, magcal.invW[0][0]); //10 @@ -281,6 +331,17 @@ int send_calibration(void) p = copy_lsb_first(p, magcal.invW[0][1]); //13 p = copy_lsb_first(p, magcal.invW[0][2]); //14 p = copy_lsb_first(p, magcal.invW[1][2]); //15 + cal_data_sent[9] = magcal.B; + cal_data_sent[10] = magcal.invW[0][0]; + cal_data_sent[11] = magcal.invW[0][1]; + cal_data_sent[12] = magcal.invW[0][2]; + cal_data_sent[13] = magcal.invW[1][0]; + cal_data_sent[14] = magcal.invW[1][1]; + cal_data_sent[15] = magcal.invW[1][2]; + cal_data_sent[16] = magcal.invW[2][0]; + cal_data_sent[17] = magcal.invW[2][1]; + cal_data_sent[18] = magcal.invW[2][2]; + cal_confirm_needed = 3; crc = 0xFFFF; for (i=0; i < 66; i++) { crc = crc16(crc, buf[i]); From 3e24361d18526e9f568a1284f80b6f9c9cebe3f1 Mon Sep 17 00:00:00 2001 From: PaulStoffregen Date: Tue, 23 Jan 2018 08:47:41 -0800 Subject: [PATCH 09/10] Show calibration confirmation in GUI --- Makefile | 10 +++-- checkempty.png | Bin 0 -> 953 bytes checkemptygray.png | Bin 0 -> 943 bytes checkgreen.png | Bin 0 -> 4220 bytes gui.cpp | 32 ++++++++++++--- gui.h | 4 ++ png2c.pl | 95 +++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 132 insertions(+), 9 deletions(-) create mode 100644 checkempty.png create mode 100644 checkemptygray.png create mode 100644 checkgreen.png create mode 100755 png2c.pl diff --git a/Makefile b/Makefile index d9c7390..83a8d7a 100644 --- a/Makefile +++ b/Makefile @@ -61,13 +61,14 @@ MAKEFLAGS = --jobs=12 endif OBJS = visualize.o serialdata.o rawdata.o magcal.o matrix.o fusion.o quality.o mahony.o +IMGS = checkgreen.png checkempty.png checkemptygray.png all: $(ALL) -MotionCal: gui.o portlist.o $(OBJS) +MotionCal: gui.o portlist.o images.o $(OBJS) $(CXX) $(SFLAG) $(CFLAGS) $(LDFLAGS) -o $@ $^ `$(WXCONFIG) --libs all,opengl` -MotionCal.exe: resource.o gui.o portlist.o $(OBJS) +MotionCal.exe: resource.o gui.o portlist.o images.o $(OBJS) $(CXX) $(SFLAG) $(CFLAGS) $(LDFLAGS) -o $@ $^ `$(WXCONFIG) --libs all,opengl` -pjrcwinsigntool $@ -./cp_windows.sh $@ @@ -75,6 +76,9 @@ MotionCal.exe: resource.o gui.o portlist.o $(OBJS) resource.o: resource.rc icon.ico $(WINDRES) $(WXFLAGS) -o resource.o resource.rc +images.cpp: $(IMGS) png2c.pl + perl png2c.pl $(IMGS) > images.cpp + MotionCal.app: MotionCal Info.plist icon.icns mkdir -p $@/Contents/MacOS mkdir -p $@/Contents/Resources/English.lproj @@ -94,7 +98,7 @@ imuread: imuread.o $(OBJS) $(CC) -s $(CFLAGS) $(LDFLAGS) -o $@ $^ $(CLILIBS) clean: - rm -f gui MotionCal imuread *.o *.exe *.sign? + rm -f gui MotionCal imuread *.o *.exe *.sign? images.cpp rm -rf MotionCal.app MotionCal.dmg .DS_Store dmg_tmpdir gui.o: gui.cpp gui.h imuread.h Makefile diff --git a/checkempty.png b/checkempty.png new file mode 100644 index 0000000000000000000000000000000000000000..350179eedcd3819f308d515613156e611f88b036 GIT binary patch literal 953 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 S?41Yz0000Add(m_button_sendcal, 1, wxEXPAND, 0); m_button_sendcal->Enable(false); + vsizer->AddSpacer(16); + text = new wxStaticText(panel, wxID_ANY, "Status"); + vsizer->Add(text, 0, wxTOP|wxBOTTOM, 4); + wxImage::AddHandler(new wxPNGHandler); + //m_confirm_icon = new wxStaticBitmap(panel, ID_CONFIRM_ICON, MyBitmap("checkgreen.png")); + m_confirm_icon = new wxStaticBitmap(panel, wxID_ANY, MyBitmap("checkemptygray.png")); + vsizer->Add(m_confirm_icon, 0, wxALL | wxALIGN_CENTER_HORIZONTAL, 0); vsizer = new wxBoxSizer(wxVERTICAL); middlesizer->Add(vsizer, 1, wxEXPAND | wxALL, 8); @@ -257,11 +265,17 @@ void MyFrame::OnTimer(wxTimerEvent &event) wobble = quality_wobble_error(); fiterror = quality_spherical_fit_error(); if (gaps < 15.0f && variance < 4.5f && wobble < 4.0f && fiterror < 5.0f) { - m_sendcal_menu->Enable(ID_SENDCAL_MENU, true); - m_button_sendcal->Enable(true); + 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); + m_confirm_icon->SetBitmap(MyBitmap("checkempty.png")); + } } else if (gaps > 20.0f && variance > 5.0f && wobble > 5.0f && fiterror > 6.0f) { - m_sendcal_menu->Enable(ID_SENDCAL_MENU, false); - m_button_sendcal->Enable(false); + 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); @@ -297,12 +311,17 @@ 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_port_list->Clear(); m_port_list->Append("(none)"); m_port_list->SetSelection(0); port_name = ""; } } + if (show_calibration_confirmed) { + m_confirm_icon->SetBitmap(MyBitmap("checkgreen.png")); + show_calibration_confirmed = false; + } } void MyFrame::OnClear(wxCommandEvent &event) @@ -322,12 +341,13 @@ void MyFrame::OnSendCal(wxCommandEvent &event) 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(); } void calibration_confirmed(void) { - // TODO: show GUI indication of calibration written to EEPROM + show_calibration_confirmed = true; } @@ -407,7 +427,7 @@ void MyFrame::OnAbout(wxCommandEvent &event) "Paul Stoffregen \n" "http://www.pjrc.com/store/prop_shield.html\n" "https://github.com/PaulStoffregen/MotionCal\n\n" - "Copyright 2016, PJRC.COM, LLC.", + "Copyright 2018, PJRC.COM, LLC.", "About MotionCal", wxOK|wxICON_INFORMATION|wxCENTER); dialog.ShowModal(); } diff --git a/gui.h b/gui.h index 07ab866..64af8ac 100644 --- a/gui.h +++ b/gui.h @@ -79,6 +79,7 @@ private: wxTimer *m_timer; wxButton *m_button_clear; wxButton *m_button_sendcal; + wxStaticBitmap *m_confirm_icon; wxMenu *m_port_menu; wxComboBox *m_port_list; wxMenu *m_sendcal_menu; @@ -108,6 +109,9 @@ private: // portlist.cpp wxArrayString serial_port_list(); +// images.cpp +wxBitmap MyBitmap(const char *name); + // sample port name, for initial sizing of left panel #if defined(LINUX) #define SAMPLE_PORT_NAME "/dev/ttyACM5." diff --git a/png2c.pl b/png2c.pl new file mode 100755 index 0000000..d622546 --- /dev/null +++ b/png2c.pl @@ -0,0 +1,95 @@ +#! /usr/bin/perl + +binmode IN, ":bytes"; +$file = $ARGV[0]; + +print "#include \n"; +print "#include \n"; +print "#include \n"; +print "\n"; + +foreach $file (@ARGV) { + open(IN, $file) or die "Can't open $file: $!\n"; + $count = 0; + $len = -s $file; + $filelist[$numfiles] = $file; + $file =~ /^([-_A-Za-z0-9\/]+)/; + $name = "png_$1"; + $name =~ s/\//_/g; + $name =~ s/-/_/g; + $size[$numfiles] = $len; + $list[$numfiles++] = $name; + print "static unsigned char ${name}[$len] = \{\n"; + while (read(IN, $byte, 1) == 1) { + $n = ord($byte); + printf '0x%02X', $n; + print ',' if $count < $len - 1; + print "\n" if $count++ % 12 == 11; + } + print "\};\n"; + close(IN); +} +print "\nstatic const unsigned char *png_image_list[] = {\n"; +for ($i=0; $i<$numfiles; $i++) { + print "$list[$i]"; + print ',' if $i < $numfiles - 1; + print "\n"; +} +print "\};\n"; + +print "\nstatic const char *png_image_name[] = {\n"; +for ($i=0; $i<$numfiles; $i++) { + print "\"$filelist[$i]\""; + print ',' if $i < $numfiles - 1; + print "\n"; +} +print "\};\n"; + +print "\nstatic const unsigned int png_image_size[] = {\n"; +for ($i=0; $i<$numfiles; $i++) { + print "$size[$i]"; + print ',' if $i < $numfiles - 1; + print "\n"; +} +print "\};\n"; + +print "\nstatic wxBitmap * image_list[] = {\n"; +for ($i=0; $i<$numfiles; $i++) { + print "NULL"; + print ',' if $i < $numfiles - 1; + print "\n"; +} + +print "\};\n\n"; + +print <= $numfiles || index < 0) return wxNullBitmap; + wxBitmap *p = image_list[index]; + if (p) return *p; + wxMemoryInputStream istream(png_image_list[index], png_image_size[index]); + wxImage img(istream, wxBITMAP_TYPE_PNG); + p = new wxBitmap(img); + return *p; +} + +wxBitmap MyBitmap(const char *name) +{ + for (size_t i=0; i < $numfiles; i++) { + if (strcmp(name, png_image_name[i]) == 0) return MyBitmap(i); + } + return wxNullBitmap; +} +EOT + + + + + + + + + + + From c24740cd8f8a2ccd5f8aa06be8965ff52b7ee920 Mon Sep 17 00:00:00 2001 From: PaulStoffregen Date: Thu, 13 Feb 2020 17:31:17 -0800 Subject: [PATCH 10/10] Add link to info about quality metric algorithms --- quality.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/quality.c b/quality.c index 3a3ee85..7e44354 100644 --- a/quality.c +++ b/quality.c @@ -1,5 +1,7 @@ #include "imuread.h" +// Discussion of what these 4 quality metrics really do +// https://forum.pjrc.com/threads/59277-Motion-Sensor-Calibration-Tool-Parameter-Understanding //static int countdown=1000; //static int pr=0;