pythonpygameraspberry-pi3playstation3

PyGame - RaspberryPi 3b+ with a ps3 controller


I am trying to use pygame with the raspberry pi to use a PlayStation 3 controller as an input for a car. I have tested the controller with a demo code, and everything works fine. Then when I try to use it in my program, it reads 0.0 as the input, when the joysticks are moved. attached is my current code:

import pygame

class controller:
        def __init__(self):
                pygame.init()
                pygame.joystick.init()
                global joystick
                joystick = pygame.joystick.Joystick(0)
                joystick.init()

        def get_value(self, axis):
                value = joystick.get_axis(axis)
                return value
control = controller()
val = control.get_value(0)
while True:
        print(val)

I am aware that this test is only for axis 0, but the output is still 0.0 for all axes.

Below, i have attached the demo code, where all the values are properly read.

import pygame, sys, time    #Imports Modules
from pygame.locals import *

pygame.init()#Initializes Pygame
pygame.joystick.init()
joystick = pygame.joystick.Joystick(0)
joystick.init()#Initializes Joystick

# get count of joysticks=1, axes=27, buttons=19 for DualShock 3

joystick_count = pygame.joystick.get_count()
print("joystick_count")
print(joystick_count)
print("--------------")

numaxes = joystick.get_numaxes()
print("numaxes")
print(numaxes)
print("--------------")

numbuttons = joystick.get_numbuttons()
print("numbuttons")
print(numbuttons)
print("--------------")

loopQuit = False
while loopQuit == False:

    # test joystick axes and prints values
    outstr = ""
    for i in range(0,4):
        axis = joystick.get_axis(i)
        outstr = outstr + str(i) + ":" + str(axis) + "|"
        print(outstr)

    # test controller buttons
    outstr = ""
    for i in range(0,numbuttons):
           button = joystick.get_button(i)
           outstr = outstr + str(i) + ":" + str(button) + "|"
    print(outstr)

    for event in pygame.event.get():
       if event.type == QUIT:
           loopQuit = True
       elif event.type == pygame.KEYDOWN:
           if event.key == pygame.K_ESCAPE:
               loopQuit = True
             
       # Returns Joystick Button Motion
       if event.type == pygame.JOYBUTTONDOWN:
        print("joy button down")
       if event.type == pygame.JOYBUTTONUP:
        print("joy button up")
       if event.type == pygame.JOYBALLMOTION:
        print("joy ball motion")
       # axis motion is movement of controller
       # dominates events when used
       if event.type == pygame.JOYAXISMOTION:
           # print("joy axis motion")

    time.sleep(0.01)
pygame.quit()
sys.exit()

any feedback will be much appreciated.


Solution

  • The code is losing the reference to the initialised joystick. It needs to maintain an internal link to it. Note the use of self. in the class below. This keeps the reference inside the class, making "self.joystick" a member variable of the class. Python classes need the self. notation (unlike lots of (all?) other object orientated languages). While editing I changed some of the names to match the Python PEP-8 style guide, I hope that's OK ;)

    class Controller:
        def __init__( self, joy_index=0 ):
            pygame.joystick.init()                # is it OK to keep calling this?
            self.joystick = pygame.joystick.Joystick( joy_index )
            self.joystick.init()
    
        def getAxisValue( self, axis ):
            value = self.joystick.get_axis( axis )
            return value
    

    Maybe you left the extra code out of the question, but a PyGame program without an event loop will eventually lock up.

    import pygame
    
    # Window size
    WINDOW_WIDTH    = 300
    WINDOW_HEIGHT   = 300
    
    
    class Controller:
        """ Class to interface with a Joystick """
        def __init__( self, joy_index=0 ):
            pygame.joystick.init()
            self.joystick = pygame.joystick.Joystick( joy_index )
            self.joystick.init()
    
        def getAxisValue( self, axis ):
            value = self.joystick.get_axis( axis )
            return value
    
    
    ### initialisation
    pygame.init()
    window = pygame.display.set_mode( ( WINDOW_WIDTH, WINDOW_HEIGHT ) )
    clock  = pygame.time.Clock()
    pygame.display.set_caption( "Any Joy?" )    
    
    # Talk to the Joystick
    control = controller()
    
    # Main loop
    done = False
    while not done:
        for event in pygame.event.get():
            if ( event.type == pygame.QUIT ):
                done = True
    
        # Query the Joystick
        val = control.getAxisValue( 0 )
        print( "Joystick Axis: " + str( val ) )
    
        # Update the window, but not more than 60fps
        window.fill( (0,0,0) )
        pygame.display.flip()
        clock.tick_busy_loop(60)
    
    pygame.quit()