Subversion Repositories Projects

Rev

Rev 706 | Rev 717 | 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: 709 $
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
 
700 FredericG 24
import MkProtocol
613 FredericG 25
 
26
 
27
 
28
CHANNEL_NAMES = ["GyroYaw", "GyroRoll", "GyroNick", "Pressure", "Batt", "AccTop", "AccRoll", "AccNick"]
651 FredericG 29
MOTOR_MAX = 16
30
 
709 FredericG 31
FS = 20
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 ")
709 FredericG 335
        self.yAxisChoice = wx.Choice(self, -1, choices=["10", "25", "50", "75", "100", "200", "500", "1000", "2000"])
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))
709 FredericG 676
                 self.graphCtrl.Draw(wx.lib.plot.PlotGraphics([line,markers, filterLine1, filterLine2], title, "Freq (Hz)", "Acc"), xAxis=(0.1,20), 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: 709 $)".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):
701 FredericG 874
        self.mk = MkProtocol.MkComm()
613 FredericG 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
 
709 FredericG 894
#    def _setMotorSpeed(self, speed, settlingTime):
895
#        speeds = [0]*MOTOR_MAX
896
#        
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)
903
#        self.currSpeed = speed
638 FredericG 904
 
613 FredericG 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))
709 FredericG 947
 
634 FredericG 948
            msg = self.mk.getDebugMsg()
949
            voltage = msg.getVoltage()
709 FredericG 950
 
951
            #data = self.mk.doVibrationTest(1000, channel)
952
            messages = self.mk.recordDbgMsg(0.05, 20*5)
953
            data = []
954
            for msg in messages:
955
                data.append(msg.getAngleRoll())
956
            print data
634 FredericG 957
 
709 FredericG 958
            vt = VibTest(self.param.descr, voltage, self.param.motors, 0, "AngleRoll", data)
959
            evt = MeasDataEvent(vibTest = vt)
960
            wx.PostEvent(self.evtConsumer, evt)
961
 
962
            if voltage<minVoltage:
963
                raise Exception("Voltage too low")
964
 
634 FredericG 965
            self._sendEvent("Done !", parVoltage=(minVoltage, maxVoltage, voltage))            
966
 
613 FredericG 967
        except Exception, e:
968
            self._sendEvent("Exception \"%s\"" % e, error=True)  
647 FredericG 969
 
970
        try:        
971
          self.mk.close()
972
        except:
973
          print "Failure closing MK serial port"
974
          pass
975
 
613 FredericG 976
        self.running = False
629 FredericG 977
        self._sendEvent("", speed = 0)    
613 FredericG 978
 
612 FredericG 979
 
586 FredericG 980
class VibTest:
648 FredericG 981
    useRms = True
649 FredericG 982
    fc1 = None
983
    fc2 = None
984
 
648 FredericG 985
 
619 FredericG 986
    def __init__(self, descr, voltage, motor, speed, channel, rawData):
594 FredericG 987
        self.descr = descr
619 FredericG 988
        self.voltage = voltage
594 FredericG 989
        self.motor = motor
990
        self.speed = speed
596 FredericG 991
        self.channel = channel
599 FredericG 992
 
993
        self.dataLen = len(rawData)
994
 
590 FredericG 995
        self.rawData = _Numeric.array(rawData)
996
        self.dc = self.rawData.mean()
997
        self.rawData -= self.dc
586 FredericG 998
 
600 FredericG 999
        self.fft = _Numeric.fft.rfft(self.rawData)
1000
 
1001
        self.spectrum = None
1002
        self.filteredData = None
599 FredericG 1003
 
602 FredericG 1004
        self.vibValue = None
1005
 
594 FredericG 1006
    def getDescr(self):
1007
        return self.Descr
587 FredericG 1008
 
590 FredericG 1009
    def getRawData(self):
1010
        return self.rawData
1011
 
1012
    def getDataLen(self):
1013
        return self.dataLen
1014
 
599 FredericG 1015
    def getSpectrum(self):
600 FredericG 1016
        if self.spectrum == None:
1017
            self.spectrum = _Numeric.absolute(self.fft[1:self.dataLen/2+1]) / (self.dataLen/2)
1018
        return self.spectrum
648 FredericG 1019
 
1020
    def refresh(self):
1021
        self.filteredData = None
1022
        self.vibValue = None
590 FredericG 1023
 
649 FredericG 1024
    def getFilteredData(self):
600 FredericG 1025
        if self.filteredData == None:
1026
            tmpfft = self.fft.copy()
649 FredericG 1027
            fc = (float(self.fc1))/(FS/2)*len(tmpfft)
1028
            print "fc1=%d => fc=%f" % (self.fc1, fc)
644 FredericG 1029
            for i in range(0,int(fc)+2):
600 FredericG 1030
                tmpfft[i] = 0
649 FredericG 1031
            fc = (float(self.fc2))/(FS/2)*len(tmpfft)
1032
            print "fc2=%d => fc=%f" % (self.fc2,fc)
644 FredericG 1033
            for i in range(int(fc)+2, len(tmpfft)):
600 FredericG 1034
                tmpfft[i] = 0
1035
            self.filteredData = _Numeric.fft.irfft(tmpfft)
615 FredericG 1036
 
600 FredericG 1037
        return self.filteredData
602 FredericG 1038
 
649 FredericG 1039
    def getVibValue(self):
602 FredericG 1040
      if self.vibValue == None:
649 FredericG 1041
        fd = self.getFilteredData()[100:-100];
648 FredericG 1042
        if self.useRms:
1043
            print "RMS"
1044
            self.vibValue = math.sqrt(sum([x*x for x in fd])/len(fd))*2*math.sqrt(2)
1045
        else:
1046
            print "PP"
1047
            self.vibValue = max(fd)-min(fd)
602 FredericG 1048
      return self.vibValue
599 FredericG 1049
 
607 FredericG 1050
 
1051
 
584 FredericG 1052
class App(wx.App):
607 FredericG 1053
 
1054
    SETTINGSFILE = "settings.cfg"
1055
 
586 FredericG 1056
    def __init__(self, par):
1057
        self.VibTests = []
1058
        wx.App.__init__(self, par)
1059
 
607 FredericG 1060
        # Init settings
1061
        self.settings={}
611 FredericG 1062
        self.settings["serialport"] = Setting("Serial Port", "COM1")
613 FredericG 1063
        self.settings["startupspeed"] = Setting("Motor Startup Speed", 25)
1064
        self.settings["startupsettling"] = Setting("Motor Startup Setting time (s)", 3)
1065
        self.settings["serialport"] = Setting("Serial Port", "COM1")
644 FredericG 1066
        self.settings["hpf"] = Setting("HP Filter cutoff (Hz)", 40)
632 FredericG 1067
        self.settings["lpf"] = Setting("LP Filter cutoff (Hz)", 400)
648 FredericG 1068
        self.settings["calcmethod"] = Setting("Calculation Method", "rms")        
628 FredericG 1069
        self.settings["minvoltage"] = Setting("Minimum Bettery Voltage (0=Automatic) (V) ", 0)
1070
        self.settings["maxvoltage"] = Setting("Maximum Bettery Voltage (0=Automatic) (V) ", 0)
607 FredericG 1071
 
628 FredericG 1072
 
607 FredericG 1073
        self.readSettings()
1074
 
606 FredericG 1075
        if len(sys.argv)>1:
619 FredericG 1076
            self.loadTests(sys.argv[1])
586 FredericG 1077
 
606 FredericG 1078
 
607 FredericG 1079
    def readSettings(self):
1080
        print "Reading settings"
1081
        cp = ConfigParser.ConfigParser()
1082
 
1083
        try:
644 FredericG 1084
            cp.read("%s/%s" % (rootPath, App.SETTINGSFILE))
607 FredericG 1085
            for setting in cp.items("DEFAULT"):
1086
                print " ",setting
1087
                try:
613 FredericG 1088
                    self.settings[setting[0]].set(setting[1])
607 FredericG 1089
                except:
1090
                    print "WARNING, unknown setting"
1091
        except:
1092
            print "ERROR reading settingsfile"
648 FredericG 1093
        self.onSettingsChanged(False)
607 FredericG 1094
 
1095
    def storeSettings(self):
1096
        print "Storing settings"
1097
 
1098
        cp = ConfigParser.ConfigParser()
1099
        for setting in self.settings.iteritems():
1100
            cp.set("", setting[0], setting[1].value)
1101
 
644 FredericG 1102
        file = open("%s/%s" % (rootPath, App.SETTINGSFILE), "w")
607 FredericG 1103
        cp.write(file)
1104
        file.close()
1105
 
611 FredericG 1106
 
648 FredericG 1107
    def onSettingsChanged(self, store):
1108
        if store:
1109
            self.storeSettings()
649 FredericG 1110
 
648 FredericG 1111
        if self.settings["calcmethod"].value == "rms":
1112
            VibTest.useRms = True
1113
        else:
1114
            VibTest.useRms = False
649 FredericG 1115
 
1116
        VibTest.fc1 = self.settings["hpf"].value
1117
        VibTest.fc2 = self.settings["lpf"].value
1118
 
648 FredericG 1119
        for test in self.VibTests:
1120
            test.refresh()
645 FredericG 1121
        self.frame_1.refreshData()
613 FredericG 1122
 
1123
    def AddTest2(self, vibTest):
1124
        self.VibTests.append(vibTest)
1125
        self.frame_1.onNewTest(vibTest)
611 FredericG 1126
 
619 FredericG 1127
    def AddTest(self, descr, voltage, motor, speed, channel, rawData):
1128
        test = VibTest(descr, voltage, motor, speed, channel, rawData)
613 FredericG 1129
        self.AddTest2(test)
586 FredericG 1130
 
616 FredericG 1131
    def removeTest(self, idx):
1132
        del(self.VibTests[idx])
1133
 
590 FredericG 1134
    def getTest(self, testId):
1135
        return self.VibTests[testId]
1136
 
584 FredericG 1137
    def OnInit(self):
1138
        wx.InitAllImageHandlers()
586 FredericG 1139
        self.frame_1 = MainFrame(None, -1, "")
587 FredericG 1140
        self.frame_1.setApp(self);
586 FredericG 1141
        self.SetTopWindow(self.frame_1)
1142
 
607 FredericG 1143
        self.frame_1.CenterOnScreen()
587 FredericG 1144
        self.frame_1.Show()
1145
        return 1
1146
 
619 FredericG 1147
    def saveTests(self, filePath):
1148
        try:
1149
          logfile = open(filePath, "r")
1150
          newFile = False
1151
          logfile.close()
1152
        except:
1153
          newFile = True
1154
 
1155
        for test in self.VibTests:
1156
          if newFile:
1157
            logfile = open(filePath, "w")
1158
            print "Writing result to %s ..." % filePath,
1159
            logfile.write("%s %d %s\n" % (test.descr, test.speed, test.channel))
1160
            for value in test.rawData:
1161
              logfile.write("%d\n" % value)
1162
            logfile.close()  
1163
            print "OK"
1164
          else:
1165
            print "Appending result to %s ..." % filePath,
1166
            logfile = open(filePath, "r")
1167
            prevData = []
1168
            for line in logfile:
1169
              prevData.append(line[:-1])
1170
            logfile.close()
1171
            logfile = open(filePath, "w")
1172
            logfile.write("%s,%s %d %s\n" % (prevData[0], test.descr, test.speed, test.channel))
1173
            i = 1
1174
            for value in test.rawData:
1175
              logfile.write("%s,%d\n" % (prevData[i], value))
1176
              i += 1
1177
            logfile.close()
1178
            print "OK"
1179
          newFile = False
1180
 
1181
 
1182
    def loadTests(self, filePath):
596 FredericG 1183
 
606 FredericG 1184
        print "Importing file \"%s\"" % filePath
596 FredericG 1185
 
1186
        logfile = open(filePath, "r")
590 FredericG 1187
        data = None
596 FredericG 1188
 
619 FredericG 1189
        headers = (logfile.readline()[:-1]).split(',')
596 FredericG 1190
        nbCols = len(headers)
1191
        print "NbCols =", nbCols
1192
 
1193
        data = []
1194
        descr = []
1195
        speed = []
1196
        channel = []
1197
        for c in range(nbCols):
1198
            data.append([])
1199
            h = headers[c].split(' ')
1200
            descr.append(h[0]);
1201
            speed.append(h[1]);
1202
            channel.append(h[2]);
1203
 
590 FredericG 1204
        for line in logfile:
1205
            values = line.split(',')
596 FredericG 1206
            for i in range(nbCols):
1207
                data[i].append(int(values[i]))
590 FredericG 1208
        logfile.close()
596 FredericG 1209
 
1210
        for c in range(nbCols):
599 FredericG 1211
            if (len(data[c]) % 2) != 0:
1212
                data[c].append(data[c][-1])
619 FredericG 1213
            self.AddTest(descr[c], 0, 0, int(speed[c]), channel[c], data[c])
612 FredericG 1214
 
613 FredericG 1215
    def startMeasure(self, measureParams, dialog):
612 FredericG 1216
        print "Start measuring"
590 FredericG 1217
 
613 FredericG 1218
        measureParams.serialPort = self.settings["serialport"].value
1219
        measureParams.motorStartupSpeed = self.settings["startupspeed"].value
1220
        measureParams.motorStartupSettlingTime = self.settings["startupsettling"].value
628 FredericG 1221
        measureParams.minVoltage = self.settings["minvoltage"].value
1222
        measureParams.maxVoltage = self.settings["maxvoltage"].value        
613 FredericG 1223
 
1224
        self.measureThread = MeasureThread(measureParams, dialog)
612 FredericG 1225
        self.measureThread.start()
590 FredericG 1226
 
613 FredericG 1227
    def cancelMeasurement(self):
1228
        print "Measuring CANCEL"
1229
 
1230
        self.measureThread.stop()
1231
 
612 FredericG 1232
 
1233
 
1234
 
1235
 
590 FredericG 1236
 
586 FredericG 1237
 
590 FredericG 1238
 
584 FredericG 1239
# end of class App
1240
 
1241
if __name__ == "__main__":
626 FredericG 1242
 
1243
    rootPath = os.path.abspath(os.path.dirname(sys.argv[0]))
1244
 
1245
    print rootPath
1246
 
584 FredericG 1247
    VibrationTestGui = App(0)
1248
    VibrationTestGui.MainLoop()