Subversion Repositories Projects

Rev

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