Rose-Hulman Robotics Team

Changeset 461

Show
Ignore:
Timestamp:
03/15/09 01:43:19 (3 years ago)
Author:
mosttw
Message:

License fixes; hopefully fixed motor speed graphing for real motors

Location:
trunk/software/rb
Files:
11 modified

Legend:

Unmodified
Added
Removed
  • trunk/software/rb/controller.py

    r458 r461  
     1# Copyright (C) 2009 Thomas W. Most 
     2# Copyright (C) 2008 Andy Spencer 
     3# 
     4# This program is free software: you can redistribute it and/or modify 
     5# it under the terms of the GNU General Public License as published by 
     6# the Free Software Foundation, either version 3 of the License, or 
     7# (at your option) any later version. 
     8# 
     9# This program is distributed in the hope that it will be useful, 
     10# but WITHOUT ANY WARRANTY; without even the implied warranty of 
     11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
     12# GNU General Public License for more details. 
     13# 
     14# You should have received a copy of the GNU General Public License 
     15# along with this program.  If not, see <http://www.gnu.org/licenses/>. 
     16 
    117import gobject 
    218 
  • trunk/software/rb/drive.py

    r459 r461  
    11# Copyright (C) 2008 Thomas W. Most 
     2# Copyright (C) 2009 Andy Spencer 
    23# 
    34# This program is free software: you can redistribute it and/or modify 
     
    7475        ''' 
    7576         
    76         def __init__(self, ldev, rdev): 
    77                 self.left  = Motor(ldev) 
    78                 self.right = Motor(rdev) 
    79                 #self.setspeed(0.0, 0.0) 
    80          
    81         def _get_running(self): 
    82                 return self.left.running 
    83          
    84         def _set_running(self, value): 
    85                 self.left.running = value 
    86                 self.right.running = value 
    87          
    88         running = property(_get_running, _set_running) 
     77        def __init__(self, controller, ldev, rdev): 
     78                self.controller = controller 
     79                self.running = True 
     80                self.left  = Motor(self, ldev) 
     81                self.right = Motor(self, rdev) 
     82                start_new_thread(self._main, ()) 
     83         
     84        def _main(self): 
     85                while self.running: 
     86                        lcur, rcur = self._split('getspeed', (), ()) 
     87                        if lcur is not None: 
     88                                self.left.current = (lcur*50*60 / 256.0) / MAX 
     89                        else: 
     90                                print "Drive._main: timeout getting left speed" 
     91                        if rcur is not None: 
     92                                self.right.current = (rcur*50*60 / 256.0) / MAX 
     93                        else: 
     94                                print "Drive._main: timeout getting right speed" 
     95                        if lcur is not None and rcur is not None: 
     96                                self.controller.send('drive_speeds', self.getspeed()) 
     97                        time.sleep(.05) 
    8998 
    9099        def _split(self, type, lt_data, rt_data): 
     
    116125                self.left.target  = clip(left,  -1.0, 1.0) * MAX 
    117126                self.right.target = clip(right, -1.0, 1.0) * MAX 
     127                self.controller.send('drive_targets', self.gettarget()) 
    118128         
    119129        def gettarget(self): 
     
    138148        ''' 
    139149         
    140         def __init__(self, port): 
    141                 self._port_name = port 
    142                 self.running    = True 
     150        def __init__(self, drive, port): 
     151                self.drive = drive 
    143152                self.target     = 0 # Speed the motor controllers should be at 
    144153                self.current    = 0 # Latest reported speed of the motors 
     154                self._port_name = port 
     155                self._port_lock = Lock() 
    145156                self._port      = Serial(port, 19200, timeout=.5) 
    146157                time.sleep(1) 
    147                 self._port_lock = Lock() 
    148158                start_new_thread(self._main, ()) 
    149159 
    150160        def _main(self): 
    151161                print "Motor._main: starting" 
    152                 while self.running: 
    153                         #print "Motor._main: stepping" 
    154                         cur = self._send("getspeed") 
    155                         if cur is not None: 
    156                                 #print "updating speed, cur=%d target=%d" % (cur, self.target) 
    157                                 #inc = min(0.05*MAX, abs(self.target - cur)) 
    158                                 #if cur < self.target: 
    159                                 #       self._send("setspeed", cur + inc) 
    160                                 #elif cur > self.target: 
    161                                 #       self._send("setspeed", cur - inc) 
    162                                 #else: 
    163                                 self.current = (cur*50*60 / 256.0) / MAX 
    164                                 self._send("setspeed", self.target) # Ping! 
    165                         else: 
    166                                 print "Motor._main: timeout getting speed" 
     162                while self.drive.running: 
     163                        self._send("setspeed", self.target) # Ping! 
    167164                        time.sleep(.05) 
    168165                print "Motor._main: exiting" 
     
    257254                print "FakeMotor sending %s - %s" % (type, repr(t_data)) 
    258255         
    259         current = property(lambda s: s.target) 
     256        current = property(lambda s: s.target, lambda s: None) 
  • trunk/software/rb/gps.py

    r363 r461  
    8181        ''' 
    8282         
    83         def __init__(self, dev): 
     83        def __init__(self, controller, dev): 
    8484                ''' 
    8585                Create a new `GPS` object.  `dev` is the device to start gpsd 
    8686                listening on. 
    8787                ''' 
    88                 self.latest_coords = None 
     88                self.controller = controller 
    8989                self.dev = dev 
    9090                self.running = True 
     91                self.latest_coords = None 
    9192                self.gpsd = None 
    9293                self.gps = None 
    93                 super(GPS, self).__init__() 
     94                 
    9495                thread.start_new_thread(self._run_gpsd, ()) 
    9596                thread.start_new_thread(self._main, ()) 
     
    164165                                                        log_debug("GPS: got update") 
    165166                                                        self.latest_coords = GPSCoord(*data) 
     167                                                        self.controller.send('gps_fix', self.latest_coords) 
    166168                                                        last_data = data 
    167169 
    168  
    169 def main(): 
    170         ''' 
    171         Print constant updates from the GPS. 
    172         ''' 
    173         logging.log_level = logging.DEBUG 
    174         gps = GPS(sys.argv[1]) 
    175         last_data = None 
    176         try: 
    177                 while True: 
    178                         data = gps.latest_coords 
    179                         if data is not last_data: 
    180                                 last_data = data 
    181                                 print data.pformat() 
    182         except KeyboardInterrupt: 
    183                 print "Shutting down, just a sec" 
    184                 gps.running = False 
    185  
    186 if __name__ == '__main__': 
    187         main() 
  • trunk/software/rb/gui/analog.py

    r458 r461  
     1# Copyright (C) 2008-2009 Andy Spencer 
     2# Copyright (C) 2008-2009 Thomas W. Most 
     3# 
     4# This program is free software: you can redistribute it and/or modify 
     5# it under the terms of the GNU General Public License as published by 
     6# the Free Software Foundation, either version 3 of the License, or 
     7# (at your option) any later version. 
     8# 
     9# This program is distributed in the hope that it will be useful, 
     10# but WITHOUT ANY WARRANTY; without even the implied warranty of 
     11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
     12# GNU General Public License for more details. 
     13# 
     14# You should have received a copy of the GNU General Public License 
     15# along with this program.  If not, see <http://www.gnu.org/licenses/>. 
     16 
    117from math import pi 
    218import gtk 
     
    7793                l = x+y 
    7894                r = y-x 
    79  
    80                 #log_debug("\tgui: x=%f, y=%f, l=%f, r=%f" % (x,y,l,r)) 
    81                 self.controller.set_speed(l, r) 
     95                self.controller.drive.setspeed(l, r) 
  • trunk/software/rb/gui/compass.py

    r445 r461  
    11#!/usr/bin/env python 
    22 
    3 # Copyright (C) 2008 Nathan T. Mendel, Ching-Chen Ma, Thomas W. Most 
     3# Copyright (C) 2008 Nathan T. Mendel 
     4# Copyright (C) 2008 Ching-Chen Ma 
     5# Copyright (C) 2009 Thomas W. Most 
    46# 
    57# This program is free software: you can redistribute it and/or modify 
  • trunk/software/rb/gui/gui.py

    r459 r461  
     1# Copyright (C) 2008-2009 Andy Spencer 
     2# Copyright (C) 2008-2009 Thomas W. Most 
     3# 
     4# This program is free software: you can redistribute it and/or modify 
     5# it under the terms of the GNU General Public License as published by 
     6# the Free Software Foundation, either version 3 of the License, or 
     7# (at your option) any later version. 
     8# 
     9# This program is distributed in the hope that it will be useful, 
     10# but WITHOUT ANY WARRANTY; without even the implied warranty of 
     11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
     12# GNU General Public License for more details. 
     13# 
     14# You should have received a copy of the GNU General Public License 
     15# along with this program.  If not, see <http://www.gnu.org/licenses/>. 
     16 
     17from __future__ import division 
     18 
    119import gobject 
    220import pygtk; pygtk.require("2.0") 
     
    422 
    523import os.path 
     24from math import pi 
    625from thread import start_new_thread 
    726 
     
    2746} 
    2847 
     48# Blue color for indicating the robot's orientation 
     49RAW_ORIENT_BLUE = (85/255, 107/255, 160/255) # Raw MicroStrain data 
     50ORIENT_BLUE = (6/255, 67/255, 213/255) # Kalman filter estimation 
     51 
    2952 
    3053class GUI(Controller): 
     
    5578                self.builder.add_from_file(GTKBUILDER_FILE) 
    5679                self.builder.connect_signals(self) 
    57                 self.window  = self.builder.get_object('window') 
     80                self.window = self.builder.get_object('window') 
    5881 
    5982                # Glade-3 -> GtkBuilder fix 
     
    6588                self.analog = AnalogWidget(self) 
    6689                self.compass = CompassWidget() 
     90                self.raw_orient_dir = self.compass.new_direction(RAW_ORIENT_BLUE, pi / 2) 
    6791                self.speed_graph = SpeedGraph(self.drive) 
    6892                self.builder.get_object("analog_body").add(self.analog) 
     
    79103                Shell(self).cmdloop() 
    80104                gobject.idle_add(gtk.main_quit) 
     105         
     106        def update_compass_raw_orient(self, state_accel): 
     107                self.raw_orient_dir.update(state_accel.orient[2]) 
    81108         
    82109        def process(self, type, data): 
     
    86113                elif type == 'drive_speeds': 
    87114                        self.analog.queue_draw() 
     115                elif type == 'microstrain': 
     116                        self.update_compass_orient(data) 
    88117         
    89118        def set_navigator(self, nav): 
     
    105134                        if nav == 'stop': 
    106135                                print "Switching to 'stop' navigator" 
    107                                 self.set_speed(0, 0) 
     136                                self.drive.setspeed(0, 0) 
    108137                        elif nav == 'analog': 
    109138                                print "Switching to analog navigator" 
     
    141170                # E-Stop  
    142171                if event.keyval in (gtk.keysyms.Escape, gtk.keysyms.space): 
    143                         self.set_mode('stop') 
     172                        self.set_navigator('stop') 
    144173 
    145174                # Switch tabs 
     
    150179                elif event.keyval in self.arrow_keys_map: 
    151180                        lo, ro = self.arrow_keys_map[event.keyval] 
    152                         self.set_speed(self.drive.left.target+lo, 
    153                                                         self.drive.right.target+ro) 
     181                        self.drive.setspeed(self.drive.left.target+lo, 
     182                                                                self.drive.right.target+ro) 
    154183 
    155184                # Key not found 
     
    205234                self.drive.eewrite() 
    206235 
    207         # utilities 
    208         def set_speed(self, lspeed, rspeed): 
    209                 # Constrain l and r 
    210                 self.drive.setspeed(lspeed, rspeed) 
    211                 self.analog.redraw(None) 
    212  
    213236        # GTK Callbacks 
    214237        def on_window_destroy(self, widget, data=None): 
  • trunk/software/rb/gui/speedgraph.py

    r460 r461  
    1 # Copyright (C) 2008 Thomas W. Most 
     1# Copyright (C) 2009 Thomas W. Most 
    22# 
    33# This program is free software: you can redistribute it and/or modify 
  • trunk/software/rb/kalman.py

    r458 r461  
     1# Copyright (C) 2009 Thomas W. Most 
     2# 
     3# This program is free software: you can redistribute it and/or modify 
     4# it under the terms of the GNU General Public License as published by 
     5# the Free Software Foundation, either version 3 of the License, or 
     6# (at your option) any later version. 
     7# 
     8# This program is distributed in the hope that it will be useful, 
     9# but WITHOUT ANY WARRANTY; without even the implied warranty of 
     10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
     11# GNU General Public License for more details. 
     12# 
     13# You should have received a copy of the GNU General Public License 
     14# along with this program.  If not, see <http://www.gnu.org/licenses/>. 
     15 
    116 
    217from thread import start_new_thread 
     18 
     19from rb.utils import meter_offset 
    320 
    421 
     
    4663                        # Use the robot's initial location as zero 
    4764                        self.gps_zero = coords.lat_lon 
     65                x, y = meter_offset(self.gps_zero, coords.lat_lon) 
    4866                 
    49                 # Convert GPS coordinates to meters 
    50                 # FIXME! 
     67                self._x_y = (x, y) 
    5168         
    5269        def update_drive_speed(self, (lspeed, rspeed)): 
  • trunk/software/rb/microstrain.py

    r360 r461  
    1 # Copyright (C) 2008 Thomas W. Most 
     1# Copyright (C) 2008-2009 Thomas W. Most 
    22# Copyright (C) 2008 Andy Spencer 
    33# 
     
    9090        ''' 
    9191         
    92         def __init__(self, dev): 
     92        def __init__(self, controller, dev): 
    9393                ''' 
    9494                Create a new `MicroStrain` object.  `dev` is the serial device 
    9595                on which the MicroStrain is present. 
    9696                ''' 
    97                  
     97                self.controller = controller 
    9898                self.running = True 
    9999                self.dev = dev 
     
    129129                                        elif isinstance(result, StateAccel): 
    130130                                                self.latest_state = result 
    131                                                 self.smoothed_state = self.calc_smoothed(result) 
     131                                                self.controller.send('microstrain', result) 
    132132                                 
    133133                                port.write("\x10\x00\x00") # Stop continuous mode 
     
    135135                                log_error("MicroStrain: disconnetion: %s" % e) 
    136136                                time.sleep(1) # The cable was probably pulled.  Wait for it. 
    137          
    138         def calc_smoothed(self, new_state): 
    139                 self._window.append(new_state) 
    140                 if len(self._window) > WINDOW_SIZE: 
    141                         self._window = self._window[len(self._window) - WINDOW_SIZE:WINDOW_SIZE] 
    142                 num = len(self._window) 
    143                 return StateAccel( 
    144                         _smooth_triple(self._window, 'orient', num), 
    145                         _smooth_triple(self._window, 'ang_vel', num), 
    146                         _smooth_triple(self._window, 'accel', num) 
    147                 ) 
    148  
    149  
    150 def _smooth_triple(window, attr, num): 
    151         ''' 
    152         Return a three-tuple of the average of each dataset 
    153         `attr` in `window`, a list of StateAccel objects. 
    154         ''' 
    155         # TODO: Probably should do a weighted average 
    156         # and/or more filtering. 
    157         triples = [getattr(sa, attr) for sa in window] 
    158         return ( 
    159                 sum(t[0] for t in triples) / num, 
    160                 sum(t[1] for t in triples) / num, 
    161                 sum(t[2] for t in triples) / num 
    162         ) 
     137 
     138 
    163139 
    164140def handle_packet(port): 
     
    268244        0x25: (11, None), 
    269245} 
    270  
    271  
    272 def main(): 
    273         ''' 
    274         Print MicroStrain data to the screen. 
    275         ''' 
    276         logging.log_level = logging.DEBUG 
    277         ms = MicroStrain(sys.argv[1]) 
    278         last_state = None 
    279         try: 
    280                 while True: 
    281                         state = ms.smoothed_state 
    282                         if state is not last_state: 
    283                                 print state.pformat() 
    284                                 last_state = state 
    285                         time.sleep(.01) 
    286         except KeyboardInterrupt: 
    287                 ms.running = False 
    288  
    289 if __name__ == '__main__': 
    290         main() 
  • trunk/software/rb/shell.py

    r459 r461  
    1 # Copyright (C) 2008 Thomas W. Most 
     1# Copyright (C) 2008-2009 Thomas W. Most 
     2# Copyright (C) 2009 Michael Auchter 
     3# Copyright (C) 2009 Andy Spencer 
    24# 
    35# This program is free software: you can redistribute it and/or modify 
     
    160162         
    161163        def do_stop(self, cmd): 
    162                 self.controller.drive.set_speeds(0.0, 0.0) 
     164                self.controller.drive.setspeed(0.0, 0.0) 
    163165         
    164166        def help_stop(self): 
  • trunk/software/rb/wiimote.py

    r449 r461  
    113113                rspeed = y / 127.0 if (abs(y) > 5) else 0 
    114114 
    115                 self.controller.set_speed(lspeed, rspeed) 
     115                self.controller.drive.setspeed(lspeed, rspeed) 
    116116 
    117117        def handle_mesg(self, messages):