Changeset 651
- Timestamp:
- 02/02/10 02:46:01 (2 years ago)
- Location:
- trunk/software
- Files:
-
- 7 modified
-
rb/controller.py (modified) (1 diff)
-
rb/gui/gui.py (modified) (1 diff)
-
rb/gui/main.gtk (modified) (9 diffs)
-
rb/gui/sensors.py (modified) (3 diffs)
-
rb/gui/speed.py (modified) (1 diff)
-
rb/transcript.py (modified) (6 diffs)
-
rbconfig.py (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/software/rb/controller.py
r650 r651 132 132 from rb.transcript import TranscriptLogger 133 133 self.transcript = TranscriptLogger( 134 datetime.now().strftime( 'logs/rblog-%Y-%m-%dT%H:%M:%S.log'),134 datetime.now().strftime(rbconfig.transcript_filename), 135 135 self.drive, self.gps, self.microstrain) 136 136 -
trunk/software/rb/gui/gui.py
r626 r651 162 162 message_id = self.statusbar.push(context_id, msg) 163 163 logger.info(msg) 164 gobject.timeout_add(3000, lambda: self.statusbar.remove(context_id, message_id) and False) 164 def remove(): 165 self.statusbar.remove_message(context_id, message_id) 166 return False 167 gobject.timeout_add(5000, remove) 165 168 166 169 return success -
trunk/software/rb/gui/main.gtk
r649 r651 26 26 <object class="GtkImageMenuItem" id="quit_imagemenuitem"> 27 27 <property name="visible">True</property> 28 <property name="use_action_appearance">True</property> 28 29 <property name="related_action">quit_action</property> 29 <property name="use_action_appearance">True</property>30 30 <property name="use_underline">True</property> 31 31 <property name="use_stock">True</property> … … 52 52 <object class="GtkRadioMenuItem" id="nav_gui_radiomenuitem"> 53 53 <property name="visible">True</property> 54 <property name="use_action_appearance">True</property> 54 55 <property name="related_action">nav_gui_action</property> 55 <property name="use_action_appearance">True</property>56 56 <property name="active">True</property> 57 57 <property name="draw_as_radio">True</property> … … 61 61 <object class="GtkRadioMenuItem" id="nav_auto_radiomenuitem"> 62 62 <property name="visible">True</property> 63 <property name="use_action_appearance">True</property> 63 64 <property name="related_action">nav_wiimote_action</property> 64 <property name="use_action_appearance">True</property>65 65 <property name="draw_as_radio">True</property> 66 66 <property name="group">nav_gui_radiomenuitem</property> … … 70 70 <object class="GtkRadioMenuItem" id="nav_wiimote_radiomenuitem"> 71 71 <property name="visible">True</property> 72 <property name="use_action_appearance">True</property> 72 73 <property name="related_action">nav_auto_action</property> 73 <property name="use_action_appearance">True</property>74 74 <property name="draw_as_radio">True</property> 75 75 <property name="group">nav_gui_radiomenuitem</property> … … 113 113 <object class="GtkRadioToolButton" id="nav_gui_toolbarbutton"> 114 114 <property name="visible">True</property> 115 <property name="use_action_appearance">True</property> 115 116 <property name="related_action">nav_gui_action</property> 116 <property name="use_action_appearance">True</property>117 117 <property name="label" translatable="yes">toolbutton1</property> 118 118 <property name="use_underline">True</property> … … 127 127 <object class="GtkRadioToolButton" id="nav_wiimote_toolbarbutton"> 128 128 <property name="visible">True</property> 129 <property name="use_action_appearance">True</property> 129 130 <property name="related_action">nav_wiimote_action</property> 130 <property name="use_action_appearance">True</property>131 131 <property name="label" translatable="yes">toolbutton2</property> 132 132 <property name="use_underline">True</property> … … 141 141 <object class="GtkRadioToolButton" id="nav_auto_toolbarbutton"> 142 142 <property name="visible">True</property> 143 <property name="use_action_appearance">True</property> 143 144 <property name="related_action">nav_auto_action</property> 144 <property name="use_action_appearance">True</property>145 145 <property name="label" translatable="yes">toolbutton3</property> 146 146 <property name="use_underline">True</property> … … 621 621 <packing> 622 622 <property name="position">0</property> 623 </packing> 624 </child> 625 <child> 626 <object class="GtkHBox" id="hbox4"> 627 <property name="visible">True</property> 628 <child> 629 <object class="GtkLabel" id="sensors_transcript_label"> 630 <property name="visible">True</property> 631 <property name="xpad">1</property> 632 <property name="label" translatable="yes">_Log filename prefix: </property> 633 <property name="use_underline">True</property> 634 <property name="mnemonic_widget">sensors_transcript_entry</property> 635 </object> 636 <packing> 637 <property name="expand">False</property> 638 <property name="position">0</property> 639 </packing> 640 </child> 641 <child> 642 <object class="GtkEntry" id="sensors_transcript_entry"> 643 <property name="visible">True</property> 644 <property name="can_focus">True</property> 645 <property name="tooltip_text" translatable="yes">Use syntax valid for Pythons time.strftime() function.</property> 646 <property name="invisible_char">●</property> 647 <property name="activates_default">True</property> 648 <property name="secondary_icon_sensitive">True</property> 649 </object> 650 <packing> 651 <property name="position">1</property> 652 </packing> 653 </child> 654 <child> 655 <object class="GtkButton" id="sensors_transcript_button"> 656 <property name="label">gtk-apply</property> 657 <property name="visible">True</property> 658 <property name="can_focus">True</property> 659 <property name="can_default">True</property> 660 <property name="receives_default">True</property> 661 <property name="has_tooltip">True</property> 662 <property name="tooltip_text" translatable="yes">Open a new logfile at the location specified to the left.</property> 663 <property name="use_underline">True</property> 664 <property name="use_stock">True</property> 665 </object> 666 <packing> 667 <property name="expand">False</property> 668 <property name="position">2</property> 669 </packing> 670 </child> 671 </object> 672 <packing> 673 <property name="expand">False</property> 674 <property name="position">1</property> 623 675 </packing> 624 676 </child> … … 883 935 <object class="GtkSizeGroup" id="sensors_1stcol_sizegroup"> 884 936 <widgets> 937 <widget name="gps_speed_label"/> 938 <widget name="gps_lat_lon_label"/> 939 <widget name="ms_accel_label"/> 940 <widget name="ms_ang_vel_label"/> 885 941 <widget name="ms_orient_label"/> 886 <widget name="ms_ang_vel_label"/>887 <widget name="ms_accel_label"/>888 <widget name="gps_lat_lon_label"/>889 <widget name="gps_speed_label"/>890 942 </widgets> 891 943 </object> 892 944 <object class="GtkSizeGroup" id="ms_data_sizegroup"> 893 945 <widgets> 946 <widget name="ms_accel_2"/> 947 <widget name="ms_accel_1"/> 948 <widget name="ms_accel_0"/> 949 <widget name="ms_ang_vel_2"/> 950 <widget name="ms_ang_vel_1"/> 951 <widget name="ms_ang_vel_0"/> 952 <widget name="ms_orient_2"/> 953 <widget name="ms_orient_0"/> 894 954 <widget name="ms_orient_1"/> 895 <widget name="ms_orient_0"/>896 <widget name="ms_orient_2"/>897 <widget name="ms_ang_vel_0"/>898 <widget name="ms_ang_vel_1"/>899 <widget name="ms_ang_vel_2"/>900 <widget name="ms_accel_0"/>901 <widget name="ms_accel_1"/>902 <widget name="ms_accel_2"/>903 955 </widgets> 904 956 </object> -
trunk/software/rb/gui/sensors.py
r635 r651 15 15 # You should have received a copy of the GNU General Public License 16 16 # along with this program. If not, see <http://www.gnu.org/licenses/>. 17 18 import os 19 from datetime import datetime 17 20 18 21 import gobject … … 46 49 ''' 47 50 48 def __init__(self, controller, builder): 51 def __init__(self, gui, builder): 52 self.statusbar = gui.statusbar 53 self.transcript = gui.controller.transcript 49 54 self.microstrain_labels = [builder.get_object(n) for n in MICROSTRAIN_DATA_LABELS] 50 55 for name in GPS_LABELS: … … 60 65 builder.get_object('sensor_gps_expander').set_expanded(rbconfig.gps != rbconfig.NONE) 61 66 builder.get_object('sensor_microstrain_expander').set_expanded(rbconfig.microstrain != rbconfig.NONE) 67 68 # Transcript stuff 69 self.trans_entry = builder.get_object('sensors_transcript_entry') 70 self.trans_button = builder.get_object('sensors_transcript_button') 71 self.trans_entry.set_sensitive(rbconfig.transcript == rbconfig.REAL) 72 self.trans_entry.set_text(rbconfig.transcript_filename) 73 self.trans_button.set_sensitive(rbconfig.transcript == rbconfig.REAL) 74 self.check_transcript_filename(self.trans_entry) 75 self.trans_entry.connect('changed', self.check_transcript_filename) 76 self.trans_button.connect('clicked', self.change_transcript_filename) 77 78 def check_transcript_filename(self, entry): 79 try: 80 path = datetime.now().strftime(self.trans_entry.get_text()) 81 if not os.path.exists(os.path.dirname(path)): 82 raise ValueError('Directory doesn\'t exist') 83 except (ValueError, IOError): 84 self.trans_button.set_sensitive(False) 85 else: 86 self.trans_button.set_sensitive(True) 87 88 def change_transcript_filename(self, button): 89 fn = datetime.now().strftime(self.trans_entry.get_text()) 90 success = self.transcript.set_log_filename(fn) 91 92 # Put a message in the statusbar 93 context_id = self.statusbar.get_context_id('transcript_filename') 94 if success: 95 msg = 'Writing sensor data to %s' % fn 96 else: 97 msg = 'Error changing sensor log to %s' % fn 98 message_id = self.statusbar.push(context_id, msg) 99 100 def remove(): 101 self.statusbar.remove_message(context_id, message_id) 102 return False 103 gobject.timeout_add(5000, remove) 62 104 63 105 def update_microstrain_status(self, status): -
trunk/software/rb/gui/speed.py
r622 r651 120 120 context.stroke() 121 121 122 # Draw Target Speed 123 context.set_source_rgb(*DRIVE_COLOR) 122 if self.drive: 123 # Draw Target Speed 124 context.set_source_rgb(*DRIVE_COLOR) 124 125 125 ltarget, rtarget = self.drive.gettarget()126 x = float(ltarget - rtarget)127 y = float(ltarget + rtarget)128 x = ( x/4+0.5) * w129 y = (-y/4+0.5) * h130 context.arc(x, y, 5, 0, 2*pi)131 context.stroke()126 ltarget, rtarget = self.drive.gettarget() 127 x = float(ltarget - rtarget) 128 y = float(ltarget + rtarget) 129 x = ( x/4+0.5) * w 130 y = (-y/4+0.5) * h 131 context.arc(x, y, 5, 0, 2*pi) 132 context.stroke() 132 133 133 # Draw Current Speed134 lcur, rcur = self.drive.getspeed()135 x = float(lcur - rcur)136 y = float(lcur + rcur)137 x = ( x/4+0.5) * w138 y = (-y/4+0.5) * h139 context.arc(x, y, 10, 0, 2*pi)140 context.stroke()134 # Draw Current Speed 135 lcur, rcur = self.drive.getspeed() 136 x = float(lcur - rcur) 137 y = float(lcur + rcur) 138 x = ( x/4+0.5) * w 139 y = (-y/4+0.5) * h 140 context.arc(x, y, 10, 0, 2*pi) 141 context.stroke() 141 142 142 143 def motion_cb(self, data, event): -
trunk/software/rb/transcript.py
r528 r651 1 # Copyright (C) 2009 Thomas W. Most1 # Copyright (C) 2009-2010 Thomas W. Most 2 2 # 3 3 # This program is free software: you can redistribute it and/or modify … … 14 14 # along with this program. If not, see <http://www.gnu.org/licenses/>. 15 15 16 from __future__ import with_statement17 18 16 ''' 19 17 Record sensor data to a log file. … … 23 21 import thread 24 22 import threading 23 import logging 24 25 logger = logging.getLogger('rb.transcript') 25 26 26 27 … … 32 33 (None in Python) will be written as blanks. 33 34 ''' 34 def __init__(self, logfp, drive=None, gps=None, microstrain=None):35 def __init__(self, filename, drive=None, gps=None, microstrain=None): 35 36 ''' 36 Create a `TranscriptLogger` object. ` logfp` is the string file37 Create a `TranscriptLogger` object. `filename` is the string file 37 38 path to write the log to; `drive` is an ``rb.drive.Drive`` object, 38 39 `gps` is a ``rb.gps.GPS`` object, and `microstrain` is an … … 41 42 self.running = True 42 43 self.lock = threading.RLock() 43 self.logfile = open(logfp, 'w') 44 44 45 self.drive = drive 45 46 self.gps = gps 46 47 self.microstrain = microstrain 48 49 self._log_filename = None 50 self._log_file = None 51 self.set_log_filename(filename) 47 52 48 53 thread.start_new_thread(self._main, ()) 49 54 55 def set_log_filename(self, filename): 56 ''' 57 Start writing to a new file, location specified by `filename`. Return 58 True on success and False on failure. 59 ''' 60 with self.lock: 61 logger.info('Setting sensor log file to %r', filename) 62 if self._log_file is not None: 63 logger.debug('Closing existing log file %r', self._log_file) 64 self._log_file.close() 65 self._log_filename = filename 66 try: 67 self._log_file = open(filename, 'w') 68 self.write_comment('Start at %s' % time.time()) 69 self.write_comment('Fields:') 70 self.write_comment('\t'.join([ 71 'timestamp', 72 # Drive 73 'left_target', 'right_target', 74 'left_speed', 'right_speed', 75 # GPS 76 'gps_timestamp', 77 'gps_lat', 'gps_lon', 'gps_horiz_error', 78 'gps_speed', 'gps_speed_error', 79 # MicroStrain 80 'ms_timestamp', 81 'ms_orient_0', 'ms_orient_1', 'ms_orient_2', 82 'ms_ang_vel_0', 'ms_ang_vel_1', 'ms_ang_vel_2', 83 'ms_accel_0', 'ms_accel_1', 'ms_accel_2' 84 ])) 85 except IOError: 86 logger.exception('Unable to start log file %r', filename) 87 return False 88 return True 89 90 def get_log_filename(self): 91 with self.lock: 92 return self._log_filename 93 50 94 def _main(self): 51 with self.lock:52 self.write_comment('Start at %s' % time.time())53 self.write_comment('Fields:')54 self.write_comment('\t'.join([55 'timestamp',56 # Drive57 'left_target', 'right_target',58 'left_speed', 'right_speed',59 # GPS60 'gps_timestamp',61 'gps_lat', 'gps_lon', 'gps_horiz_error',62 'gps_speed', 'gps_speed_error',63 # MicroStrain64 'ms_timestamp',65 'ms_orient_0', 'ms_orient_1', 'ms_orient_2',66 'ms_ang_vel_0', 'ms_ang_vel_1', 'ms_ang_vel_2',67 'ms_accel_0', 'ms_accel_1', 'ms_accel_2'68 ]))69 95 while self.running: 70 96 with self.lock: … … 73 99 row += self.get_gps_data() 74 100 row += self.get_microstrain_data() 75 self.logfile.write('\t'.join(str(d) for d in row)) 76 self.logfile.write('\n') 101 self._log_file.write('\t'.join(str(d) for d in row) + '\n') 77 102 time.sleep(.1) 78 103 79 104 def write_comment(self, comment): 80 if '\n' in comment :105 if '\n' in comment or '\r' in comment: 81 106 raise ValueError('Comments are single-line') 82 107 with self.lock: 83 self.logfile.write('# ') 84 self.logfile.write(comment) 85 self.logfile.write('\n') 108 self._log_file.write('# %s\n' % comment) 86 109 87 110 def get_drive_data(self): -
trunk/software/rbconfig.py
r639 r651 34 34 kalman = REAL 35 35 transcript = REAL 36 transcript_filename = 'logs/rblog-%Y-%m-%dT%H:%M:%S.log' 36 37 drive_ctrl = NONE 37 38

