Subversion Repositories Projects

Rev

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