Subversion Repositories Projects

Rev

Rev 647 | Rev 649 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
584 FredericG 1
#!/usr/bin/env python
2
# -*- coding: iso-8859-15 -*-
3
# generated by wxGlade 0.6.3 on Thu Sep 24 15:46:36 2009
4
 
634 FredericG 5
#
6
# Mikrokopter VibrationTest  Rev: $Rev$
7
#
8
# Author: Frederic Goddeeris   (frederic@rc-flight.be)
9
#
10
 
586 FredericG 11
import sys
606 FredericG 12
import os
612 FredericG 13
import time
14
import thread
15
import ConfigParser
648 FredericG 16
import math
612 FredericG 17
 
584 FredericG 18
import wx
585 FredericG 19
import wx.lib
20
import wx.lib.plot
612 FredericG 21
import wx.lib.newevent
623 FredericG 22
import wx.lib.agw.speedmeter as speedmeter
584 FredericG 23
 
613 FredericG 24
import mkProto
25
 
26
 
27
 
28
CHANNEL_NAMES = ["GyroYaw", "GyroRoll", "GyroNick", "Pressure", "Batt", "AccTop", "AccRoll", "AccNick"]
615 FredericG 29
FS = 11111
623 FredericG 30
pi = 3.14
636 FredericG 31
COLOR_YELLOW = wx.Colour(255, 240, 0)
32
COLOR_BACKGROUND = wx.Colour(0x80, 0x80, 0x80)
613 FredericG 33
 
636 FredericG 34
COLORS = [wx.RED, wx.GREEN, wx.BLUE, COLOR_YELLOW, COLOR_BACKGROUND, wx.BLACK,]*2
35
 
626 FredericG 36
rootPath = ""
37
 
585 FredericG 38
# Needs Numeric or numarray or NumPy
39
try:
40
    import numpy.oldnumeric as _Numeric
41
except:
42
    try:
43
        import numarray as _Numeric  #if numarray is used it is renamed Numeric
44
    except:
45
        try:
46
            import Numeric as _Numeric
47
        except:
48
            msg= """
49
            This module requires the Numeric/numarray or NumPy module,
50
            which could not be imported.  It probably is not installed
51
            (it's not part of the standard Python distribution). See the
52
            Numeric Python site (http://numpy.scipy.org) for information on
53
            downloading source or binaries."""
54
            raise ImportError, "Numeric,numarray or NumPy not found. \n" + msg
55
 
584 FredericG 56
# begin wxGlade: extracode
57
# end wxGlade
58
 
59
 
612 FredericG 60
# This creates a new Event class and a EVT binder function
613 FredericG 61
(MeasStatusUpdateEvent, EVT_MEAS_STATUS_UPDATE) = wx.lib.newevent.NewEvent()
62
(MeasDataEvent, EVT_MEAS_DATA) = wx.lib.newevent.NewEvent()
584 FredericG 63
 
612 FredericG 64
class MeasureDialog(wx.Dialog):
65
    def __init__(self, *args, **kwds):
66
        # begin wxGlade: MeasureDialog.__init__
626 FredericG 67
        kwds["style"] = wx.CAPTION|wx.RESIZE_BORDER|wx.THICK_FRAME
612 FredericG 68
        wx.Dialog.__init__(self, *args, **kwds)
69
        self.text_ctrl_1 = wx.TextCtrl(self, -1, "", style=wx.TE_MULTILINE|wx.TE_READONLY|wx.HSCROLL)
70
        self.button = wx.Button(self, -1, "STOP")
623 FredericG 71
        self.voltageCtrl = speedmeter.SpeedMeter(self, extrastyle=speedmeter.SM_DRAW_HAND | speedmeter.SM_DRAW_PARTIAL_SECTORS |  speedmeter.SM_DRAW_MIDDLE_ICON )
72
        self.speedCtrl = speedmeter.SpeedMeter(self, extrastyle=speedmeter.SM_DRAW_HAND | speedmeter.SM_DRAW_PARTIAL_SECTORS | speedmeter.SM_DRAW_MIDDLE_TEXT | speedmeter.SM_DRAW_SECONDARY_TICKS)
626 FredericG 73
 
612 FredericG 74
        self.__set_properties()
75
        self.__do_layout()
76
 
77
        self.Bind(wx.EVT_BUTTON, self.onButton, self.button)
78
        # end wxGlade
79
 
626 FredericG 80
        self.button.SetFocus()
81
 
636 FredericG 82
 
83
 
623 FredericG 84
        # Configure Voltage Ctrl
85
        self.voltageCtrl.SetAngleRange(0,pi)
86
        intervals = range(0, 5)
87
        self.voltageCtrl.SetIntervals(intervals)
636 FredericG 88
        colours = [wx.RED, wx.GREEN, wx.GREEN, COLOR_YELLOW]
623 FredericG 89
        self.voltageCtrl.SetIntervalColours(colours)
90
        ticks = ["", "", "", "", ""]
91
        self.voltageCtrl.SetTicks(ticks)
92
        self.voltageCtrl.SetTicksColour(wx.WHITE)
636 FredericG 93
        self.voltageCtrl.SetHandColour(COLOR_YELLOW)
623 FredericG 94
 
626 FredericG 95
        icon = wx.Icon("%s/Resources/fuel.ico" % rootPath, wx.BITMAP_TYPE_ICO)
623 FredericG 96
        icon.SetWidth(24)
97
        icon.SetHeight(24)
98
 
99
        self.voltageCtrl.SetMiddleIcon(icon)
636 FredericG 100
        self.voltageCtrl.SetSpeedBackground(COLOR_BACKGROUND)
623 FredericG 101
        self.voltageCtrl.SetArcColour(wx.WHITE)
102
        self.voltageCtrl.SetSpeedValue(2)
103
 
104
 
105
        # Configure Speed Ctr;
106
        self.speedCtrl.SetAngleRange(0,pi)
107
        intervals = range(0, 261, 20)
108
        self.speedCtrl.SetIntervals(intervals)
109
 
636 FredericG 110
        colours = [COLOR_BACKGROUND]*(len(intervals)-1)
623 FredericG 111
        for i in range(5,10):
112
          colours[i] = wx.GREEN
113
        self.speedCtrl.SetIntervalColours(colours)
114
        ticks = [str(interval) for interval in intervals]
115
        self.speedCtrl.SetTicks(ticks)
116
        self.speedCtrl.SetTicksColour(wx.WHITE)
117
        self.speedCtrl.SetNumberOfSecondaryTicks(1)
118
        self.speedCtrl.SetTicksFont(wx.Font(7, wx.SWISS, wx.NORMAL, wx.NORMAL))
119
        self.speedCtrl.SetMiddleText("Speed")
120
        self.speedCtrl.SetMiddleTextColour(wx.WHITE)
121
        self.speedCtrl.SetMiddleTextFont(wx.Font(8, wx.SWISS, wx.NORMAL, wx.BOLD))
636 FredericG 122
        self.speedCtrl.SetHandColour(COLOR_YELLOW)
123
        self.speedCtrl.SetSpeedBackground(COLOR_BACKGROUND)
623 FredericG 124
        self.speedCtrl.SetArcColour(wx.WHITE)
125
        self.speedCtrl.SetSpeedValue(0)
126
 
127
 
612 FredericG 128
        self.running = True
129
        self.Bind(EVT_MEAS_STATUS_UPDATE, self.OnUpdate)
613 FredericG 130
        self.Bind(EVT_MEAS_DATA, self.OnData)
131
        # The first argument that is passed to the constructor is the parent
132
        self.app = args[0].app
133
        self.error = False
623 FredericG 134
        self.firstVoltage = True
612 FredericG 135
 
623 FredericG 136
 
612 FredericG 137
    def __set_properties(self):
138
        # begin wxGlade: MeasureDialog.__set_properties
139
        self.SetTitle("Measuring Status")
140
        self.text_ctrl_1.SetMinSize((400,300))
623 FredericG 141
        self.voltageCtrl.SetMinSize((50,-1))
142
        self.speedCtrl.SetMinSize((50,-1))
612 FredericG 143
        # end wxGlade
144
 
145
    def __do_layout(self):
146
        # begin wxGlade: MeasureDialog.__do_layout
147
        sizer_1 = wx.BoxSizer(wx.HORIZONTAL)
623 FredericG 148
        sizer_4 = wx.BoxSizer(wx.VERTICAL)
612 FredericG 149
        sizer_2 = wx.BoxSizer(wx.VERTICAL)
150
        sizer_1.Add((20, 20), 0, 0, 0)
151
        sizer_2.Add((20, 20), 0, 0, 0)
152
        sizer_2.Add(self.text_ctrl_1, 1, wx.EXPAND, 0)
153
        sizer_2.Add((20, 20), 0, 0, 0)
154
        sizer_2.Add(self.button, 0, wx.ALIGN_CENTER_HORIZONTAL, 0)
155
        sizer_2.Add((20, 20), 0, 0, 0)
156
        sizer_1.Add(sizer_2, 1, wx.EXPAND, 0)
157
        sizer_1.Add((20, 20), 0, 0, 0)
623 FredericG 158
        sizer_4.Add(self.voltageCtrl, 1, wx.EXPAND, 0)
159
        sizer_4.Add(self.speedCtrl, 1, wx.EXPAND, 0)
160
        sizer_1.Add(sizer_4, 1, wx.EXPAND, 0)
161
        sizer_1.Add((20, 20), 0, 0, 0)
612 FredericG 162
        self.SetSizer(sizer_1)
163
        sizer_1.Fit(self)
164
        self.Layout()
165
        # end wxGlade
613 FredericG 166
 
167
    def OnData(self, evt):
168
        print "Received Data"
169
        self.app.AddTest2(evt.vibTest)
623 FredericG 170
 
612 FredericG 171
    def OnUpdate(self, evt):
613 FredericG 172
        print "Status update"
612 FredericG 173
        self.running = evt.running
613 FredericG 174
        if evt.error:
175
            self.error = True;
176
            self.text_ctrl_1.WriteText("ERROR: ")
177
            self.text_ctrl_1.SetBackgroundColour("Red")
612 FredericG 178
        self.text_ctrl_1.WriteText("%s\n"%evt.msg)
179
        if (not self.running):
613 FredericG 180
            if (not self.error):
181
                self.text_ctrl_1.SetBackgroundColour("Green")
182
                self.text_ctrl_1.write(" ") # so that the background is redrawn
623 FredericG 183
            self.button.SetLabel("Close")
613 FredericG 184
 
623 FredericG 185
        if evt.speed != None:
186
            self.speedCtrl.SetSpeedValue(evt.speed)
187
 
188
        if evt.voltage != None:
189
            vmin,vmax,v = evt.voltage
190
            if self.firstVoltage:
191
                ticks = ["", "%.1f V"%vmin, "", "%.1f V"%vmax, ""]
192
                self.voltageCtrl.SetTicks(ticks)
193
                self.firstVoltage = False
194
            i = (v-vmin)/(vmax-vmin)  # 0..1
195
            i *= 2
196
            i = i+1
638 FredericG 197
            i = min(max(i,0),4)
623 FredericG 198
            self.voltageCtrl.SetSpeedValue(i)
199
 
200
 
612 FredericG 201
 
202
    def onButton(self, event): # wxGlade: MeasureDialog.<event_handler>
203
        if (not self.running):
204
            self.Destroy()
613 FredericG 205
        else:
206
            self.app.cancelMeasurement()
612 FredericG 207
 
208
# end of class MeasureDialog
209
 
210
 
607 FredericG 211
class SettingsDialog(wx.Dialog):
601 FredericG 212
    def __init__(self, *args, **kwds):
607 FredericG 213
        # begin wxGlade: SettingsDialog.__init__
214
        kwds["style"] = wx.DEFAULT_DIALOG_STYLE
215
        wx.Dialog.__init__(self, *args, **kwds)
608 FredericG 216
        self.button_5 = wx.Button(self, wx.ID_CANCEL, "")
217
        self.button_6 = wx.Button(self, wx.ID_OK, "")
601 FredericG 218
 
219
        self.__set_properties()
220
        self.__do_layout()
611 FredericG 221
 
222
        self.Bind(wx.EVT_BUTTON, self.onOK, self.button_6)
601 FredericG 223
        # end wxGlade
224
 
608 FredericG 225
        # The first argument that is passed to the constructor is the parent
611 FredericG 226
        self.settings = args[0].app.settings
608 FredericG 227
        # Add text-boxes for all settings
611 FredericG 228
        self.tb = []
229
        self.grid_sizer_2.SetRows(len(self.settings))
230
        for setting in self.settings.iteritems():
608 FredericG 231
            lb = wx.StaticText(self, -1, setting[1].descr, style=wx.ALIGN_RIGHT)
232
            tb = wx.TextCtrl(self, -1, str(setting[1].value))
233
            self.grid_sizer_2.Add(lb, 0, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL, 0)
234
            self.grid_sizer_2.Add(tb, 0, 0, 0)
611 FredericG 235
            self.tb.append(tb)
608 FredericG 236
        self.sizer_5.Fit(self)
237
        self.Layout()
238
 
601 FredericG 239
    def __set_properties(self):
607 FredericG 240
        # begin wxGlade: SettingsDialog.__set_properties
601 FredericG 241
        self.SetTitle("Settings")
242
        # end wxGlade
243
 
244
    def __do_layout(self):
607 FredericG 245
        # begin wxGlade: SettingsDialog.__do_layout
608 FredericG 246
        sizer_5 = wx.BoxSizer(wx.VERTICAL)
247
        grid_sizer_3 = wx.GridSizer(1, 2, 0, 0)
248
        sizer_6 = wx.BoxSizer(wx.HORIZONTAL)
249
        grid_sizer_2 = wx.GridSizer(1, 2, 4, 4)
250
        sizer_5.Add((20, 20), 0, 0, 0)
251
        sizer_6.Add((20, 20), 0, 0, 0)
252
        sizer_6.Add(grid_sizer_2, 0, 0, 0)
253
        sizer_6.Add((20, 20), 0, 0, 0)
254
        sizer_5.Add(sizer_6, 1, wx.EXPAND, 0)
255
        sizer_5.Add((20, 20), 0, 0, 0)
256
        grid_sizer_3.Add(self.button_5, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL, 0)
257
        grid_sizer_3.Add(self.button_6, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL, 0)
258
        sizer_5.Add(grid_sizer_3, 0, wx.EXPAND, 0)
259
        sizer_5.Add((20, 20), 0, 0, 0)
260
        self.SetSizer(sizer_5)
261
        sizer_5.Fit(self)
601 FredericG 262
        self.Layout()
263
        # end wxGlade
264
 
608 FredericG 265
        # Store some of the items, we will need them later
266
        self.grid_sizer_2 = grid_sizer_2
267
        self.sizer_5 = sizer_5
268
 
269
 
611 FredericG 270
    def onOK(self, event): # wxGlade: SettingsDialog.<event_handler>
271
        print "Updating parameters"
272
        try:
273
            i=0
274
            for setting in self.settings.iteritems():
275
              print setting[0], self.tb[i].GetValue()
276
              setting[1].set(self.tb[i].GetValue())
277
              i += 1
278
            event.Skip()
279
        except:
280
            wx.MessageBox("Invalid format for \"%s\" setting." % setting[1].descr)
281
 
607 FredericG 282
# end of class SettingsDialog
283
 
284
 
285
 
584 FredericG 286
class MainFrame(wx.Frame):
287
    def __init__(self, *args, **kwds):
288
        # begin wxGlade: MainFrame.__init__
289
        kwds["style"] = wx.DEFAULT_FRAME_STYLE
290
        wx.Frame.__init__(self, *args, **kwds)
587 FredericG 291
 
292
        # Menu Bar
293
        self.frame_1_menubar = wx.MenuBar()
294
        wxglade_tmp_menu = wx.Menu()
607 FredericG 295
        wxglade_tmp_menu.Append(101, "Settings", "", wx.ITEM_NORMAL)
616 FredericG 296
        wxglade_tmp_menu.AppendSeparator()
607 FredericG 297
        wxglade_tmp_menu.Append(150, "Exit", "", wx.ITEM_NORMAL)
639 FredericG 298
        self.frame_1_menubar.Append(wxglade_tmp_menu, "&File")
587 FredericG 299
        wxglade_tmp_menu = wx.Menu()
639 FredericG 300
        wxglade_tmp_menu.Append(301, "Delete All\tAlt+D", "", wx.ITEM_NORMAL)
301
        wxglade_tmp_menu.Append(302, "Delete Selected\tCtrl+D", "", wx.ITEM_NORMAL)
616 FredericG 302
        wxglade_tmp_menu.AppendSeparator()
639 FredericG 303
        wxglade_tmp_menu.Append(310, "Select All\tCtrl+A", "", wx.ITEM_NORMAL)
627 FredericG 304
        wxglade_tmp_menu.AppendSeparator()
639 FredericG 305
        wxglade_tmp_menu.Append(303, "Load\tCtrl+L", "", wx.ITEM_NORMAL)
306
        wxglade_tmp_menu.Append(304, "Save\tCtrl+S", "", wx.ITEM_NORMAL)
587 FredericG 307
        self.frame_1_menubar.Append(wxglade_tmp_menu, "TestSet")
308
        wxglade_tmp_menu = wx.Menu()
626 FredericG 309
        wxglade_tmp_menu.Append(401, "Flash VibTest FC software", "", wx.ITEM_NORMAL)
310
        wxglade_tmp_menu.Append(402, "Restore original FC software", "", wx.ITEM_NORMAL)
587 FredericG 311
        self.frame_1_menubar.Append(wxglade_tmp_menu, "MK")
312
        wxglade_tmp_menu = wx.Menu()
626 FredericG 313
        wxglade_tmp_menu.Append(1099, "About", "", wx.ITEM_NORMAL)
587 FredericG 314
        self.frame_1_menubar.Append(wxglade_tmp_menu, "Help")
315
        self.SetMenuBar(self.frame_1_menubar)
316
        # Menu Bar end
633 FredericG 317
        self.label_1 = wx.StaticText(self, -1, "Test Description :", style=wx.ALIGN_RIGHT)
318
        self.descrCtrl = wx.TextCtrl(self, -1, "N/A")
319
        self.label_2 = wx.StaticText(self, -1, "Channel(s) :", style=wx.ALIGN_RIGHT)
320
        self.accTopCb = wx.CheckBox(self, -1, "ACC Top")
321
        self.accRollCb = wx.CheckBox(self, -1, "ACC Roll")
322
        self.accNickCb = wx.CheckBox(self, -1, "ACC Nick")
323
        self.label_3 = wx.StaticText(self, -1, "Motor(s) :", style=wx.ALIGN_RIGHT)
324
        self.motorsCtrl = wx.TextCtrl(self, -1, "1")
325
        self.label_4 = wx.StaticText(self, -1, "Speed(s) :")
326
        self.speedCtrl = wx.TextCtrl(self, -1, "100-200:10")
327
        self.bitmap_button_1 = wx.BitmapButton(self, -1, wx.Bitmap("Resources\\Fairytale_player_play.png", wx.BITMAP_TYPE_ANY))
328
        self.static_line_1 = wx.StaticLine(self, -1)
626 FredericG 329
        self.graphCtrl = wx.lib.plot.PlotCanvas(self, size=(800,300))
600 FredericG 330
        self.label_40 = wx.StaticText(self, -1, "Graph Type ")
331
        self.graphTypeChoice = wx.Choice(self, -1, choices=["Raw Signal", "Filtered Signal", "Spectrum"])
332
        self.label_41 = wx.StaticText(self, -1, "Y Axis Range ")
643 FredericG 333
        self.yAxisChoice = wx.Choice(self, -1, choices=["25", "50", "75", "100", "200"])
627 FredericG 334
        self.copyGraphButton = wx.Button(self, -1, "Copy Graph Data")
586 FredericG 335
        self.TestListCtrl = wx.ListCtrl(self, -1, style=wx.LC_REPORT|wx.SUNKEN_BORDER)
584 FredericG 336
 
337
        self.__set_properties()
338
        self.__do_layout()
587 FredericG 339
 
607 FredericG 340
        self.Bind(wx.EVT_MENU, self.OnSettings, id=101)
626 FredericG 341
        self.Bind(wx.EVT_MENU, self.onExit, id=150)
607 FredericG 342
        self.Bind(wx.EVT_MENU, self.onClear, id=301)
616 FredericG 343
        self.Bind(wx.EVT_MENU, self.onClearSelected, id=302)
627 FredericG 344
        self.Bind(wx.EVT_MENU, self.onSelectAll, id=310)
616 FredericG 345
        self.Bind(wx.EVT_MENU, self.OnImport, id=303)
346
        self.Bind(wx.EVT_MENU, self.onExport, id=304)
626 FredericG 347
        self.Bind(wx.EVT_MENU, self.onAbout, id=1099)
633 FredericG 348
        self.Bind(wx.EVT_BUTTON, self.onStartMeasure, self.bitmap_button_1)
600 FredericG 349
        self.Bind(wx.EVT_CHOICE, self.onGraphTypeChange, self.graphTypeChoice)
350
        self.Bind(wx.EVT_CHOICE, self.onYAxisChange, self.yAxisChoice)
627 FredericG 351
        self.Bind(wx.EVT_BUTTON, self.onCopyGraphData, self.copyGraphButton)
584 FredericG 352
        # end wxGlade
626 FredericG 353
        favicon = wx.Icon('%s/Resources/60px-Procman.ico' % rootPath, wx.BITMAP_TYPE_ICO, 32, 32)
354
        wx.Frame.SetIcon(self, favicon)
633 FredericG 355
 
584 FredericG 356
 
587 FredericG 357
    def setApp(self, app):
358
        self.app = app
585 FredericG 359
 
584 FredericG 360
    def __set_properties(self):
361
        # begin wxGlade: MainFrame.__set_properties
587 FredericG 362
        self.SetTitle("VibrationTest")
600 FredericG 363
        self.SetSize((850, 700))
633 FredericG 364
        self.label_1.SetMinSize((110, -1))
365
        self.label_1.SetFont(wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
366
        self.descrCtrl.SetMinSize((350, -1))
367
        self.label_2.SetMinSize((110, -1))
368
        self.label_2.SetFont(wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
369
        self.accTopCb.SetFont(wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
370
        self.accRollCb.SetFont(wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
371
        self.accRollCb.SetValue(1)
372
        self.accNickCb.SetFont(wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
373
        self.label_3.SetMinSize((110, -1))
374
        self.label_3.SetFont(wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
375
        self.label_4.SetFont(wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
646 FredericG 376
        self.speedCtrl.SetToolTipString("e.g. \n 100 \n 100,150 \n 100-200:10 \n 50,100-200:10 \n 5*100,5*200")
633 FredericG 377
        self.bitmap_button_1.SetToolTipString("Start Measurement")
378
        self.bitmap_button_1.SetSize(self.bitmap_button_1.GetBestSize())
379
        self.static_line_1.SetMinSize((800,3))
626 FredericG 380
        self.graphCtrl.SetMinSize((800,300))
633 FredericG 381
        self.label_40.SetFont(wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
600 FredericG 382
        self.graphTypeChoice.SetSelection(0)
633 FredericG 383
        self.label_41.SetFont(wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
600 FredericG 384
        self.yAxisChoice.SetSelection(1)
633 FredericG 385
        self.copyGraphButton.SetFont(wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
600 FredericG 386
        self.TestListCtrl.SetMinSize((800,300))
633 FredericG 387
        self.TestListCtrl.SetFont(wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
584 FredericG 388
        # end wxGlade
389
 
390
    def __do_layout(self):
391
        # begin wxGlade: MainFrame.__do_layout
600 FredericG 392
        sizer_3 = wx.BoxSizer(wx.HORIZONTAL)
393
        sizer_8 = wx.BoxSizer(wx.VERTICAL)
394
        sizer_11 = wx.BoxSizer(wx.VERTICAL)
395
        sizer_12 = wx.BoxSizer(wx.HORIZONTAL)
633 FredericG 396
        sizer_17 = wx.BoxSizer(wx.VERTICAL)
600 FredericG 397
        sizer_9 = wx.BoxSizer(wx.HORIZONTAL)
633 FredericG 398
        sizer_7 = wx.BoxSizer(wx.HORIZONTAL)
399
        sizer_13 = wx.BoxSizer(wx.VERTICAL)
400
        sizer_16 = wx.BoxSizer(wx.HORIZONTAL)
401
        sizer_15 = wx.BoxSizer(wx.HORIZONTAL)
402
        sizer_14 = wx.BoxSizer(wx.HORIZONTAL)
600 FredericG 403
        sizer_3.Add((20, 20), 0, 0, 0)
404
        sizer_8.Add((20, 20), 0, 0, 0)
633 FredericG 405
        sizer_14.Add(self.label_1, 0, wx.ALIGN_CENTER_VERTICAL, 0)
406
        sizer_14.Add((20, 20), 0, 0, 0)
407
        sizer_14.Add(self.descrCtrl, 0, wx.ALIGN_CENTER_VERTICAL, 0)
408
        sizer_13.Add(sizer_14, 1, wx.EXPAND, 0)
409
        sizer_13.Add((20, 5), 0, 0, 0)
410
        sizer_15.Add(self.label_2, 0, wx.ALIGN_CENTER_VERTICAL, 0)
411
        sizer_15.Add((20, 20), 0, 0, 0)
412
        sizer_15.Add(self.accTopCb, 0, wx.ALIGN_CENTER_VERTICAL, 0)
413
        sizer_15.Add((20, 20), 0, 0, 0)
414
        sizer_15.Add(self.accRollCb, 0, wx.ALIGN_CENTER_VERTICAL, 0)
415
        sizer_15.Add((20, 20), 0, 0, 0)
416
        sizer_15.Add(self.accNickCb, 0, wx.ALIGN_CENTER_VERTICAL, 0)
417
        sizer_13.Add(sizer_15, 1, wx.EXPAND, 0)
418
        sizer_13.Add((20, 5), 0, 0, 0)
419
        sizer_16.Add(self.label_3, 0, wx.ALIGN_CENTER_VERTICAL, 0)
420
        sizer_16.Add((20, 20), 0, 0, 0)
421
        sizer_16.Add(self.motorsCtrl, 0, wx.ALIGN_CENTER_VERTICAL, 0)
422
        sizer_16.Add((50, 20), 0, 0, 0)
423
        sizer_16.Add(self.label_4, 0, wx.RIGHT|wx.ALIGN_CENTER_VERTICAL, 0)
424
        sizer_16.Add((20, 20), 0, 0, 0)
425
        sizer_16.Add(self.speedCtrl, 0, wx.ALIGN_CENTER_VERTICAL, 0)
426
        sizer_13.Add(sizer_16, 1, wx.EXPAND, 0)
427
        sizer_7.Add(sizer_13, 1, wx.EXPAND, 0)
428
        sizer_7.Add((20, 20), 0, 0, 0)
429
        sizer_7.Add((20, 20), 0, 0, 0)
430
        sizer_9.Add(sizer_7, 1, wx.EXPAND, 0)
431
        sizer_9.Add(self.bitmap_button_1, 0, 0, 0)
600 FredericG 432
        sizer_8.Add(sizer_9, 0, 0, 0)
633 FredericG 433
        sizer_17.Add((20, 20), 0, 0, 0)
434
        sizer_17.Add(self.static_line_1, 0, wx.EXPAND, 0)
435
        sizer_17.Add((20, 20), 0, 0, 0)
436
        sizer_8.Add(sizer_17, 0, wx.EXPAND, 0)
626 FredericG 437
        sizer_11.Add(self.graphCtrl, 1, wx.EXPAND, 0)
600 FredericG 438
        sizer_11.Add((20, 5), 0, 0, 0)
439
        sizer_12.Add(self.label_40, 0, wx.ALIGN_CENTER_VERTICAL, 0)
440
        sizer_12.Add(self.graphTypeChoice, 0, 0, 0)
441
        sizer_12.Add((40, 20), 0, 0, 0)
442
        sizer_12.Add(self.label_41, 0, wx.ALIGN_CENTER_VERTICAL, 0)
443
        sizer_12.Add(self.yAxisChoice, 0, 0, 0)
627 FredericG 444
        sizer_12.Add((80, 20), 0, 0, 0)
445
        sizer_12.Add(self.copyGraphButton, 0, 0, 0)
600 FredericG 446
        sizer_11.Add(sizer_12, 0, 0, 0)
447
        sizer_8.Add(sizer_11, 0, 0, 0)
448
        sizer_8.Add((20, 30), 0, 0, 0)
449
        sizer_8.Add(self.TestListCtrl, 1, 0, 0)
450
        sizer_8.Add((20, 20), 0, 0, 0)
451
        sizer_3.Add(sizer_8, 1, wx.EXPAND, 0)
452
        self.SetSizer(sizer_3)
584 FredericG 453
        self.Layout()
600 FredericG 454
        self.SetSize((850, 700))
584 FredericG 455
        # end wxGlade
456
 
590 FredericG 457
        # List events
458
        self.TestListCtrl.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnTestSelected, self.TestListCtrl)
459
 
586 FredericG 460
        # Configure Graph
626 FredericG 461
        #self.graphCtrl = wx.lib.plot.PlotCanvas(self.GraphPanel, size=(800,300))
593 FredericG 462
 
626 FredericG 463
        self.graphCtrl.SetPointLabelFunc(self.DrawPointLabel)
585 FredericG 464
 
626 FredericG 465
        self.graphCtrl.SetFont(wx.Font(10,wx.SWISS,wx.NORMAL,wx.NORMAL))
466
        self.graphCtrl.SetFontSizeAxis(10)
467
        self.graphCtrl.SetFontSizeLegend(7)
468
        self.graphCtrl.setLogScale((False,False))
585 FredericG 469
 
586 FredericG 470
 
471
        # Configure TestListCtrl
594 FredericG 472
        self.TestListCtrl.InsertColumn(0, "Description")
619 FredericG 473
        self.TestListCtrl.InsertColumn(1, "Voltage")
474
        self.TestListCtrl.InsertColumn(2, "Speed")
475
        self.TestListCtrl.InsertColumn(3, "Channel")
476
        self.TestListCtrl.InsertColumn(4, "Vibration Value")
477
        self.TestListCtrl.SetColumnWidth(4, 500)
586 FredericG 478
 
585 FredericG 479
    def DrawPointLabel(self, dc, mDataDict):
480
        """This is the fuction that defines how the pointLabels are plotted
481
            dc - DC that will be passed
482
            mDataDict - Dictionary of data that you want to use for the pointLabel
483
 
484
            As an example I have decided I want a box at the curve point
485
            with some text information about the curve plotted below.
486
            Any wxDC method can be used.
487
        """
488
        # ----------
489
        dc.SetPen(wx.Pen(wx.BLACK))
490
        dc.SetBrush(wx.Brush( wx.BLACK, wx.SOLID ) )
491
 
492
        sx, sy = mDataDict["scaledXY"] #scaled x,y of closest point
493
        dc.DrawRectangle( sx-5,sy-5, 10, 10)  #10by10 square centered on point
494
        px,py = mDataDict["pointXY"]
495
        cNum = mDataDict["curveNum"]
496
        pntIn = mDataDict["pIndex"]
497
        legend = mDataDict["legend"]
498
        #make a string to display
499
        s = "Crv# %i, '%s', Pt. (%.2f,%.2f), PtInd %i" %(cNum, legend, px, py, pntIn)
500
        dc.DrawText(s, sx , sy+1)
501
        # -----------
502
 
596 FredericG 503
 
504
    def onNewTest(self, test):
505
        index = self.TestListCtrl.InsertStringItem(sys.maxint, test.descr)
645 FredericG 506
        self._fillRowInTestList(index, test)
507
        self.TestListCtrl.Select(index)
508
 
509
    def _fillRowInTestList(self, index, test):
510
        self.TestListCtrl.SetStringItem(index, 0, test.descr)
619 FredericG 511
        self.TestListCtrl.SetStringItem(index, 1, "%.1f V" %test.voltage)
512
        self.TestListCtrl.SetStringItem(index, 2, str(test.speed))
513
        self.TestListCtrl.SetStringItem(index, 3, test.channel)
607 FredericG 514
 
648 FredericG 515
        vv = test.getVibValue(self.app.settings["hpf"].value, self.app.settings["lpf"].value)
516
        vvs = "|%s| (%.1f)" % ("----------------------------------------------------------------------------------------------------"[0:min(int(vv+1)/2,100)], vv)
619 FredericG 517
        self.TestListCtrl.SetStringItem(index, 4, vvs)
596 FredericG 518
 
645 FredericG 519
    def refreshData(self):
520
        for idx in range(len(self.app.VibTests)):
521
            self._fillRowInTestList(idx, self.app.getTest(idx))
522
        self.drawGraph()
523
 
590 FredericG 524
    def OnTestSelected(self, event):
525
         testId = event.m_itemIndex
526
         print "Test Selected id=%d" % (testId)
592 FredericG 527
         self.activeTestId = testId
528
         self.drawGraph()
636 FredericG 529
 
530
 
531
    def orderSelectedTests(self):
532
        tests = []
533
        idx = self.TestListCtrl.GetFirstSelected()
534
        while idx != -1:
535
            header = "%s %s"%(self.app.getTest(idx).descr,self.app.getTest(idx).channel)
536
            found = False
537
            for t in tests:
538
              if t[0] == header:
539
                t.append(idx)
540
                found = True
541
                break
542
            if not found:
543
                tests.append([header, idx])
544
            idx = self.TestListCtrl.GetNextSelected(idx)
545
        return tests
546
 
590 FredericG 547
 
592 FredericG 548
    def drawGraph(self):
607 FredericG 549
 
600 FredericG 550
         y = int(self.yAxisChoice.GetStringSelection())
590 FredericG 551
 
607 FredericG 552
         nbSelected = self.TestListCtrl.SelectedItemCount
596 FredericG 553
 
616 FredericG 554
         if nbSelected == 0:
626 FredericG 555
              self.graphCtrl.Clear()
616 FredericG 556
 
557
         elif nbSelected > 1:
607 FredericG 558
             self.graphTypeChoice.Disable()
627 FredericG 559
             self.copyGraphButton.Enable()
636 FredericG 560
 
561
             tests = self.orderSelectedTests()
562
 
563
             lines = []
564
             maxX = 0
565
             cCnt = 0
566
             for s in tests:
567
               data = []
568
               x=1
569
               for t in s[1:]:
570
                 data.append([x,self.app.getTest(t).getVibValue(self.app.settings["hpf"].value, self.app.settings["lpf"].value)])
607 FredericG 571
                 x += 1
636 FredericG 572
               lines.append(wx.lib.plot.PolyLine(data, legend= s[0], colour=COLORS[cCnt], width=2))
573
               lines.append(wx.lib.plot.PolyMarker(data, legend= "", colour=COLORS[cCnt], marker='circle',size=2))
574
               maxX = max(maxX, x)
575
               cCnt += 1
576
 
607 FredericG 577
             title = "Comparing tests"
629 FredericG 578
             self.graphCtrl.setLogScale((False,False))
636 FredericG 579
             self.graphCtrl.Draw(wx.lib.plot.PlotGraphics(lines, title, "Test", "Vibration Value"), xAxis=(1,maxX), yAxis=(0,y))
626 FredericG 580
             self.graphCtrl.SetEnableGrid('Horizontal')
636 FredericG 581
             self.graphCtrl.SetEnableLegend(True)
582
 
600 FredericG 583
 
607 FredericG 584
         else:
585
             self.graphTypeChoice.Enable()
627 FredericG 586
             self.copyGraphButton.Disable()
607 FredericG 587
             vibTest = self.app.getTest(self.activeTestId)
588
             nb = vibTest.getDataLen()
590 FredericG 589
 
607 FredericG 590
             if self.graphTypeChoice.GetSelection() == 0:
591
                 xydata = _Numeric.linspace(0,0.09*nb,2*nb)
592
                 xydata.shape = (nb, 2)
593
                 xydata[:,1] = vibTest.getRawData()
594
                 line = wx.lib.plot.PolyLine(xydata, legend= 'Raw Data', colour='red', width=2)
595
 
596
                 title = "Raw Signal: %s %s %d" %(vibTest.descr, vibTest.channel, vibTest.speed)
629 FredericG 597
                 self.graphCtrl.setLogScale((False,False))
643 FredericG 598
                 self.graphCtrl.Draw(wx.lib.plot.PlotGraphics([line], title, "Time (ms)", "Acc"), yAxis= (-y/2,y/2))
626 FredericG 599
                 self.graphCtrl.SetEnableGrid('Horizontal')
636 FredericG 600
                 self.graphCtrl.SetEnableLegend(False)
601
 
599 FredericG 602
 
607 FredericG 603
             if self.graphTypeChoice.GetSelection() == 1:
604
                 xydata = _Numeric.linspace(0,0.09*nb,2*nb)
605
                 xydata.shape = (nb, 2)
615 FredericG 606
                 xydata[:,1] = vibTest.getFilteredData(self.app.settings["hpf"].value, self.app.settings["lpf"].value)
607 FredericG 607
                 line = wx.lib.plot.PolyLine(xydata, legend= 'Raw Data', colour='red', width=2)
608
 
609
                 title = "Filtered Signal: %s %s %d" %(vibTest.descr, vibTest.channel, vibTest.speed)
629 FredericG 610
                 self.graphCtrl.setLogScale((False,False))
643 FredericG 611
                 self.graphCtrl.Draw(wx.lib.plot.PlotGraphics([line], title, "Time (ms)", "Acc"), yAxis= (-y/2,y/2))
626 FredericG 612
                 self.graphCtrl.SetEnableGrid('Horizontal')
636 FredericG 613
                 self.graphCtrl.SetEnableLegend(False)
607 FredericG 614
 
615
             elif self.graphTypeChoice.GetSelection() == 2:
615 FredericG 616
                 xydata = _Numeric.linspace(0,FS/2,nb)
607 FredericG 617
                 xydata.shape = (nb/2, 2)
618
 
619
                 xydata[:,1] = vibTest.getSpectrum()
629 FredericG 620
 
621
                 #print xydata
607 FredericG 622
 
623
                 line = wx.lib.plot.PolyLine(xydata, legend= 'Spectrum', colour='red')
624
                 markers = wx.lib.plot.PolyMarker(xydata, legend= '', colour='red', marker='circle',size=2)
615 FredericG 625
 
626
                 fc = self.app.settings["hpf"].value
627
                 filterLine1 = wx.lib.plot.PolyLine(((fc,0),(fc,y)), legend='HP Filter', colour='Black', width=4)
628
                 fc = self.app.settings["lpf"].value
629
                 filterLine2 = wx.lib.plot.PolyLine(((fc,0),(fc,y)), legend='HP Filter', colour='Black', width=4)
607 FredericG 630
 
631
                 title = "Spectrum: %s %s %d" %(vibTest.descr, vibTest.channel, vibTest.speed)
632 FredericG 632
                 self.graphCtrl.setLogScale((True,False))
633
                 self.graphCtrl.Draw(wx.lib.plot.PlotGraphics([line,markers, filterLine1, filterLine2], title, "Freq (Hz)", "Acc"), xAxis=(20,500), yAxis= (0,y))
636 FredericG 634
                 self.graphCtrl.SetEnableGrid(True)
635
                 self.graphCtrl.SetEnableLegend(False)
629 FredericG 636
 
590 FredericG 637
 
599 FredericG 638
 
587 FredericG 639
    def OnImport(self, event): # wxGlade: MainFrame.<event_handler>
606 FredericG 640
        dlg = wx.FileDialog(
641
            self, message="Choose a file",
619 FredericG 642
            defaultDir="%s/Data/" % os.getcwd(),
637 FredericG 643
            defaultFile=".",
644
            wildcard="Text files (*.txt)|*.txt|All files (*.*)|*.*",
606 FredericG 645
            style=wx.OPEN | wx.CHANGE_DIR
646
            )
647
        if dlg.ShowModal() == wx.ID_OK:
648
            paths = dlg.GetPaths();
619 FredericG 649
            self.app.loadTests(paths[0])
606 FredericG 650
        dlg.Destroy()
587 FredericG 651
 
619 FredericG 652
    def onExport(self, event): # wxGlade: MainFrame.<event_handler>
653
        dlg = wx.FileDialog(
654
              self, message="Save file as ...",
655
              defaultDir="%s/Data/" % os.getcwd(),
637 FredericG 656
              defaultFile=".",
657
              wildcard="Text files (*.txt)|*.txt|All files (*.*)|*.*",
619 FredericG 658
              style=wx.SAVE
659
              )
660
        if dlg.ShowModal() == wx.ID_OK:
661
            paths = dlg.GetPaths();
662
            self.app.saveTests(paths[0])
663
        dlg.Destroy()
664
 
599 FredericG 665
    def onYAxisChange(self, event): # wxGlade: MainFrame.<event_handler>
592 FredericG 666
        self.drawGraph()
667
 
600 FredericG 668
    def onGraphTypeChange(self, event): # wxGlade: MainFrame.<event_handler>
599 FredericG 669
        self.drawGraph()
670
 
607 FredericG 671
    def OnSettings(self, event): # wxGlade: MainFrame.<event_handler>
672
        dlg = SettingsDialog(self, -1, "Sample Dialog", size=(350, 200),
673
                         #style=wx.CAPTION | wx.SYSTEM_MENU | wx.THICK_FRAME,
674
                         style=wx.DEFAULT_DIALOG_STYLE, # & ~wx.CLOSE_BOX
675
                         )
676
        dlg.CenterOnScreen()
611 FredericG 677
        val = dlg.ShowModal()  # this does not return until the dialog is closed.
607 FredericG 678
        dlg.Destroy()
648 FredericG 679
        self.app.onSettingsChanged(True)
607 FredericG 680
 
612 FredericG 681
    def onStartMeasure(self, event): # wxGlade: MainFrame.<event_handler>
613 FredericG 682
        # Collect measure parameters
683
        mp = MeasureParameters()
640 FredericG 684
 
685
        try:
686
          mp.descr = self.descrCtrl.GetValue()
687
          mp.motors = map(int,self.motorsCtrl.GetValue().split(','))
688
          mp.channels = []
689
          if self.accTopCb.IsChecked(): mp.channels.append(5)
690
          if self.accRollCb.IsChecked(): mp.channels.append(6)
691
          if self.accNickCb.IsChecked(): mp.channels.append(7)
646 FredericG 692
 
693
          mp.speeds = []
694
          for speedTxt in self.speedCtrl.GetValue().split(","):
695
              if speedTxt.count("-") == 1:
696
                  # assume from-to:step format
697
                  speedTxt = speedTxt.split("-")
698
                  if len(speedTxt) != 2: raise Exception("Invalid format")
699
                  speedTxt[1] = speedTxt[1].split(":")
700
                  if len(speedTxt[1]) != 2: raise Exception("Invalid format")
701
                  mp.speeds = range(int(speedTxt[0]),int(speedTxt[1][0])+int(speedTxt[1][1]),int(speedTxt[1][1]))
702
              else:
703
                  # assume s or s*n format
704
                  if speedTxt.count("*") == 1:
705
                      speedTxt = speedTxt.split("*")
706
                      for i in range(int(speedTxt[0])):
707
                        mp.speeds.append(int(speedTxt[1]))
708
                  else:
709
                      mp.speeds.append(int(speedTxt))
640 FredericG 710
        except Exception,e:
711
          dial = wx.MessageDialog(None, 'Invalid paramters', 'Error', wx.OK |
712
            wx.ICON_ERROR)
713
          dial.ShowModal()
714
          raise e
715
 
716
 
614 FredericG 717
 
633 FredericG 718
        print mp.descr
719
        print mp.motors
720
        print mp.channels
721
        print mp.speeds
613 FredericG 722
 
633 FredericG 723
 
724
 
612 FredericG 725
        # create the dialog that will show the satus
726
        dlg = MeasureDialog(self)
727
        dlg.CenterOnScreen()
613 FredericG 728
 
729
        # Signal the application
730
        self.app.startMeasure(mp, dlg)
731
 
612 FredericG 732
        # Show the dialog
733
        val = dlg.ShowModal()  # this does not return until the dialog is closed.
734
        dlg.Destroy()
735
 
616 FredericG 736
    def _removeTest(self, idx):
737
        print "Deleting test %d" % idx
738
        self.app.removeTest(idx)
739
        self.TestListCtrl.DeleteItem(idx)
740
 
741
 
742
    def onClear(self, event): # wxGlade: MainFrame.<event_handler>
639 FredericG 743
        dial = wx.MessageDialog(None, 'Clear ALL tests?', 'Question',
744
            wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION)
745
        if dial.ShowModal() == wx.ID_YES:
746
          print "Clear all tests"
747
          for i in range(len(self.app.VibTests)-1, -1, -1):
748
              self._removeTest(i)
749
          self.drawGraph()
616 FredericG 750
 
751
 
752
    def onClearSelected(self, event): # wxGlade: MainFrame.<event_handler>
639 FredericG 753
        dial = wx.MessageDialog(None, 'Clear Selected tests?', 'Question',
754
            wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION)
755
        if dial.ShowModal() == wx.ID_YES:
756
          while True:
757
              idx = self.TestListCtrl.GetFirstSelected()
758
              if idx == -1: break
759
              self._removeTest(idx)
616 FredericG 760
 
627 FredericG 761
 
626 FredericG 762
 
763
    def onAbout(self, event): # wxGlade: MainFrame.<event_handler>
764
         # First we create and fill the info object
765
        print "about"
766
        info = wx.AboutDialogInfo()
648 FredericG 767
        info.Name = "- MK Vibration Test - "
768
        info.Version = "v0.9 RC1"
626 FredericG 769
        info.Copyright = ""
643 FredericG 770
        info.Developers=["Frederic Goddeeris  Frederic@rc-flight.be"]
626 FredericG 771
        info.Description = "Please consult the WIKI page for a complete description of the tool:"
772
        info.WebSite = ("http://www.mikrokopter.de/ucwiki/en/VibrationTest", "VibrationTest WIKI page")
773
        wx.AboutBox(info)
774
 
775
 
776
    def onExit(self, event): # wxGlade: MainFrame.<event_handler>
777
        self.Close(True)
778
 
779
 
627 FredericG 780
    def onSelectAll(self, event): # wxGlade: MainFrame.<event_handler>
781
        for i in xrange(self.TestListCtrl.GetItemCount()):
782
          self.TestListCtrl.Select(i)
783
 
784
    def onCopyGraphData(self, event): # wxGlade: MainFrame.<event_handler>
785
        clipdata = wx.TextDataObject()
786
        txt = ""
787
        idx = self.TestListCtrl.GetFirstSelected()
788
        while idx != -1:
789
             txt += ("%d\n" % self.app.getTest(idx).getVibValue(self.app.settings["hpf"].value, self.app.settings["lpf"].value))
790
             idx = self.TestListCtrl.GetNextSelected(idx)
791
        clipdata.SetText(txt)
792
        wx.TheClipboard.Open()
793
        wx.TheClipboard.SetData(clipdata)
794
        wx.TheClipboard.Close()
795
 
584 FredericG 796
# end of class MainFrame
797
 
607 FredericG 798
class Setting:
799
    def __init__(self, descr, defaultValue):
800
        self.descr = descr
801
        self.value = defaultValue
611 FredericG 802
 
803
    def set(self, newValue):
804
        if isinstance(self.value, int):
805
            self.value = int(newValue)
806
        else:
807
            self.value = str(newValue)
584 FredericG 808
 
613 FredericG 809
class MeasureParameters:
810
      pass
612 FredericG 811
 
812
class MeasureThread:
613 FredericG 813
    def __init__(self, measureParameters, evtConsumer):
814
        self.mk = mkProto.MkComm()
815
        self.param = measureParameters
612 FredericG 816
        self.evtConsumer = evtConsumer
613 FredericG 817
        self.cancel = False
818
        self.running = False
612 FredericG 819
 
820
    def start(self):
821
        thread.start_new_thread(self._run, ())
822
 
613 FredericG 823
    def stop(self):
824
        self.cancel = True
825
 
826
    def _testCancel(self):
827
        if self.cancel:
828
            raise Exception("Operation cancelled")
829
 
623 FredericG 830
    def _sendEvent(self, msg=None, error=False, parVoltage=None, speed=None):
831
        evt = MeasStatusUpdateEvent(running=self.running, msg=msg, error=error, voltage=parVoltage, speed=speed)
613 FredericG 832
        wx.PostEvent(self.evtConsumer, evt)
833
 
834
    def _setMotorSpeed(self, speed, settlingTime):
835
        speeds = [0,0,0,0]
638 FredericG 836
 
613 FredericG 837
        for motor in self.param.motors:
838
            speeds[motor-1] = speed
839
        for i in range(int(settlingTime*10)):
840
          self._testCancel()
841
          self.mk.setMotorTest(speeds)
842
          time.sleep(.1)
646 FredericG 843
        self.currSpeed = speed
613 FredericG 844
 
845
 
612 FredericG 846
    def _run(self):
613 FredericG 847
        self.running = True
848
        self._sendEvent("Starting test \"%s\"" % self.param.descr)
646 FredericG 849
        self.currSpeed = 0
850
 
613 FredericG 851
        try:
852
            self._sendEvent("Opening SerialPort \"%s\"" % self.param.serialPort)
853
            self.mk.open(comPort=self.param.serialPort)
612 FredericG 854
 
613 FredericG 855
            msg = self.mk.getVersionMsg()
856
            version = msg.getVersion()
857
            self._sendEvent("Version: %d.%d" % version)
858
 
859
            msg = self.mk.getDebugMsg()
860
            voltage = msg.getVoltage()
861
            if (voltage == 0):
628 FredericG 862
              # Board is probably fed by USB
613 FredericG 863
              minVoltage = 0
623 FredericG 864
              maxVoltage = 1
613 FredericG 865
            else:
628 FredericG 866
              # Determine the n umber of cells
613 FredericG 867
              if (voltage > 4.2*3):
623 FredericG 868
                nbCells = 4
613 FredericG 869
              else:
623 FredericG 870
                nbCells = 3
628 FredericG 871
              # Set minimum and maximum voltages
872
              if self.param.minVoltage > 0:
873
                minVoltage =  self.param.minVoltage
874
              else:
875
                minVoltage = nbCells*3.5  # auto
876
              if self.param.maxVoltage > 0:
877
                maxVoltage =  self.param.maxVoltage
878
              else:
879
                maxVoltage = nbCells*3.9
880
 
613 FredericG 881
            self._sendEvent("Voltage: %2.1fV" % voltage)
623 FredericG 882
            self._sendEvent("Min/Max Voltage: %2.1fV-%2.1fV" % (minVoltage, maxVoltage), parVoltage=(minVoltage, maxVoltage, voltage))
883
 
884
            self._sendEvent("Starting motor(s) (speed=%d)... " % self.param.motorStartupSpeed, speed=self.param.motorStartupSpeed)
613 FredericG 885
            self._setMotorSpeed(self.param.motorStartupSpeed, self.param.motorStartupSettlingTime)
886
 
887
            for speed in self.param.speeds:
646 FredericG 888
                if speed != self.currSpeed:
889
                    self._sendEvent("Changing motor speed to %d... " % speed, speed=speed)
890
                    self._setMotorSpeed(speed, 1)
613 FredericG 891
 
892
                for channel in self.param.channels:
893
                    self._setMotorSpeed(speed, .1)
619 FredericG 894
                    msg = self.mk.getDebugMsg()
895
                    voltage = msg.getVoltage()
896
 
623 FredericG 897
                    self._sendEvent("Getting data from channel %s" % CHANNEL_NAMES[channel], parVoltage=(minVoltage, maxVoltage, voltage))
613 FredericG 898
                    data = self.mk.doVibrationTest(1000, channel)
899
 
619 FredericG 900
                    vt = VibTest(self.param.descr, voltage, self.param.motors, speed, CHANNEL_NAMES[channel], data)
613 FredericG 901
                    evt = MeasDataEvent(vibTest = vt)
902
                    wx.PostEvent(self.evtConsumer, evt)
903
 
619 FredericG 904
                    if voltage<minVoltage:
905
                        raise Exception("Voltage too low")
634 FredericG 906
 
907
 
908
            self._setMotorSpeed(speed, .1)
909
            time.sleep(1)
910
            msg = self.mk.getDebugMsg()
911
            voltage = msg.getVoltage()
912
 
913
            self._sendEvent("Done !", parVoltage=(minVoltage, maxVoltage, voltage))
914
 
613 FredericG 915
        except Exception, e:
916
            self._sendEvent("Exception \"%s\"" % e, error=True)
647 FredericG 917
 
918
        try:
919
          self.mk.close()
920
        except:
921
          print "Failure closing MK serial port"
922
          pass
923
 
613 FredericG 924
        self.running = False
629 FredericG 925
        self._sendEvent("", speed = 0)
613 FredericG 926
 
612 FredericG 927
 
586 FredericG 928
class VibTest:
648 FredericG 929
    useRms = True
930
 
619 FredericG 931
    def __init__(self, descr, voltage, motor, speed, channel, rawData):
594 FredericG 932
        self.descr = descr
619 FredericG 933
        self.voltage = voltage
594 FredericG 934
        self.motor = motor
935
        self.speed = speed
596 FredericG 936
        self.channel = channel
599 FredericG 937
 
938
        self.dataLen = len(rawData)
939
 
590 FredericG 940
        self.rawData = _Numeric.array(rawData)
941
        self.dc = self.rawData.mean()
942
        self.rawData -= self.dc
586 FredericG 943
 
600 FredericG 944
        self.fft = _Numeric.fft.rfft(self.rawData)
945
 
946
        self.spectrum = None
947
        self.filteredData = None
615 FredericG 948
        self.fc1 = None
949
        self.fc2 = None
599 FredericG 950
 
602 FredericG 951
        self.vibValue = None
952
 
594 FredericG 953
    def getDescr(self):
954
        return self.Descr
587 FredericG 955
 
590 FredericG 956
    def getRawData(self):
957
        return self.rawData
958
 
959
    def getDataLen(self):
960
        return self.dataLen
961
 
599 FredericG 962
    def getSpectrum(self):
600 FredericG 963
        if self.spectrum == None:
964
            self.spectrum = _Numeric.absolute(self.fft[1:self.dataLen/2+1]) / (self.dataLen/2)
965
        return self.spectrum
648 FredericG 966
 
967
    def refresh(self):
968
        self.filteredData = None
969
        self.vibValue = None
590 FredericG 970
 
615 FredericG 971
    def getFilteredData(self, fc1, fc2):
972
        if self.fc1 != fc1 or self.fc2 != fc2:
973
            self.filteredData = None
974
 
600 FredericG 975
        if self.filteredData == None:
976
            tmpfft = self.fft.copy()
615 FredericG 977
            fc = (float(fc1))/(FS/2)*len(tmpfft)
644 FredericG 978
            print "fc1=%d => fc=%f" % (fc1,fc)
979
            for i in range(0,int(fc)+2):
600 FredericG 980
                tmpfft[i] = 0
615 FredericG 981
            fc = (float(fc2))/(FS/2)*len(tmpfft)
644 FredericG 982
            print "fc2=%d => fc=%f" % (fc2,fc)
983
            for i in range(int(fc)+2, len(tmpfft)):
600 FredericG 984
                tmpfft[i] = 0
985
            self.filteredData = _Numeric.fft.irfft(tmpfft)
615 FredericG 986
            self.fc1 = fc1
987
            self.fc2 = fc2
988
 
600 FredericG 989
        return self.filteredData
602 FredericG 990
 
615 FredericG 991
    def getVibValue(self, fc1, fc2):
992
      if self.fc1 != fc1 or self.fc2 != fc2:
648 FredericG 993
        self.vibValue = None
994
 
602 FredericG 995
      if self.vibValue == None:
615 FredericG 996
        fd = self.getFilteredData(fc1, fc2)[100:-100];
648 FredericG 997
        if self.useRms:
998
            print "RMS"
999
            self.vibValue = math.sqrt(sum([x*x for x in fd])/len(fd))*2*math.sqrt(2)
1000
        else:
1001
            print "PP"
1002
            self.vibValue = max(fd)-min(fd)
602 FredericG 1003
      return self.vibValue
599 FredericG 1004
 
607 FredericG 1005
 
1006
 
584 FredericG 1007
class App(wx.App):
607 FredericG 1008
 
1009
    SETTINGSFILE = "settings.cfg"
1010
 
586 FredericG 1011
    def __init__(self, par):
1012
        self.VibTests = []
1013
        wx.App.__init__(self, par)
1014
 
607 FredericG 1015
        # Init settings
1016
        self.settings={}
611 FredericG 1017
        self.settings["serialport"] = Setting("Serial Port", "COM1")
613 FredericG 1018
        self.settings["startupspeed"] = Setting("Motor Startup Speed", 25)
1019
        self.settings["startupsettling"] = Setting("Motor Startup Setting time (s)", 3)
1020
        self.settings["serialport"] = Setting("Serial Port", "COM1")
644 FredericG 1021
        self.settings["hpf"] = Setting("HP Filter cutoff (Hz)", 40)
632 FredericG 1022
        self.settings["lpf"] = Setting("LP Filter cutoff (Hz)", 400)
648 FredericG 1023
        self.settings["calcmethod"] = Setting("Calculation Method", "rms")
628 FredericG 1024
        self.settings["minvoltage"] = Setting("Minimum Bettery Voltage (0=Automatic) (V) ", 0)
1025
        self.settings["maxvoltage"] = Setting("Maximum Bettery Voltage (0=Automatic) (V) ", 0)
607 FredericG 1026
 
628 FredericG 1027
 
607 FredericG 1028
        self.readSettings()
1029
 
606 FredericG 1030
        if len(sys.argv)>1:
619 FredericG 1031
            self.loadTests(sys.argv[1])
586 FredericG 1032
 
606 FredericG 1033
 
607 FredericG 1034
    def readSettings(self):
1035
        print "Reading settings"
1036
        cp = ConfigParser.ConfigParser()
1037
 
1038
        try:
644 FredericG 1039
            cp.read("%s/%s" % (rootPath, App.SETTINGSFILE))
607 FredericG 1040
            for setting in cp.items("DEFAULT"):
1041
                print " ",setting
1042
                try:
613 FredericG 1043
                    self.settings[setting[0]].set(setting[1])
607 FredericG 1044
                except:
1045
                    print "WARNING, unknown setting"
1046
        except:
1047
            print "ERROR reading settingsfile"
648 FredericG 1048
        self.onSettingsChanged(False)
607 FredericG 1049
 
1050
    def storeSettings(self):
1051
        print "Storing settings"
1052
 
1053
        cp = ConfigParser.ConfigParser()
1054
        for setting in self.settings.iteritems():
1055
            cp.set("", setting[0], setting[1].value)
1056
 
644 FredericG 1057
        file = open("%s/%s" % (rootPath, App.SETTINGSFILE), "w")
607 FredericG 1058
        cp.write(file)
1059
        file.close()
1060
 
611 FredericG 1061
 
648 FredericG 1062
    def onSettingsChanged(self, store):
1063
        if store:
1064
            self.storeSettings()
1065
        if self.settings["calcmethod"].value == "rms":
1066
            VibTest.useRms = True
1067
        else:
1068
            VibTest.useRms = False
1069
        for test in self.VibTests:
1070
            test.refresh()
645 FredericG 1071
        self.frame_1.refreshData()
613 FredericG 1072
 
1073
    def AddTest2(self, vibTest):
1074
        self.VibTests.append(vibTest)
1075
        self.frame_1.onNewTest(vibTest)
611 FredericG 1076
 
619 FredericG 1077
    def AddTest(self, descr, voltage, motor, speed, channel, rawData):
1078
        test = VibTest(descr, voltage, motor, speed, channel, rawData)
613 FredericG 1079
        self.AddTest2(test)
586 FredericG 1080
 
616 FredericG 1081
    def removeTest(self, idx):
1082
        del(self.VibTests[idx])
1083
 
590 FredericG 1084
    def getTest(self, testId):
1085
        return self.VibTests[testId]
1086
 
584 FredericG 1087
    def OnInit(self):
1088
        wx.InitAllImageHandlers()
586 FredericG 1089
        self.frame_1 = MainFrame(None, -1, "")
587 FredericG 1090
        self.frame_1.setApp(self);
586 FredericG 1091
        self.SetTopWindow(self.frame_1)
1092
 
607 FredericG 1093
        self.frame_1.CenterOnScreen()
587 FredericG 1094
        self.frame_1.Show()
1095
        return 1
1096
 
619 FredericG 1097
    def saveTests(self, filePath):
1098
        try:
1099
          logfile = open(filePath, "r")
1100
          newFile = False
1101
          logfile.close()
1102
        except:
1103
          newFile = True
1104
 
1105
        for test in self.VibTests:
1106
          if newFile:
1107
            logfile = open(filePath, "w")
1108
            print "Writing result to %s ..." % filePath,
1109
            logfile.write("%s %d %s\n" % (test.descr, test.speed, test.channel))
1110
            for value in test.rawData:
1111
              logfile.write("%d\n" % value)
1112
            logfile.close()
1113
            print "OK"
1114
          else:
1115
            print "Appending result to %s ..." % filePath,
1116
            logfile = open(filePath, "r")
1117
            prevData = []
1118
            for line in logfile:
1119
              prevData.append(line[:-1])
1120
            logfile.close()
1121
            logfile = open(filePath, "w")
1122
            logfile.write("%s,%s %d %s\n" % (prevData[0], test.descr, test.speed, test.channel))
1123
            i = 1
1124
            for value in test.rawData:
1125
              logfile.write("%s,%d\n" % (prevData[i], value))
1126
              i += 1
1127
            logfile.close()
1128
            print "OK"
1129
          newFile = False
1130
 
1131
 
1132
    def loadTests(self, filePath):
596 FredericG 1133
 
606 FredericG 1134
        print "Importing file \"%s\"" % filePath
596 FredericG 1135
 
1136
        logfile = open(filePath, "r")
590 FredericG 1137
        data = None
596 FredericG 1138
 
619 FredericG 1139
        headers = (logfile.readline()[:-1]).split(',')
596 FredericG 1140
        nbCols = len(headers)
1141
        print "NbCols =", nbCols
1142
 
1143
        data = []
1144
        descr = []
1145
        speed = []
1146
        channel = []
1147
        for c in range(nbCols):
1148
            data.append([])
1149
            h = headers[c].split(' ')
1150
            descr.append(h[0]);
1151
            speed.append(h[1]);
1152
            channel.append(h[2]);
1153
 
590 FredericG 1154
        for line in logfile:
1155
            values = line.split(',')
596 FredericG 1156
            for i in range(nbCols):
1157
                data[i].append(int(values[i]))
590 FredericG 1158
        logfile.close()
596 FredericG 1159
 
1160
        for c in range(nbCols):
599 FredericG 1161
            if (len(data[c]) % 2) != 0:
1162
                data[c].append(data[c][-1])
619 FredericG 1163
            self.AddTest(descr[c], 0, 0, int(speed[c]), channel[c], data[c])
612 FredericG 1164
 
613 FredericG 1165
    def startMeasure(self, measureParams, dialog):
612 FredericG 1166
        print "Start measuring"
590 FredericG 1167
 
613 FredericG 1168
        measureParams.serialPort = self.settings["serialport"].value
1169
        measureParams.motorStartupSpeed = self.settings["startupspeed"].value
1170
        measureParams.motorStartupSettlingTime = self.settings["startupsettling"].value
628 FredericG 1171
        measureParams.minVoltage = self.settings["minvoltage"].value
1172
        measureParams.maxVoltage = self.settings["maxvoltage"].value
613 FredericG 1173
 
1174
        self.measureThread = MeasureThread(measureParams, dialog)
612 FredericG 1175
        self.measureThread.start()
590 FredericG 1176
 
613 FredericG 1177
    def cancelMeasurement(self):
1178
        print "Measuring CANCEL"
1179
 
1180
        self.measureThread.stop()
1181
 
612 FredericG 1182
 
1183
 
1184
 
1185
 
590 FredericG 1186
 
586 FredericG 1187
 
590 FredericG 1188
 
584 FredericG 1189
# end of class App
1190
 
1191
if __name__ == "__main__":
626 FredericG 1192
 
1193
    rootPath = os.path.abspath(os.path.dirname(sys.argv[0]))
1194
 
1195
    print rootPath
1196
 
584 FredericG 1197
    VibrationTestGui = App(0)
1198
    VibrationTestGui.MainLoop()