Compare commits
10 commits
5997e62410
...
c24740cd8f
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c24740cd8f | ||
|
|
3e24361d18 | ||
|
|
a68ad5a3c3 | ||
|
|
8ee5e0bf55 | ||
|
|
dabaaece7d | ||
|
|
f8f279563f | ||
|
|
d579c0dcf5 | ||
|
|
447bd9e429 | ||
|
|
a3a4b7e504 | ||
|
|
1a6a6f48ee |
15 changed files with 525 additions and 147 deletions
36
Makefile
36
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,33 +42,42 @@ 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
|
||||
|
||||
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 $@
|
||||
|
||||
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
|
||||
|
||||
images.cpp: $(IMGS) png2c.pl
|
||||
perl png2c.pl $(IMGS) > images.cpp
|
||||
|
||||
MotionCal.app: MotionCal Info.plist icon.icns
|
||||
mkdir -p $@/Contents/MacOS
|
||||
|
|
@ -86,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
|
||||
|
|
|
|||
BIN
checkempty.png
Normal file
BIN
checkempty.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 953 B |
BIN
checkemptygray.png
Normal file
BIN
checkemptygray.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 943 B |
BIN
checkgreen.png
Normal file
BIN
checkgreen.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.1 KiB |
277
gui.cpp
277
gui.cpp
|
|
@ -2,10 +2,8 @@
|
|||
#include "imuread.h"
|
||||
|
||||
|
||||
|
||||
wxMenu *port_menu;
|
||||
wxMenu *sendcal_menu;
|
||||
wxString port_name;
|
||||
static bool show_calibration_confirmed = false;
|
||||
|
||||
|
||||
wxBEGIN_EVENT_TABLE(MyCanvas, wxGLCanvas)
|
||||
|
|
@ -49,9 +47,10 @@ void MyCanvas::OnPaint( wxPaintEvent& WXUNUSED(event) )
|
|||
|
||||
void MyCanvas::InitGL()
|
||||
{
|
||||
//printf("Init\n");
|
||||
SetCurrent(*m_glRC);
|
||||
visualize_init();
|
||||
wxSizeEvent e = wxSizeEvent(GetSize());
|
||||
OnSize(e);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -61,144 +60,179 @@ 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_RANGE(9000, 9999, MyFrame::OnPortMenu)
|
||||
EVT_MENU_OPEN(MyFrame::OnShowMenu)
|
||||
EVT_COMBOBOX(ID_PORTLIST, MyFrame::OnPortList)
|
||||
EVT_COMBOBOX_DROPDOWN(ID_PORTLIST, MyFrame::OnShowPortList)
|
||||
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 )
|
||||
{
|
||||
wxPanel *panel;
|
||||
wxMenuBar *menuBar;
|
||||
wxMenu *menu;
|
||||
wxSizer *topsizer;
|
||||
wxSizer *leftsizer, *middlesizer, *rightsizer;
|
||||
wxSizer *hsizer, *vsizer, *calsizer;
|
||||
wxStaticText *text;
|
||||
//wxMenuItem *item;
|
||||
int i, j;
|
||||
|
||||
topsizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
panel = new wxPanel(this);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
topsizer->Add(rightsizer, 0, wxALL | wxEXPAND | wxALIGN_TOP, 5);
|
||||
|
||||
vsizer = new wxBoxSizer(wxVERTICAL);
|
||||
leftsizer->Add(vsizer, 0, wxALL, 8);
|
||||
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);
|
||||
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);
|
||||
|
||||
vsizer->AddSpacer(8);
|
||||
text = new wxStaticText(panel, wxID_ANY, "Actions");
|
||||
vsizer->Add(text, 0, wxTOP|wxBOTTOM, 4);
|
||||
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");
|
||||
vsizer->Add(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);
|
||||
|
||||
text = new wxStaticText(this, wxID_ANY, "");
|
||||
text = new wxStaticText(panel, wxID_ANY, "");
|
||||
text->SetLabelMarkup("<small><i>Ideal calibration is a perfectly centered sphere</i></small>");
|
||||
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("<small>Calibration should be performed\n<b>after</b> final installation. Presence\nof magnets and ferrous metals\ncan alter magnetic calibration.\nMechanical stress during\nassembly can alter accelerometer\nand gyroscope calibration.</small>");
|
||||
//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();
|
||||
|
||||
|
|
@ -211,6 +245,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;
|
||||
|
|
@ -218,15 +253,29 @@ 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();
|
||||
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);
|
||||
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) {
|
||||
sendcal_menu->Enable(ID_SENDCAL, 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);
|
||||
|
|
@ -257,13 +306,33 @@ void MyFrame::OnTimer(wxTimerEvent &event)
|
|||
m_gyro[i]->SetLabelText(buf);
|
||||
}
|
||||
} else {
|
||||
sendcal_menu->Enable(ID_SENDCAL, 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_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)
|
||||
{
|
||||
//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]);
|
||||
|
|
@ -271,23 +340,85 @@ 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]);
|
||||
*/
|
||||
m_confirm_icon->SetBitmap(MyBitmap("checkempty.png"));
|
||||
send_calibration();
|
||||
}
|
||||
|
||||
void MyFrame::OnPort(wxCommandEvent &event)
|
||||
void calibration_confirmed(void)
|
||||
{
|
||||
show_calibration_confirmed = true;
|
||||
}
|
||||
|
||||
|
||||
void MyFrame::OnShowMenu(wxMenuEvent &event)
|
||||
{
|
||||
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)");
|
||||
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++) {
|
||||
menu->AppendRadioItem(9001 + i, list[i]);
|
||||
if (isopen && port_name.IsSameAs(list[i])) {
|
||||
menu->Check(9001 + i, true);
|
||||
}
|
||||
}
|
||||
menu->UpdateUI();
|
||||
}
|
||||
|
||||
void MyFrame::OnShowPortList(wxCommandEvent& event)
|
||||
{
|
||||
//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::OnPortMenu(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("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)
|
||||
{
|
||||
|
|
@ -296,7 +427,7 @@ void MyFrame::OnAbout(wxCommandEvent &event)
|
|||
"Paul Stoffregen <paul@pjrc.com>\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();
|
||||
}
|
||||
|
|
@ -313,48 +444,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)
|
||||
|
|
|
|||
43
gui.h
43
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
|
||||
{
|
||||
|
|
@ -61,9 +63,6 @@ public:
|
|||
const wxSize &size = wxDefaultSize,
|
||||
long style = wxDEFAULT_FRAME_STYLE);
|
||||
~MyFrame(void);
|
||||
void InitGL();
|
||||
void OnPort(wxCommandEvent &event);
|
||||
void OnSendCal(wxCommandEvent &event);
|
||||
private:
|
||||
wxStaticText *m_err_coverage;
|
||||
wxStaticText *m_err_variance;
|
||||
|
|
@ -78,20 +77,24 @@ private:
|
|||
|
||||
MyCanvas *m_canvas;
|
||||
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;
|
||||
void OnSendCal(wxCommandEvent &event);
|
||||
void OnClear(wxCommandEvent &event);
|
||||
void OnShowMenu(wxMenuEvent &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);
|
||||
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
|
||||
{
|
||||
|
|
@ -106,5 +109,17 @@ 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."
|
||||
#elif defined(WINDOWS)
|
||||
#define SAMPLE_PORT_NAME "COM22:."
|
||||
#elif defined(MACOSX)
|
||||
#define SAMPLE_PORT_NAME "/dev/cu.usbmodem2457891..."
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
|||
64
imuread.c
64
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);
|
||||
|
|
@ -38,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();
|
||||
|
|
|
|||
|
|
@ -15,8 +15,8 @@
|
|||
#if defined(LINUX)
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glu.h>
|
||||
#include <GL/gl.h> // sudo apt install mesa-common-dev
|
||||
#include <GL/glu.h> // sudo apt install libglu1-mesa-dev freeglut3-dev
|
||||
#elif defined(WINDOWS)
|
||||
#include <windows.h>
|
||||
#include <GL/gl.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);
|
||||
|
|
|
|||
2
magcal.c
2
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) {
|
||||
|
|
|
|||
95
png2c.pl
Executable file
95
png2c.pl
Executable file
|
|
@ -0,0 +1,95 @@
|
|||
#! /usr/bin/perl
|
||||
|
||||
binmode IN, ":bytes";
|
||||
$file = $ARGV[0];
|
||||
|
||||
print "#include <wx/bitmap.h>\n";
|
||||
print "#include <wx/image.h>\n";
|
||||
print "#include <wx/mstream.h>\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 <<EOT;
|
||||
wxBitmap MyBitmap(size_t index)
|
||||
{
|
||||
if (index >= $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
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
91
rawdata.c
91
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;
|
||||
|
|
@ -25,7 +28,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;
|
||||
|
|
@ -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)
|
||||
|
|
@ -186,10 +233,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;
|
||||
|
|
@ -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]);
|
||||
|
|
|
|||
|
|
@ -1 +1,2 @@
|
|||
MotionCal ICON "icon.ico"
|
||||
#include "wx/msw/wx.rc"
|
||||
26
serialdata.c
26
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;
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -622,7 +638,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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
30
visualize.c
30
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,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue