element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • About Us
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
Raspberry Pi
  • Products
  • More
Raspberry Pi
Raspberry Pi Forum Yet another Pip-Boy project
  • Blog
  • Forum
  • Documents
  • Quiz
  • Events
  • Polls
  • Files
  • Members
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
Join Raspberry Pi to participate - click to join for free!
Featured Articles
Announcing Pi
Technical Specifications
Raspberry Pi FAQs
Win a Pi
Raspberry Pi Wishlist
Actions
  • Share
  • More
  • Cancel
Forum Thread Details
  • Replies 17 replies
  • Subscribers 664 subscribers
  • Views 3104 views
  • Users 0 members are here
Related

Yet another Pip-Boy project

lordzoabar
lordzoabar over 5 years ago

Hardware:

Raspberry Pi Zero-W

Adafruit Ultimate GPS breakout

Adafruit I2S 3W Amplifier breakout

Fallout 76 Pip-Boy 2000 MKVI kit
various tactile switches and rotary encoders
*no monitor decided on yet*

 


So I’ve been working on my own Pip-Boy project, and I’ve run into a snag.   I am using the Raspipboy Python program made by Selectnone years ago, (https://bitbucket.org/selectnone/raspipboy/wiki/Home) and have been running into a number of problems.   I want to use it, as it is the most “complete” PipOS I have found (and I know NOTHING about how to even start writing my own).  It was originally written in Python2, but I’ve been able to update my local copy of it to 3.7.  I tried keeping it in Py2, but I get the same issues as I do when running it in 3, and 3 runs faster, anyway.   I’m not at home at the moment, so I don’t have the traceback logs in front of me, but pretty much, every time it makes a call to GPSD to draw up the maps when the Data-Maps tab is opened, it crashes.   If I could just disable the maps tabs, that would be fine with me even, but I don’t know how to safely do that without completely breaking everything else.   If anyone familiar with Python would be willing to take a look at the script package, I can relay all the changes I’ve made, (mostly through trial and error).  If anyone knows of another good PipOS that’s been written, that actually works, I would greatly appreciate that as well. 

  • Sign in to reply
  • Cancel
  • cstanton
    cstanton over 5 years ago

    it'll help to have a log of the errors that're causing the problems. GPSD should be straight forward to diagnose and find out the problem, perhaps it's simply a missing package? It could be that it's 'faster' because it's not processing the output from the GPS.

     

    So be upfront with the error logs you have, changes you've made, etc, because otherwise anyone trying to help is only being forced to ask you for it and won't know if they can help image

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
  • lordzoabar
    lordzoabar over 5 years ago in reply to cstanton

    # RasPipBoy: A Pip-Boy 3000 implementation for Raspberry Pi
    #   Neal D Corbett, 2013
    # GPS/position functions
    
    import os, time, math
    import urllib.request, urllib.parse, urllib.error, urllib.request, urllib.error, urllib.parse, io, json
    import config
    
    if config.USE_GPS:
        # Load libraries used by GPS, if present:
        def gps():
            try:
                global gps
                import gps
                
            except:
                # Deactivate GPS-related systems if load failed:
                print("GPS LIBRARY NOT FOUND!")
                config.USE_GPS = False
            loadGPS()
    
    class GpsModuleClass:
        
        saveVersion = 1
        
        cacheFilename = ("%s/map_coords.txt" %(config.CACHEPATH))
        
        lat, lon = 0, 0
        locality = ""
        localityLat, localityLon = 0, 0
        
        # Do rendered-commandline print if cmdLine object is available, otherwise do a plain print:
        def cmdLinePrint(self, cmdLine, msg):
            if (cmdLine == 0):
                print(msg)
            else:
                cmdLine.printText(msg)
                
        # Return Lat/Lon value for a given address:
        def addressToLatLong(self,address):
            urlParams = {
                'address': address,
                'sensor': 'false',
            }
            url = 'http://maps.google.com/maps/api/geocode/json?' + urllib.parse.urlencode( urlParams )
            print(url)
            response = urllib.request.urlopen( url )
            responseBody = response.read()
            
            body = io.StringIO( responseBody )
            result = json.load( body )
            if 'status' not in result or result['status'] != 'OK':
                return None
            else:
                return result['results'][0]['geometry']['location']['lat'], result['results'][0]['geometry']['location']['lng']
        
        # Return Locality for a given lat/lon value:
        def latLongToLocality(self, lat, lon):
            urlParams = {
                'latlng': (str(lat) +"," + str(lon)),
                'sensor': 'false',
            }
            url = 'http://maps.google.com/maps/api/geocode/json?' + urllib.parse.urlencode( urlParams )
            print("latLongToLocality:")
            print(url)
            response = urllib.request.urlopen( url )
            responseBody = response.read()
            
            body = io.StringIO( responseBody )
            result = json.load( body )
            if 'status' not in result or result['status'] != 'OK':
                return None
            else:
                addressComps = result['results'][0]['address_components']
                
                notLocality = True
                compNum = 0
                retVal = ""
                while (notLocality and compNum < len(addressComps)):
                    addressComp = addressComps[compNum]
                    retVal = addressComp['long_name']
                    for compType in addressComp['types']:
                        if (compType == 'locality'):
                            notLocality = False
                    compNum += 1
                return retVal
                
        def hasCoords(self):
            badCoords = (((self.lat == 0) or math.isnan(self.lat)))
            return(not badCoords)
        
        def getCoords(self, *args):
            
            cmdLine = 0
            if (len(args) != 0):
                cmdLine = args[0]
            
            # Do initial GPS-fix:
            self.cmdLinePrint(cmdLine, ">GPSD.LOCATE")
            self.cmdLinePrint(cmdLine, "Acquiring GPS Fix...")
    
           if config.USE_GPS:
                # Play sound until we have a GPS location locked:
                if (config.USE_SOUND) and (cmdLine != 0):
                    #downloadSound = config.SOUNDS["static"]
                    downloadSound = config.SOUNDS["beacon"]
                    #config.SOUNDS["static"].play(loops=-1)
                    downloadSound.play(loops=-1)
                
    #             Listen on port 2947 (gpsd) of localhost
    
    #             Initialise GPS module:
                session = gps.gps(host="localhost", port="2947")
                session.stream(gps.WATCH_ENABLE | gps.WATCH_NEWSTYLE)
                
                while True:
                    try:
                        report = session.next()
                        # Wait for a 'TPV' report and display the current time
                        # To see all report data, uncomment the line below
                        # print(report)
                        if report['class'] == 'TPV':
                            if hasattr(report, 'time'):
                                print(report.time)
                    except KeyError:
                        pass
                    except KeyboardInterrupt:
                        quit()
                    except StopIteration:
                        session = None
                        print("GPSD has terminated")
        
                time.sleep(1)
                
                # Don't use GPS if no devices were found:
                if (len(session.devices) == 0):
                    config.USE_GPS = False
                    print("GPS MODULE NOT FOUND!")
                
                if config.USE_GPS:
                    try:
                        while (self.lat == 0) and (self.lat == 0):
                            next(session)
                            self.lat = session.fix.latitude
                            self.lon = session.fix.longitude
                            self.cmdLinePrint(cmdLine, "\t(%s,%s)" %(str(self.lat),str(self.lon)))
                    except StopIteration:
                        self.cmdLinePrint(cmdLine, "GPSD has terminated")
                        config.USE_GPS = False
                
                del session
                
                if (config.USE_SOUND) and (cmdLine != 0):
                    downloadSound.stop()
                
            newCoords = True
            
            if (not self.hasCoords()):
                # If GPS-fix wasn't available, load it from cached coords:
                if (os.path.exists(self.cacheFilename)):
                    self.cmdLinePrint(cmdLine, ">GPSD.LOADCACHE %s" %(config.defaultPlace))
                    self.cmdLinePrint(cmdLine, "Getting cached coords from %s..." %(self.cacheFilename))
                    with open(self.cacheFilename, 'r') as f:
                        savedVersion = eval(f.readline())
                        
                        # Only use coordinates-cache file if its version matches current version:
                        if (savedVersion == self.saveVersion):
                            self.lat = eval(f.readline())
                            self.lon = eval(f.readline())
                            self.locality = (f.readline()).rstrip()
                            self.localityLat = eval(f.readline())
                            self.localityLon = eval(f.readline())
                            self.cmdLinePrint(cmdLine, "\t(%s,%s)" %(str(self.lat),str(self.lon)))
                            newCoords = False
                        else:
                            self.cmdLinePrint("\tInvalid cache-version, ignoring file")
                            
                # If cache wasn't available, generate coords from defaultPlace:
                if (newCoords):
                    self.cmdLinePrint(cmdLine, ">GPSD.DEFAULTLOC %s" %(config.defaultPlace))
                    self.cmdLinePrint(cmdLine, "Getting coords via geocode for Default Location %s..." %(config.defaultPlace))
                    
                    self.lat, self.lon = self.addressToLatLong(config.defaultPlace)
                    self.cmdLinePrint(cmdLine, "\t(%s,%s)" %(str(self.lat),str(self.lon)))
                    
                    self.locality = self.latLongToLocality(self.lat, self.lon)
                    
                    # Get map-centre coordinates for Locality:
                    self.localityLat, self.localityLon = self.addressToLatLong(self.locality)
                
            # Get locality (i.e. city) for current coordinates via reverse-geocoding, if connection is available:
            self.cmdLinePrint(cmdLine, ">GPSD.LOCALITY")
            if (self.locality == ""):
                self.locality = self.latLongToLocality(self.lat, self.lon)
                newCoords = True
            
            self.cmdLinePrint(cmdLine, "\tLocality: \"%s\"" % (self.locality))
            
            # Output new coordinates/locality to cache-file:
            if (newCoords):
                self.cmdLinePrint(cmdLine, ">GPSD.SAVECACHE %s" %(self.cacheFilename))
                with open(self.cacheFilename, 'w') as f:
                    f.write("%s\n%s\n%s\n%s\n%s\n%s\n" %(self.saveVersion,repr(self.lat),repr(self.lon),self.locality,repr(self.localityLat),repr(self.localityLon)))
                    
            return self.lat, self.lon

     

     

    As for error logging...

     

    >GPSD.LOCATE

    Acquiring GPS Fix...

    Traceback (most recent call last):

      File "main.py", line 520, in <module>

        engine = Engine()

      File "main.py", line 196, in __init__

        self.gpsModule.getCoords(cmdLine)

      File "/home/pi/raspipboy/pipboy_gps.py", line 113, in getCoords

        session = gps.gps(host="localhost", port="2947")

    AttributeError: 'function' object has no attribute 'gps'

     

    I can run "cgps -s" and it shows that I AM pulling data from the satellites, but somewhere along the way it's getting stopped.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
  • cstanton
    cstanton over 5 years ago in reply to lordzoabar

    session = gps.gps(host="localhost", port="2947")

    AttributeError: 'function' object has no attribute 'gps'

     

    This is implying that the 'gps' object does not have a property you can call or play with called 'gps' (the dot gps part).

     

    You need to make sure you're using the GPS library properly to be able to refer to it in this way and for it to connect to the GPS daemon properly. Have you made sure that 'gps' is installed as a python library? You may need to use pip or pip3 to install it.

     

    Also you need 'gpsd' installed as a raspberry pi os/raspbian package and running so that python can connect to it on port 2947.

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • Cancel
  • lordzoabar
    lordzoabar over 5 years ago in reply to cstanton

    Yup.  I've got both the gps and gps3 library's installed, and I can confirm gpsd running, and a strong FIX on the gps module.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
  • lordzoabar
    lordzoabar over 5 years ago in reply to lordzoabar

    I've even installed the gps library directly to the raspipboy directory.   No change in the error log.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
  • cstanton
    cstanton over 5 years ago in reply to lordzoabar

    Have you tried running the python code as root or with sudo?

     

    It may be the case that the user you're running the code as is not in the necessary group to access the gps feed/data when the code's running.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
  • lordzoabar
    lordzoabar over 5 years ago in reply to cstanton

    Yup, sudo for everything.

     

    Now, in a bit of early morning, sleep deprived insanity, I decided to download a fresh copy of the original script, and tried running it in python2.  STILL doesn't work, however it DOES get a good bit further down the line.

     

     

    Traceback (most recent call last):

      File "main.py", line 520, in <module>

        engine = Engine()

      File "main.py", line 196, in __init__

        self.gpsModule.getCoords(cmdLine)

      File "/home/pi/raspipboy/pipboy_gps.py", line 183, in getCoords

        self.lat, self.lon = self.addressToLatLong(config.defaultPlace)

    TypeError: 'NoneType' object is not iterable

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
  • cstanton
    cstanton over 5 years ago in reply to lordzoabar

    > Yup, sudo for everything.

     

    How was your config.py setup?

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
  • lordzoabar
    lordzoabar over 5 years ago in reply to cstanton

    # RasPipBoy: A Pip-Boy 3000 implementation for Raspberry Pi
    #   Neal D Corbett, 2013
    # Configuration data
    
    
    # Device options 
    #  (These will be automatically be set to 'False' if unavailable)
    USE_INTERNET = True     # Download map/place data via internet connection
    USE_GPS = True          # Use GPS module, accessed via GPSD daemon
    USE_SOUND = True        # Play sounds via RasPi's current sound-source
    USE_CAMERA = False       # Use RasPi camera-module as V.A.T.S
    USE_SERIAL = False       # Communicate with custom serial-port controller
    
    
    QUICKLOAD = True      # If true, commandline-startup bits aren't rendered
    FORCE_DOWNLOAD = False  # Don't use cached map-data, if online
    
    
    # Render screen-objects at this size - smaller is faster
    WIDTH = 320
    HEIGHT = 240
    
    
    # Address for map's default position: 
    #   (used if GPS is inactive)
    defaultPlace = "Washington DC"
    
    
    # Player data:
    PLAYERNAME = 'Chase'
    PLAYERLEVEL = 30
    
    
    FPS = 60
    
    
    import pygame, os
    
    
    # My Google-API key:
    # (this is limited to only 2000 location requests a day, 
    #    so please don't use this key if you're making your own project!)
    gKey = 'My Google Key Here'
    
    
    
    
    # Teensy USB serial: symbolic link set up by creating: 
    #   /etc/udev/rules.d/99-usb-serial.rules
    # With line:
    #   SUBSYSTEM=="tty", ATTRS{manufacturer}=="Teensyduino", SYMLINK+="teensy"
    SERIALPORT = '/dev/teensy'
    # Pi GPIO serial:
    #SERIALPORT = '/dev/ttyAMA0'
    
    
    # Test serial-controller:
    if USE_SERIAL:
        # Load libraries used by serial device, if present:
        def loadSerial():
            try:
                print ("Importing Serial libraries...")
                global serial
                import serial
            except:
                # Deactivate serial-related systems if load failed:
                print "SERIAL LIBRARY NOT FOUND!"
                USE_SERIAL = False
        loadSerial()
    if(USE_SERIAL):
        try:
            print ("Init serial: %s" %(SERIALPORT))
            ser = serial.Serial(SERIALPORT, 9600)
            ser.timeout=1
            
            print "  Requesting device identity..."
            ser.write("\nidentify\n")
            
            ident = ser.readline()
            ident = ident.strip()
            print ("    Value: %s" %(str(ident)))
            
            if (ident != "PIPBOY"):
                print "  Pip-Boy controls not found on serial-port!"    
                #config.USE_SERIAL = False
            
        except:
            print ("* Failed to access serial! Ignoring serial port")
            USE_SERIAL = False
    print ("SERIAL: %s" %(USE_SERIAL))
    
    
    # Test camera:
    if USE_CAMERA:
        # Is there a camera module connected?
        def hasCamera():
            try:
                import picamera
                camera = picamera.PiCamera()
                camera.close()
                return True
            except:
                return False
        
        USE_CAMERA = hasCamera()
    print ("CAMERA: %s" %(USE_CAMERA))
    
    
    # Downloaded/auto-generated data will be put here:
    CACHEPATH = 'cache'
    if not os.path.exists(CACHEPATH):
        os.makedirs(CACHEPATH)
    
    
    DRAWCOLOUR = pygame.Color (255, 255, 255)
    TINTCOLOUR = pygame.Color (33, 255, 156)
    SELBOXGREY = 50
    
    
    EVENTS = {
        'SONG_END': pygame.USEREVENT + 1
    }
    
    
    print "Loading images..."
    IMAGES = {
        "background":pygame.image.load('images/pipboy_back.png'),
        "scanline":pygame.image.load('images/pipboyscanlines.png'),
        "distort":pygame.image.load('images/pipboydistorteffectmap.png'),
        "statusboy":pygame.image.load('images/pipboy_statusboy.png'),
    }
    
    
    print "(done)"
    
    
    # Test internet connection:
    if USE_INTERNET:
        import urllib2
        
        def internet_on():
            try:
                # Can we access this Google address?
                response=urllib2.urlopen('http://www.google.com',timeout=5)
                return True
            except urllib2.URLError as err: pass
            return False
        
        USE_INTERNET = internet_on()
    print ("INTERNET: %s" %(USE_INTERNET))
    
    
    # Test and set up sounds::
    MINHUMVOL = 0.7
    MAXHUMVOL = 1.0
    if USE_SOUND:
        try:
            print "Loading sounds..."
            pygame.mixer.init(44100, -16, 2, 2048)
    
    
            SOUNDS = {
                "start":    pygame.mixer.Sound('sounds/pipboy/ui_pipboy_access_up.wav'),
                "end":      pygame.mixer.Sound('sounds/pipboy/ui_pipboy_access_down.wav'),
                "hum":      pygame.mixer.Sound('sounds/pipboy/ui_pipboy_hum_lp.wav'),
                "scroll":   pygame.mixer.Sound('sounds/pipboy/ui_pipboy_scroll.wav'),
                "changetab":    pygame.mixer.Sound('sounds/pipboy/ui_pipboy_tab.wav'),
                "changemode":   pygame.mixer.Sound('sounds/pipboy/ui_pipboy_mode.wav'),
                "static":       pygame.mixer.Sound('sounds/radio/ui_radio_static_lp.wav'),
                "tapestart":    pygame.mixer.Sound('sounds/pipboy/ui_pipboy_holotape_start.wav'),
                "tapestop":     pygame.mixer.Sound('sounds/pipboy/ui_pipboy_holotape_stop.wav'),
                "lighton":      pygame.mixer.Sound('sounds/pipboy/ui_pipboy_light_on.wav'),
                "lightoff":     pygame.mixer.Sound('sounds/pipboy/ui_pipboy_light_off.wav'),
                "beacon":       pygame.mixer.Sound('sounds/radio/beacon/ui_radio_beacon_header.wav'),
                "camerastart":  pygame.mixer.Sound('sounds/vats/ui_vats_enter.wav'),
                #"cameraexit":  pygame.mixer.Sound('sounds/vats/ui_vats_exit.wav'),
            }
            SOUNDS["hum"].set_volume(MINHUMVOL)
            print "(done)"
        except:
            USE_SOUND = False
    print ("SOUND: %s" %(USE_SOUND))
    
    
    # Set up fonts:
    pygame.font.init()
    kernedFontName = 'fonts/monofonto-kerned.ttf'
    monoFontName = 'fonts/monofonto.ttf'
    
    
    # Scale font-sizes to chosen resolution:
    FONT_SML = pygame.font.Font(kernedFontName, int (HEIGHT * (12.0 / 360)))
    FONT_MED = pygame.font.Font(kernedFontName, int (HEIGHT * (16.0 / 360.0)))
    FONT_LRG = pygame.font.Font(kernedFontName, int (HEIGHT * (18.0 / 360.0)))
    MONOFONT = pygame.font.Font(monoFontName, int (HEIGHT * (16.0 / 360.0)))
    
    
    # Find monofont's character-size:
    tempImg = MONOFONT.render("X", True, DRAWCOLOUR, (0, 0, 0))
    charHeight = tempImg.get_height()
    charWidth = tempImg.get_width()
    del tempImg

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
  • lordzoabar
    lordzoabar over 5 years ago in reply to cstanton

    Is there anything in there that I’m just not seeing? 

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
>
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2025 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube