Subversion Repositories Projects

Rev

Rev 693 | 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: 693 $
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")
683 FredericG 318
        self.label_1_copy = wx.StaticText(self, -1, "Channel(s) :", style=wx.ALIGN_RIGHT)
319
        self.gyroYawCb = wx.CheckBox(self, -1, "Gyro Yaw")
320
        self.gyroRollCb = wx.CheckBox(self, -1, "Gyro Roll")
321
        self.gyroNickCb = wx.CheckBox(self, -1, "Gyro Nick")
633 FredericG 322
        self.accTopCb = wx.CheckBox(self, -1, "ACC Top")
323
        self.accRollCb = wx.CheckBox(self, -1, "ACC Roll")
324
        self.accNickCb = wx.CheckBox(self, -1, "ACC Nick")
325
        self.label_3 = wx.StaticText(self, -1, "Motor(s) :", style=wx.ALIGN_RIGHT)
326
        self.motorsCtrl = wx.TextCtrl(self, -1, "1")
327
        self.label_4 = wx.StaticText(self, -1, "Speed(s) :")
328
        self.speedCtrl = wx.TextCtrl(self, -1, "100-200:10")
329
        self.bitmap_button_1 = wx.BitmapButton(self, -1, wx.Bitmap("Resources\\Fairytale_player_play.png", wx.BITMAP_TYPE_ANY))
330
        self.static_line_1 = wx.StaticLine(self, -1)
626 FredericG 331
        self.graphCtrl = wx.lib.plot.PlotCanvas(self, size=(800,300))
600 FredericG 332
        self.label_40 = wx.StaticText(self, -1, "Graph Type ")
333
        self.graphTypeChoice = wx.Choice(self, -1, choices=["Raw Signal", "Filtered Signal", "Spectrum"])
334
        self.label_41 = wx.StaticText(self, -1, "Y Axis Range ")
643 FredericG 335
        self.yAxisChoice = wx.Choice(self, -1, choices=["25", "50", "75", "100", "200"])
627 FredericG 336
        self.copyGraphButton = wx.Button(self, -1, "Copy Graph Data")
586 FredericG 337
        self.TestListCtrl = wx.ListCtrl(self, -1, style=wx.LC_REPORT|wx.SUNKEN_BORDER)
584 FredericG 338
 
339
        self.__set_properties()
340
        self.__do_layout()
587 FredericG 341
 
607 FredericG 342
        self.Bind(wx.EVT_MENU, self.OnSettings, id=101)
626 FredericG 343
        self.Bind(wx.EVT_MENU, self.onExit, id=150)
607 FredericG 344
        self.Bind(wx.EVT_MENU, self.onClear, id=301)
616 FredericG 345
        self.Bind(wx.EVT_MENU, self.onClearSelected, id=302)
627 FredericG 346
        self.Bind(wx.EVT_MENU, self.onSelectAll, id=310)
616 FredericG 347
        self.Bind(wx.EVT_MENU, self.OnImport, id=303)
348
        self.Bind(wx.EVT_MENU, self.onExport, id=304)
626 FredericG 349
        self.Bind(wx.EVT_MENU, self.onAbout, id=1099)
633 FredericG 350
        self.Bind(wx.EVT_BUTTON, self.onStartMeasure, self.bitmap_button_1)
600 FredericG 351
        self.Bind(wx.EVT_CHOICE, self.onGraphTypeChange, self.graphTypeChoice)
352
        self.Bind(wx.EVT_CHOICE, self.onYAxisChange, self.yAxisChoice)
627 FredericG 353
        self.Bind(wx.EVT_BUTTON, self.onCopyGraphData, self.copyGraphButton)
584 FredericG 354
        # end wxGlade
626 FredericG 355
        favicon = wx.Icon('%s/Resources/60px-Procman.ico' % rootPath, wx.BITMAP_TYPE_ICO, 32, 32)
356
        wx.Frame.SetIcon(self, favicon)
690 FredericG 357
        self.graphCtrl.canvas.Bind(wx.EVT_LEFT_DOWN, self.OnMouseLeftDown)
358
        self.measureState = 0
633 FredericG 359
 
584 FredericG 360
 
587 FredericG 361
    def setApp(self, app):
362
        self.app = app
585 FredericG 363
 
584 FredericG 364
    def __set_properties(self):
365
        # begin wxGlade: MainFrame.__set_properties
587 FredericG 366
        self.SetTitle("VibrationTest")
600 FredericG 367
        self.SetSize((850, 700))
633 FredericG 368
        self.label_1.SetMinSize((110, -1))
369
        self.label_1.SetFont(wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
370
        self.descrCtrl.SetMinSize((350, -1))
683 FredericG 371
        self.label_1_copy.SetMinSize((110, -1))
372
        self.label_1_copy.SetFont(wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
373
        self.gyroYawCb.SetMinSize((100, -1))
374
        self.gyroYawCb.SetFont(wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
375
        self.gyroRollCb.SetMinSize((100, -1))
376
        self.gyroRollCb.SetFont(wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
377
        self.gyroNickCb.SetMinSize((100, -1))
378
        self.gyroNickCb.SetFont(wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
379
        self.accTopCb.SetMinSize((100, -1))
633 FredericG 380
        self.accTopCb.SetFont(wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
683 FredericG 381
        self.accRollCb.SetMinSize((100, -1))
633 FredericG 382
        self.accRollCb.SetFont(wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
383
        self.accRollCb.SetValue(1)
683 FredericG 384
        self.accNickCb.SetMinSize((100, -1))
633 FredericG 385
        self.accNickCb.SetFont(wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
386
        self.label_3.SetMinSize((110, -1))
387
        self.label_3.SetFont(wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
388
        self.label_4.SetFont(wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
646 FredericG 389
        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 390
        self.bitmap_button_1.SetToolTipString("Start Measurement")
391
        self.bitmap_button_1.SetSize(self.bitmap_button_1.GetBestSize())
392
        self.static_line_1.SetMinSize((800,3))
626 FredericG 393
        self.graphCtrl.SetMinSize((800,300))
633 FredericG 394
        self.label_40.SetFont(wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
600 FredericG 395
        self.graphTypeChoice.SetSelection(0)
633 FredericG 396
        self.label_41.SetFont(wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
600 FredericG 397
        self.yAxisChoice.SetSelection(1)
633 FredericG 398
        self.copyGraphButton.SetFont(wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
600 FredericG 399
        self.TestListCtrl.SetMinSize((800,300))
633 FredericG 400
        self.TestListCtrl.SetFont(wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
584 FredericG 401
        # end wxGlade
402
 
403
    def __do_layout(self):
404
        # begin wxGlade: MainFrame.__do_layout
600 FredericG 405
        sizer_3 = wx.BoxSizer(wx.HORIZONTAL)
406
        sizer_8 = wx.BoxSizer(wx.VERTICAL)
407
        sizer_11 = wx.BoxSizer(wx.VERTICAL)
408
        sizer_12 = wx.BoxSizer(wx.HORIZONTAL)
633 FredericG 409
        sizer_17 = wx.BoxSizer(wx.VERTICAL)
600 FredericG 410
        sizer_9 = wx.BoxSizer(wx.HORIZONTAL)
633 FredericG 411
        sizer_7 = wx.BoxSizer(wx.HORIZONTAL)
412
        sizer_13 = wx.BoxSizer(wx.VERTICAL)
413
        sizer_16 = wx.BoxSizer(wx.HORIZONTAL)
683 FredericG 414
        sizer_10 = wx.BoxSizer(wx.HORIZONTAL)
415
        sizer_18 = wx.BoxSizer(wx.VERTICAL)
416
        sizer_20 = wx.BoxSizer(wx.HORIZONTAL)
417
        sizer_19 = wx.BoxSizer(wx.HORIZONTAL)
633 FredericG 418
        sizer_14 = wx.BoxSizer(wx.HORIZONTAL)
600 FredericG 419
        sizer_3.Add((20, 20), 0, 0, 0)
420
        sizer_8.Add((20, 20), 0, 0, 0)
633 FredericG 421
        sizer_14.Add(self.label_1, 0, wx.ALIGN_CENTER_VERTICAL, 0)
422
        sizer_14.Add((20, 20), 0, 0, 0)
423
        sizer_14.Add(self.descrCtrl, 0, wx.ALIGN_CENTER_VERTICAL, 0)
683 FredericG 424
        sizer_13.Add(sizer_14, 0, 0, 0)
633 FredericG 425
        sizer_13.Add((20, 5), 0, 0, 0)
683 FredericG 426
        sizer_10.Add(self.label_1_copy, 0, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL, 0)
427
        sizer_10.Add((20, 20), 0, 0, 0)
428
        sizer_19.Add(self.gyroYawCb, 0, wx.ALIGN_CENTER_VERTICAL, 0)
429
        sizer_19.Add((20, 20), 0, 0, 0)
430
        sizer_19.Add(self.gyroRollCb, 0, wx.ALIGN_CENTER_VERTICAL, 0)
431
        sizer_19.Add((20, 20), 0, 0, 0)
432
        sizer_19.Add(self.gyroNickCb, 0, wx.ALIGN_CENTER_VERTICAL, 0)
433
        sizer_18.Add(sizer_19, 1, wx.EXPAND, 0)
434
        sizer_20.Add(self.accTopCb, 0, wx.ALIGN_CENTER_VERTICAL, 0)
435
        sizer_20.Add((20, 20), 0, 0, 0)
436
        sizer_20.Add(self.accRollCb, 0, wx.ALIGN_CENTER_VERTICAL, 0)
437
        sizer_20.Add((20, 20), 0, 0, 0)
438
        sizer_20.Add(self.accNickCb, 0, wx.ALIGN_CENTER_VERTICAL, 0)
439
        sizer_18.Add(sizer_20, 1, wx.EXPAND, 0)
440
        sizer_10.Add(sizer_18, 1, wx.EXPAND, 0)
441
        sizer_13.Add(sizer_10, 1, wx.EXPAND, 0)
633 FredericG 442
        sizer_13.Add((20, 5), 0, 0, 0)
443
        sizer_16.Add(self.label_3, 0, wx.ALIGN_CENTER_VERTICAL, 0)
444
        sizer_16.Add((20, 20), 0, 0, 0)
445
        sizer_16.Add(self.motorsCtrl, 0, wx.ALIGN_CENTER_VERTICAL, 0)
446
        sizer_16.Add((50, 20), 0, 0, 0)
447
        sizer_16.Add(self.label_4, 0, wx.RIGHT|wx.ALIGN_CENTER_VERTICAL, 0)
448
        sizer_16.Add((20, 20), 0, 0, 0)
449
        sizer_16.Add(self.speedCtrl, 0, wx.ALIGN_CENTER_VERTICAL, 0)
683 FredericG 450
        sizer_13.Add(sizer_16, 0, wx.EXPAND, 0)
633 FredericG 451
        sizer_7.Add(sizer_13, 1, wx.EXPAND, 0)
452
        sizer_7.Add((20, 20), 0, 0, 0)
453
        sizer_7.Add((20, 20), 0, 0, 0)
683 FredericG 454
        sizer_9.Add(sizer_7, 0, 0, 0)
633 FredericG 455
        sizer_9.Add(self.bitmap_button_1, 0, 0, 0)
600 FredericG 456
        sizer_8.Add(sizer_9, 0, 0, 0)
633 FredericG 457
        sizer_17.Add((20, 20), 0, 0, 0)
458
        sizer_17.Add(self.static_line_1, 0, wx.EXPAND, 0)
459
        sizer_17.Add((20, 20), 0, 0, 0)
460
        sizer_8.Add(sizer_17, 0, wx.EXPAND, 0)
626 FredericG 461
        sizer_11.Add(self.graphCtrl, 1, wx.EXPAND, 0)
600 FredericG 462
        sizer_11.Add((20, 5), 0, 0, 0)
463
        sizer_12.Add(self.label_40, 0, wx.ALIGN_CENTER_VERTICAL, 0)
464
        sizer_12.Add(self.graphTypeChoice, 0, 0, 0)
465
        sizer_12.Add((40, 20), 0, 0, 0)
466
        sizer_12.Add(self.label_41, 0, wx.ALIGN_CENTER_VERTICAL, 0)
467
        sizer_12.Add(self.yAxisChoice, 0, 0, 0)
627 FredericG 468
        sizer_12.Add((80, 20), 0, 0, 0)
469
        sizer_12.Add(self.copyGraphButton, 0, 0, 0)
600 FredericG 470
        sizer_11.Add(sizer_12, 0, 0, 0)
471
        sizer_8.Add(sizer_11, 0, 0, 0)
472
        sizer_8.Add((20, 30), 0, 0, 0)
473
        sizer_8.Add(self.TestListCtrl, 1, 0, 0)
474
        sizer_8.Add((20, 20), 0, 0, 0)
475
        sizer_3.Add(sizer_8, 1, wx.EXPAND, 0)
476
        self.SetSizer(sizer_3)
584 FredericG 477
        self.Layout()
600 FredericG 478
        self.SetSize((850, 700))
584 FredericG 479
        # end wxGlade
480
 
590 FredericG 481
        # List events
482
        self.TestListCtrl.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnTestSelected, self.TestListCtrl)
483
 
586 FredericG 484
        # Configure Graph
626 FredericG 485
        #self.graphCtrl = wx.lib.plot.PlotCanvas(self.GraphPanel, size=(800,300))
593 FredericG 486
 
626 FredericG 487
        self.graphCtrl.SetPointLabelFunc(self.DrawPointLabel)
585 FredericG 488
 
626 FredericG 489
        self.graphCtrl.SetFont(wx.Font(10,wx.SWISS,wx.NORMAL,wx.NORMAL))
490
        self.graphCtrl.SetFontSizeAxis(10)
491
        self.graphCtrl.SetFontSizeLegend(7)
492
        self.graphCtrl.setLogScale((False,False))
585 FredericG 493
 
586 FredericG 494
 
495
        # Configure TestListCtrl
594 FredericG 496
        self.TestListCtrl.InsertColumn(0, "Description")
619 FredericG 497
        self.TestListCtrl.InsertColumn(1, "Voltage")
498
        self.TestListCtrl.InsertColumn(2, "Speed")
499
        self.TestListCtrl.InsertColumn(3, "Channel")
500
        self.TestListCtrl.InsertColumn(4, "Vibration Value")
501
        self.TestListCtrl.SetColumnWidth(4, 500)
586 FredericG 502
 
585 FredericG 503
    def DrawPointLabel(self, dc, mDataDict):
504
        """This is the fuction that defines how the pointLabels are plotted
505
            dc - DC that will be passed
506
            mDataDict - Dictionary of data that you want to use for the pointLabel
507
 
508
            As an example I have decided I want a box at the curve point
509
            with some text information about the curve plotted below.
510
            Any wxDC method can be used.
511
        """
512
        # ----------
513
        dc.SetPen(wx.Pen(wx.BLACK))
514
        dc.SetBrush(wx.Brush( wx.BLACK, wx.SOLID ) )
515
 
516
        sx, sy = mDataDict["scaledXY"] #scaled x,y of closest point
517
        dc.DrawRectangle( sx-5,sy-5, 10, 10)  #10by10 square centered on point
518
        px,py = mDataDict["pointXY"]
519
        cNum = mDataDict["curveNum"]
520
        pntIn = mDataDict["pIndex"]
521
        legend = mDataDict["legend"]
522
        #make a string to display
523
        s = "Crv# %i, '%s', Pt. (%.2f,%.2f), PtInd %i" %(cNum, legend, px, py, pntIn)
524
        dc.DrawText(s, sx , sy+1)
525
        # -----------
526
 
596 FredericG 527
 
528
    def onNewTest(self, test):
529
        index = self.TestListCtrl.InsertStringItem(sys.maxint, test.descr)
645 FredericG 530
        self._fillRowInTestList(index, test)
531
        self.TestListCtrl.Select(index)
532
 
533
    def _fillRowInTestList(self, index, test):
534
        self.TestListCtrl.SetStringItem(index, 0, test.descr)
619 FredericG 535
        self.TestListCtrl.SetStringItem(index, 1, "%.1f V" %test.voltage)
536
        self.TestListCtrl.SetStringItem(index, 2, str(test.speed))
537
        self.TestListCtrl.SetStringItem(index, 3, test.channel)
607 FredericG 538
 
649 FredericG 539
        vv = test.getVibValue()
648 FredericG 540
        vvs = "|%s| (%.1f)" % ("----------------------------------------------------------------------------------------------------"[0:min(int(vv+1)/2,100)], vv)
619 FredericG 541
        self.TestListCtrl.SetStringItem(index, 4, vvs)
596 FredericG 542
 
645 FredericG 543
    def refreshData(self):
544
        for idx in range(len(self.app.VibTests)):
545
            self._fillRowInTestList(idx, self.app.getTest(idx))
546
        self.drawGraph()
547
 
590 FredericG 548
    def OnTestSelected(self, event):
549
         testId = event.m_itemIndex
550
         print "Test Selected id=%d" % (testId)
592 FredericG 551
         self.activeTestId = testId
552
         self.drawGraph()
636 FredericG 553
 
554
 
555
    def orderSelectedTests(self):
556
        tests = []
557
        idx = self.TestListCtrl.GetFirstSelected()
558
        while idx != -1:
559
            header = "%s %s"%(self.app.getTest(idx).descr,self.app.getTest(idx).channel)
560
            found = False
561
            for t in tests:
562
              if t[0] == header:
563
                t.append(idx)
564
                found = True
565
                break
566
            if not found:
567
                tests.append([header, idx])
568
            idx = self.TestListCtrl.GetNextSelected(idx)
569
        return tests
690 FredericG 570
 
571
    def OnMouseLeftDown(self,event):
572
        x,y = self.graphCtrl._getXY(event)
573
        s= "Left Mouse Down at Point: (%.4f, %.4f)" % (x,y)
574
        print s
575
        if self.measureState == 0:
576
            self.measureX1 = x
577
            self.measureState += 1
578
        elif self.measureState == 1:
579
            dx = x-self.measureX1
580
            rpm = 60.0*1000/dx
581
            s = "Time-Difference: %.1fms\n"%dx
692 FredericG 582
            for i in range(1,8):
690 FredericG 583
                s += "\n%dT -> %d RPM" %(i,rpm*i)
584
            dial = wx.MessageDialog(None, s, 'RPM Measurement', wx.OK )
585
            dial.ShowModal()
586
 
587
            self.measureState = 0
588
 
636 FredericG 589
 
590 FredericG 590
 
592 FredericG 591
    def drawGraph(self):
607 FredericG 592
 
600 FredericG 593
         y = int(self.yAxisChoice.GetStringSelection())
590 FredericG 594
 
607 FredericG 595
         nbSelected = self.TestListCtrl.SelectedItemCount
596 FredericG 596
 
616 FredericG 597
         if nbSelected == 0:
626 FredericG 598
              self.graphCtrl.Clear()
616 FredericG 599
 
600
         elif nbSelected > 1:
607 FredericG 601
             self.graphTypeChoice.Disable()
627 FredericG 602
             self.copyGraphButton.Enable()
636 FredericG 603
 
604
             tests = self.orderSelectedTests()
605
 
606
             lines = []
607
             maxX = 0
608
             cCnt = 0
609
             for s in tests:
610
               data = []
611
               x=1
612
               for t in s[1:]:
649 FredericG 613
                 data.append([x,self.app.getTest(t).getVibValue()])
607 FredericG 614
                 x += 1
636 FredericG 615
               lines.append(wx.lib.plot.PolyLine(data, legend= s[0], colour=COLORS[cCnt], width=2))
616
               lines.append(wx.lib.plot.PolyMarker(data, legend= "", colour=COLORS[cCnt], marker='circle',size=2))
617
               maxX = max(maxX, x)
618
               cCnt += 1
619
 
607 FredericG 620
             title = "Comparing tests"
629 FredericG 621
             self.graphCtrl.setLogScale((False,False))
636 FredericG 622
             self.graphCtrl.Draw(wx.lib.plot.PlotGraphics(lines, title, "Test", "Vibration Value"), xAxis=(1,maxX), yAxis=(0,y))
626 FredericG 623
             self.graphCtrl.SetEnableGrid('Horizontal')
636 FredericG 624
             self.graphCtrl.SetEnableLegend(True)
625
 
600 FredericG 626
 
607 FredericG 627
         else:
628
             self.graphTypeChoice.Enable()
627 FredericG 629
             self.copyGraphButton.Disable()
607 FredericG 630
             vibTest = self.app.getTest(self.activeTestId)
631
             nb = vibTest.getDataLen()
590 FredericG 632
 
607 FredericG 633
             if self.graphTypeChoice.GetSelection() == 0:
634
                 xydata = _Numeric.linspace(0,0.09*nb,2*nb)
635
                 xydata.shape = (nb, 2)
636
                 xydata[:,1] = vibTest.getRawData()
637
                 line = wx.lib.plot.PolyLine(xydata, legend= 'Raw Data', colour='red', width=2)
638
 
639
                 title = "Raw Signal: %s %s %d" %(vibTest.descr, vibTest.channel, vibTest.speed)
629 FredericG 640
                 self.graphCtrl.setLogScale((False,False))
643 FredericG 641
                 self.graphCtrl.Draw(wx.lib.plot.PlotGraphics([line], title, "Time (ms)", "Acc"), yAxis= (-y/2,y/2))
626 FredericG 642
                 self.graphCtrl.SetEnableGrid('Horizontal')
636 FredericG 643
                 self.graphCtrl.SetEnableLegend(False)
644
 
599 FredericG 645
 
607 FredericG 646
             if self.graphTypeChoice.GetSelection() == 1:
647
                 xydata = _Numeric.linspace(0,0.09*nb,2*nb)
648
                 xydata.shape = (nb, 2)
649 FredericG 649
                 xydata[:,1] = vibTest.getFilteredData()
607 FredericG 650
                 line = wx.lib.plot.PolyLine(xydata, legend= 'Raw Data', colour='red', width=2)
651
 
652
                 title = "Filtered Signal: %s %s %d" %(vibTest.descr, vibTest.channel, vibTest.speed)
629 FredericG 653
                 self.graphCtrl.setLogScale((False,False))
643 FredericG 654
                 self.graphCtrl.Draw(wx.lib.plot.PlotGraphics([line], title, "Time (ms)", "Acc"), yAxis= (-y/2,y/2))
626 FredericG 655
                 self.graphCtrl.SetEnableGrid('Horizontal')
636 FredericG 656
                 self.graphCtrl.SetEnableLegend(False)
607 FredericG 657
 
658
             elif self.graphTypeChoice.GetSelection() == 2:
615 FredericG 659
                 xydata = _Numeric.linspace(0,FS/2,nb)
607 FredericG 660
                 xydata.shape = (nb/2, 2)
661
 
662
                 xydata[:,1] = vibTest.getSpectrum()
629 FredericG 663
 
664
                 #print xydata
607 FredericG 665
 
666
                 line = wx.lib.plot.PolyLine(xydata, legend= 'Spectrum', colour='red')
667
                 markers = wx.lib.plot.PolyMarker(xydata, legend= '', colour='red', marker='circle',size=2)
615 FredericG 668
 
669
                 fc = self.app.settings["hpf"].value
670
                 filterLine1 = wx.lib.plot.PolyLine(((fc,0),(fc,y)), legend='HP Filter', colour='Black', width=4)
671
                 fc = self.app.settings["lpf"].value
672
                 filterLine2 = wx.lib.plot.PolyLine(((fc,0),(fc,y)), legend='HP Filter', colour='Black', width=4)
607 FredericG 673
 
674
                 title = "Spectrum: %s %s %d" %(vibTest.descr, vibTest.channel, vibTest.speed)
632 FredericG 675
                 self.graphCtrl.setLogScale((True,False))
676
                 self.graphCtrl.Draw(wx.lib.plot.PlotGraphics([line,markers, filterLine1, filterLine2], title, "Freq (Hz)", "Acc"), xAxis=(20,500), yAxis= (0,y))
636 FredericG 677
                 self.graphCtrl.SetEnableGrid(True)
678
                 self.graphCtrl.SetEnableLegend(False)
629 FredericG 679
 
590 FredericG 680
 
599 FredericG 681
 
587 FredericG 682
    def OnImport(self, event): # wxGlade: MainFrame.<event_handler>
606 FredericG 683
        dlg = wx.FileDialog(
684
            self, message="Choose a file",
619 FredericG 685
            defaultDir="%s/Data/" % os.getcwd(),
637 FredericG 686
            defaultFile=".",
687
            wildcard="Text files (*.txt)|*.txt|All files (*.*)|*.*",
606 FredericG 688
            style=wx.OPEN | wx.CHANGE_DIR
689
            )
690
        if dlg.ShowModal() == wx.ID_OK:
691
            paths = dlg.GetPaths();
619 FredericG 692
            self.app.loadTests(paths[0])
606 FredericG 693
        dlg.Destroy()
587 FredericG 694
 
619 FredericG 695
    def onExport(self, event): # wxGlade: MainFrame.<event_handler>
696
        dlg = wx.FileDialog(
697
              self, message="Save file as ...",
698
              defaultDir="%s/Data/" % os.getcwd(),
637 FredericG 699
              defaultFile=".",
700
              wildcard="Text files (*.txt)|*.txt|All files (*.*)|*.*",
619 FredericG 701
              style=wx.SAVE
702
              )
703
        if dlg.ShowModal() == wx.ID_OK:
704
            paths = dlg.GetPaths();
705
            self.app.saveTests(paths[0])
706
        dlg.Destroy()
707
 
599 FredericG 708
    def onYAxisChange(self, event): # wxGlade: MainFrame.<event_handler>
592 FredericG 709
        self.drawGraph()
710
 
600 FredericG 711
    def onGraphTypeChange(self, event): # wxGlade: MainFrame.<event_handler>
599 FredericG 712
        self.drawGraph()
713
 
607 FredericG 714
    def OnSettings(self, event): # wxGlade: MainFrame.<event_handler>
715
        dlg = SettingsDialog(self, -1, "Sample Dialog", size=(350, 200),
716
                         #style=wx.CAPTION | wx.SYSTEM_MENU | wx.THICK_FRAME,
717
                         style=wx.DEFAULT_DIALOG_STYLE, # & ~wx.CLOSE_BOX
718
                         )
719
        dlg.CenterOnScreen()
611 FredericG 720
        val = dlg.ShowModal()  # this does not return until the dialog is closed.
607 FredericG 721
        dlg.Destroy()
648 FredericG 722
        self.app.onSettingsChanged(True)
607 FredericG 723
 
612 FredericG 724
    def onStartMeasure(self, event): # wxGlade: MainFrame.<event_handler>
613 FredericG 725
        # Collect measure parameters
726
        mp = MeasureParameters()
651 FredericG 727
        decoding = ""
640 FredericG 728
 
729
        try:
651 FredericG 730
          decoding = "Description"
640 FredericG 731
          mp.descr = self.descrCtrl.GetValue()
651 FredericG 732
 
733
          decoding = "Motor(s)"
640 FredericG 734
          mp.motors = map(int,self.motorsCtrl.GetValue().split(','))
651 FredericG 735
          for motor in mp.motors:
736
              if (motor<1) or (motor>MOTOR_MAX):
737
                  raise Exception("Motor number should be between 1 and %d" % MOTOR_MAX)
738
 
739
          decoding = "Channel(s)"
640 FredericG 740
          mp.channels = []
683 FredericG 741
          if self.gyroYawCb.IsChecked(): mp.channels.append(0)
742
          if self.gyroRollCb.IsChecked(): mp.channels.append(1)
743
          if self.gyroNickCb.IsChecked(): mp.channels.append(2)
640 FredericG 744
          if self.accTopCb.IsChecked(): mp.channels.append(5)
745
          if self.accRollCb.IsChecked(): mp.channels.append(6)
746
          if self.accNickCb.IsChecked(): mp.channels.append(7)
651 FredericG 747
 
748
          decoding = "Speed(s)"
646 FredericG 749
          mp.speeds = []
750
          for speedTxt in self.speedCtrl.GetValue().split(","):
751
              if speedTxt.count("-") == 1:
752
                  # assume from-to:step format
753
                  speedTxt = speedTxt.split("-")
754
                  if len(speedTxt) != 2: raise Exception("Invalid format")
755
                  speedTxt[1] = speedTxt[1].split(":")
756
                  if len(speedTxt[1]) != 2: raise Exception("Invalid format")
757
                  mp.speeds = range(int(speedTxt[0]),int(speedTxt[1][0])+int(speedTxt[1][1]),int(speedTxt[1][1]))
758
              else:
759
                  # assume s or s*n format
760
                  if speedTxt.count("*") == 1:
761
                      speedTxt = speedTxt.split("*")
762
                      for i in range(int(speedTxt[0])):
763
                        mp.speeds.append(int(speedTxt[1]))
764
                  else:
765
                      mp.speeds.append(int(speedTxt))
651 FredericG 766
          for speed in mp.speeds:
767
                if (speed<0) or (speed>255):
768
                    raise Exception("Speed values should be between 0 and 255")
769
 
640 FredericG 770
        except Exception,e:
651 FredericG 771
          dial = wx.MessageDialog(None, 'Invalid paramter \"%s\"\n\n%s' % (decoding, str(e)), 'Error', wx.OK |
640 FredericG 772
            wx.ICON_ERROR)
773
          dial.ShowModal()
774
          raise e
775
 
776
 
614 FredericG 777
 
633 FredericG 778
        print mp.descr
779
        print mp.motors
780
        print mp.channels
781
        print mp.speeds
613 FredericG 782
 
633 FredericG 783
 
784
 
612 FredericG 785
        # create the dialog that will show the satus
786
        dlg = MeasureDialog(self)
787
        dlg.CenterOnScreen()
613 FredericG 788
 
789
        # Signal the application
790
        self.app.startMeasure(mp, dlg)
791
 
612 FredericG 792
        # Show the dialog
793
        val = dlg.ShowModal()  # this does not return until the dialog is closed.
794
        dlg.Destroy()
795
 
616 FredericG 796
    def _removeTest(self, idx):
797
        print "Deleting test %d" % idx
798
        self.app.removeTest(idx)
799
        self.TestListCtrl.DeleteItem(idx)
800
 
801
 
802
    def onClear(self, event): # wxGlade: MainFrame.<event_handler>
639 FredericG 803
        dial = wx.MessageDialog(None, 'Clear ALL tests?', 'Question',
804
            wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION)
805
        if dial.ShowModal() == wx.ID_YES:
806
          print "Clear all tests"
807
          for i in range(len(self.app.VibTests)-1, -1, -1):
808
              self._removeTest(i)
809
          self.drawGraph()
616 FredericG 810
 
811
 
812
    def onClearSelected(self, event): # wxGlade: MainFrame.<event_handler>
639 FredericG 813
        dial = wx.MessageDialog(None, 'Clear Selected tests?', 'Question',
814
            wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION)
815
        if dial.ShowModal() == wx.ID_YES:
816
          while True:
817
              idx = self.TestListCtrl.GetFirstSelected()
818
              if idx == -1: break
819
              self._removeTest(idx)
616 FredericG 820
 
627 FredericG 821
 
626 FredericG 822
 
823
    def onAbout(self, event): # wxGlade: MainFrame.<event_handler>
824
         # First we create and fill the info object
825
        print "about"
826
        info = wx.AboutDialogInfo()
651 FredericG 827
        info.Name = "MK Vibration Test - "
693 FredericG 828
        info.Version = "v1.2 ($Rev: 693 $)".replace("$","")
626 FredericG 829
        info.Copyright = ""
651 FredericG 830
        info.Developers=["Frederic Goddeeris  (Frederic@rc-flight.be)"]
626 FredericG 831
        info.Description = "Please consult the WIKI page for a complete description of the tool:"
832
        info.WebSite = ("http://www.mikrokopter.de/ucwiki/en/VibrationTest", "VibrationTest WIKI page")
833
        wx.AboutBox(info)
834
 
835
 
836
    def onExit(self, event): # wxGlade: MainFrame.<event_handler>
837
        self.Close(True)
838
 
839
 
627 FredericG 840
    def onSelectAll(self, event): # wxGlade: MainFrame.<event_handler>
841
        for i in xrange(self.TestListCtrl.GetItemCount()):
842
          self.TestListCtrl.Select(i)
843
 
844
    def onCopyGraphData(self, event): # wxGlade: MainFrame.<event_handler>
845
        clipdata = wx.TextDataObject()
846
        txt = ""
847
        idx = self.TestListCtrl.GetFirstSelected()
848
        while idx != -1:
649 FredericG 849
             txt += ("%d\n" % self.app.getTest(idx).getVibValue())
627 FredericG 850
             idx = self.TestListCtrl.GetNextSelected(idx)
851
        clipdata.SetText(txt)
852
        wx.TheClipboard.Open()
853
        wx.TheClipboard.SetData(clipdata)
854
        wx.TheClipboard.Close()
855
 
584 FredericG 856
# end of class MainFrame
857
 
607 FredericG 858
class Setting:
859
    def __init__(self, descr, defaultValue):
860
        self.descr = descr
861
        self.value = defaultValue
611 FredericG 862
 
863
    def set(self, newValue):
864
        if isinstance(self.value, int):
865
            self.value = int(newValue)
866
        else:
867
            self.value = str(newValue)
584 FredericG 868
 
613 FredericG 869
class MeasureParameters:
870
      pass
612 FredericG 871
 
872
class MeasureThread:
613 FredericG 873
    def __init__(self, measureParameters, evtConsumer):
874
        self.mk = mkProto.MkComm()
875
        self.param = measureParameters
612 FredericG 876
        self.evtConsumer = evtConsumer
613 FredericG 877
        self.cancel = False
878
        self.running = False
612 FredericG 879
 
880
    def start(self):
881
        thread.start_new_thread(self._run, ())
882
 
613 FredericG 883
    def stop(self):
884
        self.cancel = True
885
 
886
    def _testCancel(self):
887
        if self.cancel:
888
            raise Exception("Operation cancelled")
889
 
623 FredericG 890
    def _sendEvent(self, msg=None, error=False, parVoltage=None, speed=None):
891
        evt = MeasStatusUpdateEvent(running=self.running, msg=msg, error=error, voltage=parVoltage, speed=speed)
613 FredericG 892
        wx.PostEvent(self.evtConsumer, evt)
893
 
894
    def _setMotorSpeed(self, speed, settlingTime):
651 FredericG 895
        speeds = [0]*MOTOR_MAX
638 FredericG 896
 
613 FredericG 897
        for motor in self.param.motors:
898
            speeds[motor-1] = speed
899
        for i in range(int(settlingTime*10)):
900
          self._testCancel()
901
          self.mk.setMotorTest(speeds)
902
          time.sleep(.1)
646 FredericG 903
        self.currSpeed = speed
613 FredericG 904
 
905
 
612 FredericG 906
    def _run(self):
613 FredericG 907
        self.running = True
908
        self._sendEvent("Starting test \"%s\"" % self.param.descr)    
646 FredericG 909
        self.currSpeed = 0
910
 
613 FredericG 911
        try:
912
            self._sendEvent("Opening SerialPort \"%s\"" % self.param.serialPort)
913
            self.mk.open(comPort=self.param.serialPort)
653 FredericG 914
 
915
            print "Sending FC->NC forwarding",
916
            self.mk.sendNCRedirectUartFromFC()
917
            print "Done"
612 FredericG 918
 
613 FredericG 919
            msg = self.mk.getVersionMsg()
920
            version = msg.getVersion()
921
            self._sendEvent("Version: %d.%d" % version)
922
 
923
            msg = self.mk.getDebugMsg()
924
            voltage = msg.getVoltage()
925
            if (voltage == 0):
628 FredericG 926
              # Board is probably fed by USB
613 FredericG 927
              minVoltage = 0
623 FredericG 928
              maxVoltage = 1
613 FredericG 929
            else:
628 FredericG 930
              # Determine the n umber of cells
613 FredericG 931
              if (voltage > 4.2*3):
623 FredericG 932
                nbCells = 4  
613 FredericG 933
              else:
623 FredericG 934
                nbCells = 3
628 FredericG 935
              # Set minimum and maximum voltages
936
              if self.param.minVoltage > 0:
937
                minVoltage =  self.param.minVoltage
938
              else:
939
                minVoltage = nbCells*3.5  # auto
940
              if self.param.maxVoltage > 0:
941
                maxVoltage =  self.param.maxVoltage
942
              else:
943
                maxVoltage = nbCells*3.9  
944
 
613 FredericG 945
            self._sendEvent("Voltage: %2.1fV" % voltage)
623 FredericG 946
            self._sendEvent("Min/Max Voltage: %2.1fV-%2.1fV" % (minVoltage, maxVoltage), parVoltage=(minVoltage, maxVoltage, voltage))
947
 
948
            self._sendEvent("Starting motor(s) (speed=%d)... " % self.param.motorStartupSpeed, speed=self.param.motorStartupSpeed)
613 FredericG 949
            self._setMotorSpeed(self.param.motorStartupSpeed, self.param.motorStartupSettlingTime)
950
 
951
            for speed in self.param.speeds:
646 FredericG 952
                if speed != self.currSpeed:
953
                    self._sendEvent("Changing motor speed to %d... " % speed, speed=speed)
954
                    self._setMotorSpeed(speed, 1)
613 FredericG 955
 
956
                for channel in self.param.channels:
957
                    self._setMotorSpeed(speed, .1)
619 FredericG 958
                    msg = self.mk.getDebugMsg()
959
                    voltage = msg.getVoltage()
960
 
623 FredericG 961
                    self._sendEvent("Getting data from channel %s" % CHANNEL_NAMES[channel], parVoltage=(minVoltage, maxVoltage, voltage))
613 FredericG 962
                    data = self.mk.doVibrationTest(1000, channel)
963
 
619 FredericG 964
                    vt = VibTest(self.param.descr, voltage, self.param.motors, speed, CHANNEL_NAMES[channel], data)
613 FredericG 965
                    evt = MeasDataEvent(vibTest = vt)
966
                    wx.PostEvent(self.evtConsumer, evt)
967
 
619 FredericG 968
                    if voltage<minVoltage:
969
                        raise Exception("Voltage too low")
634 FredericG 970
 
971
 
972
            self._setMotorSpeed(speed, .1)    
973
            time.sleep(1)
974
            msg = self.mk.getDebugMsg()
975
            voltage = msg.getVoltage()
976
 
977
            self._sendEvent("Done !", parVoltage=(minVoltage, maxVoltage, voltage))            
978
 
613 FredericG 979
        except Exception, e:
980
            self._sendEvent("Exception \"%s\"" % e, error=True)  
647 FredericG 981
 
982
        try:        
983
          self.mk.close()
984
        except:
985
          print "Failure closing MK serial port"
986
          pass
987
 
613 FredericG 988
        self.running = False
629 FredericG 989
        self._sendEvent("", speed = 0)    
613 FredericG 990
 
612 FredericG 991
 
586 FredericG 992
class VibTest:
648 FredericG 993
    useRms = True
649 FredericG 994
    fc1 = None
995
    fc2 = None
996
 
648 FredericG 997
 
619 FredericG 998
    def __init__(self, descr, voltage, motor, speed, channel, rawData):
594 FredericG 999
        self.descr = descr
619 FredericG 1000
        self.voltage = voltage
594 FredericG 1001
        self.motor = motor
1002
        self.speed = speed
596 FredericG 1003
        self.channel = channel
599 FredericG 1004
 
1005
        self.dataLen = len(rawData)
1006
 
590 FredericG 1007
        self.rawData = _Numeric.array(rawData)
1008
        self.dc = self.rawData.mean()
1009
        self.rawData -= self.dc
586 FredericG 1010
 
600 FredericG 1011
        self.fft = _Numeric.fft.rfft(self.rawData)
1012
 
1013
        self.spectrum = None
1014
        self.filteredData = None
599 FredericG 1015
 
602 FredericG 1016
        self.vibValue = None
1017
 
594 FredericG 1018
    def getDescr(self):
1019
        return self.Descr
587 FredericG 1020
 
590 FredericG 1021
    def getRawData(self):
1022
        return self.rawData
1023
 
1024
    def getDataLen(self):
1025
        return self.dataLen
1026
 
599 FredericG 1027
    def getSpectrum(self):
600 FredericG 1028
        if self.spectrum == None:
1029
            self.spectrum = _Numeric.absolute(self.fft[1:self.dataLen/2+1]) / (self.dataLen/2)
1030
        return self.spectrum
648 FredericG 1031
 
1032
    def refresh(self):
1033
        self.filteredData = None
1034
        self.vibValue = None
590 FredericG 1035
 
649 FredericG 1036
    def getFilteredData(self):
600 FredericG 1037
        if self.filteredData == None:
1038
            tmpfft = self.fft.copy()
649 FredericG 1039
            fc = (float(self.fc1))/(FS/2)*len(tmpfft)
1040
            print "fc1=%d => fc=%f" % (self.fc1, fc)
644 FredericG 1041
            for i in range(0,int(fc)+2):
600 FredericG 1042
                tmpfft[i] = 0
649 FredericG 1043
            fc = (float(self.fc2))/(FS/2)*len(tmpfft)
1044
            print "fc2=%d => fc=%f" % (self.fc2,fc)
644 FredericG 1045
            for i in range(int(fc)+2, len(tmpfft)):
600 FredericG 1046
                tmpfft[i] = 0
1047
            self.filteredData = _Numeric.fft.irfft(tmpfft)
615 FredericG 1048
 
600 FredericG 1049
        return self.filteredData
602 FredericG 1050
 
649 FredericG 1051
    def getVibValue(self):
602 FredericG 1052
      if self.vibValue == None:
649 FredericG 1053
        fd = self.getFilteredData()[100:-100];
648 FredericG 1054
        if self.useRms:
1055
            print "RMS"
1056
            self.vibValue = math.sqrt(sum([x*x for x in fd])/len(fd))*2*math.sqrt(2)
1057
        else:
1058
            print "PP"
1059
            self.vibValue = max(fd)-min(fd)
602 FredericG 1060
      return self.vibValue
599 FredericG 1061
 
607 FredericG 1062
 
1063
 
584 FredericG 1064
class App(wx.App):
607 FredericG 1065
 
1066
    SETTINGSFILE = "settings.cfg"
1067
 
586 FredericG 1068
    def __init__(self, par):
1069
        self.VibTests = []
1070
        wx.App.__init__(self, par)
1071
 
607 FredericG 1072
        # Init settings
1073
        self.settings={}
611 FredericG 1074
        self.settings["serialport"] = Setting("Serial Port", "COM1")
613 FredericG 1075
        self.settings["startupspeed"] = Setting("Motor Startup Speed", 25)
1076
        self.settings["startupsettling"] = Setting("Motor Startup Setting time (s)", 3)
1077
        self.settings["serialport"] = Setting("Serial Port", "COM1")
644 FredericG 1078
        self.settings["hpf"] = Setting("HP Filter cutoff (Hz)", 40)
632 FredericG 1079
        self.settings["lpf"] = Setting("LP Filter cutoff (Hz)", 400)
648 FredericG 1080
        self.settings["calcmethod"] = Setting("Calculation Method", "rms")        
628 FredericG 1081
        self.settings["minvoltage"] = Setting("Minimum Bettery Voltage (0=Automatic) (V) ", 0)
1082
        self.settings["maxvoltage"] = Setting("Maximum Bettery Voltage (0=Automatic) (V) ", 0)
607 FredericG 1083
 
628 FredericG 1084
 
607 FredericG 1085
        self.readSettings()
1086
 
606 FredericG 1087
        if len(sys.argv)>1:
619 FredericG 1088
            self.loadTests(sys.argv[1])
586 FredericG 1089
 
606 FredericG 1090
 
607 FredericG 1091
    def readSettings(self):
1092
        print "Reading settings"
1093
        cp = ConfigParser.ConfigParser()
1094
 
1095
        try:
644 FredericG 1096
            cp.read("%s/%s" % (rootPath, App.SETTINGSFILE))
607 FredericG 1097
            for setting in cp.items("DEFAULT"):
1098
                print " ",setting
1099
                try:
613 FredericG 1100
                    self.settings[setting[0]].set(setting[1])
607 FredericG 1101
                except:
1102
                    print "WARNING, unknown setting"
1103
        except:
1104
            print "ERROR reading settingsfile"
648 FredericG 1105
        self.onSettingsChanged(False)
607 FredericG 1106
 
1107
    def storeSettings(self):
1108
        print "Storing settings"
1109
 
1110
        cp = ConfigParser.ConfigParser()
1111
        for setting in self.settings.iteritems():
1112
            cp.set("", setting[0], setting[1].value)
1113
 
644 FredericG 1114
        file = open("%s/%s" % (rootPath, App.SETTINGSFILE), "w")
607 FredericG 1115
        cp.write(file)
1116
        file.close()
1117
 
611 FredericG 1118
 
648 FredericG 1119
    def onSettingsChanged(self, store):
1120
        if store:
1121
            self.storeSettings()
649 FredericG 1122
 
648 FredericG 1123
        if self.settings["calcmethod"].value == "rms":
1124
            VibTest.useRms = True
1125
        else:
1126
            VibTest.useRms = False
649 FredericG 1127
 
1128
        VibTest.fc1 = self.settings["hpf"].value
1129
        VibTest.fc2 = self.settings["lpf"].value
1130
 
648 FredericG 1131
        for test in self.VibTests:
1132
            test.refresh()
645 FredericG 1133
        self.frame_1.refreshData()
613 FredericG 1134
 
1135
    def AddTest2(self, vibTest):
1136
        self.VibTests.append(vibTest)
1137
        self.frame_1.onNewTest(vibTest)
611 FredericG 1138
 
619 FredericG 1139
    def AddTest(self, descr, voltage, motor, speed, channel, rawData):
1140
        test = VibTest(descr, voltage, motor, speed, channel, rawData)
613 FredericG 1141
        self.AddTest2(test)
586 FredericG 1142
 
616 FredericG 1143
    def removeTest(self, idx):
1144
        del(self.VibTests[idx])
1145
 
590 FredericG 1146
    def getTest(self, testId):
1147
        return self.VibTests[testId]
1148
 
584 FredericG 1149
    def OnInit(self):
1150
        wx.InitAllImageHandlers()
586 FredericG 1151
        self.frame_1 = MainFrame(None, -1, "")
587 FredericG 1152
        self.frame_1.setApp(self);
586 FredericG 1153
        self.SetTopWindow(self.frame_1)
1154
 
607 FredericG 1155
        self.frame_1.CenterOnScreen()
587 FredericG 1156
        self.frame_1.Show()
1157
        return 1
1158
 
619 FredericG 1159
    def saveTests(self, filePath):
1160
        try:
1161
          logfile = open(filePath, "r")
1162
          newFile = False
1163
          logfile.close()
1164
        except:
1165
          newFile = True
1166
 
1167
        for test in self.VibTests:
1168
          if newFile:
1169
            logfile = open(filePath, "w")
1170
            print "Writing result to %s ..." % filePath,
1171
            logfile.write("%s %d %s\n" % (test.descr, test.speed, test.channel))
1172
            for value in test.rawData:
1173
              logfile.write("%d\n" % value)
1174
            logfile.close()  
1175
            print "OK"
1176
          else:
1177
            print "Appending result to %s ..." % filePath,
1178
            logfile = open(filePath, "r")
1179
            prevData = []
1180
            for line in logfile:
1181
              prevData.append(line[:-1])
1182
            logfile.close()
1183
            logfile = open(filePath, "w")
1184
            logfile.write("%s,%s %d %s\n" % (prevData[0], test.descr, test.speed, test.channel))
1185
            i = 1
1186
            for value in test.rawData:
1187
              logfile.write("%s,%d\n" % (prevData[i], value))
1188
              i += 1
1189
            logfile.close()
1190
            print "OK"
1191
          newFile = False
1192
 
1193
 
1194
    def loadTests(self, filePath):
596 FredericG 1195
 
606 FredericG 1196
        print "Importing file \"%s\"" % filePath
596 FredericG 1197
 
1198
        logfile = open(filePath, "r")
590 FredericG 1199
        data = None
596 FredericG 1200
 
619 FredericG 1201
        headers = (logfile.readline()[:-1]).split(',')
596 FredericG 1202
        nbCols = len(headers)
1203
        print "NbCols =", nbCols
1204
 
1205
        data = []
1206
        descr = []
1207
        speed = []
1208
        channel = []
1209
        for c in range(nbCols):
1210
            data.append([])
1211
            h = headers[c].split(' ')
1212
            descr.append(h[0]);
1213
            speed.append(h[1]);
1214
            channel.append(h[2]);
1215
 
590 FredericG 1216
        for line in logfile:
1217
            values = line.split(',')
596 FredericG 1218
            for i in range(nbCols):
1219
                data[i].append(int(values[i]))
590 FredericG 1220
        logfile.close()
596 FredericG 1221
 
1222
        for c in range(nbCols):
599 FredericG 1223
            if (len(data[c]) % 2) != 0:
1224
                data[c].append(data[c][-1])
619 FredericG 1225
            self.AddTest(descr[c], 0, 0, int(speed[c]), channel[c], data[c])
612 FredericG 1226
 
613 FredericG 1227
    def startMeasure(self, measureParams, dialog):
612 FredericG 1228
        print "Start measuring"
590 FredericG 1229
 
613 FredericG 1230
        measureParams.serialPort = self.settings["serialport"].value
1231
        measureParams.motorStartupSpeed = self.settings["startupspeed"].value
1232
        measureParams.motorStartupSettlingTime = self.settings["startupsettling"].value
628 FredericG 1233
        measureParams.minVoltage = self.settings["minvoltage"].value
1234
        measureParams.maxVoltage = self.settings["maxvoltage"].value        
613 FredericG 1235
 
1236
        self.measureThread = MeasureThread(measureParams, dialog)
612 FredericG 1237
        self.measureThread.start()
590 FredericG 1238
 
613 FredericG 1239
    def cancelMeasurement(self):
1240
        print "Measuring CANCEL"
1241
 
1242
        self.measureThread.stop()
1243
 
612 FredericG 1244
 
1245
 
1246
 
1247
 
590 FredericG 1248
 
586 FredericG 1249
 
590 FredericG 1250
 
584 FredericG 1251
# end of class App
1252
 
1253
if __name__ == "__main__":
626 FredericG 1254
 
1255
    rootPath = os.path.abspath(os.path.dirname(sys.argv[0]))
1256
 
1257
    print rootPath
1258
 
584 FredericG 1259
    VibrationTestGui = App(0)
1260
    VibrationTestGui.MainLoop()