Subversion Repositories Projects

Rev

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