def active_check(): dev = InputDevice('/dev/input/event7') print(dev.path, dev.name, dev.phys) while True: keys = dev.active_keys() if len(keys): print(keys) pad = dev.absinfo(ecodes.ABS_X) if pad.value != 127: print("DPAD X: ", pad.value) pad = dev.absinfo(ecodes.ABS_Y) if pad.value != 127: print("DPAD Y: ", pad.value) time.sleep(0.1)
class Gamepad(): def __init__(self, device_name): self._device_name = device_name self._gamepad = InputDevice(self._device_name) def get_active_keys(self): return self._gamepad.active_keys() def get_analog_value(self, id): return self._gamepad.absinfo(id).value
def process_events(options: dict, controller: evdev.InputDevice, roomba: "pyroombaadapter.PyRoombaAdapter", shutdown_event: "threading.Event") -> None: """Translate controller events to Roomba commands. Args: options: The dict containing command line options and controller config controller: An instance of evdev's InputDevice roomba: An instance of PyRoombaAdapter shutdown_event: Event that signals shutdown. This function will block until this Event is set. Returns: None """ wheel_full_speed = False left_wheel_axis = rrc.roomba.AxisToPWM( controller.absinfo(options["control_map"]["wheel_left"]).min, controller.absinfo(options["control_map"]["wheel_left"]).max, rrc.roomba.WHEEL_PWM_MIN, rrc.roomba.WHEEL_PWM_MAX, invert_axis=(options["control_map"]["wheel_left"] in options["invert_axis_list"]), center_deadband=options["drive_axis_deadband"], pwm_limit=options["cli_args"]["limit_speed"]) right_wheel_axis = rrc.roomba.AxisToPWM( controller.absinfo(options["control_map"]["wheel_right"]).min, controller.absinfo(options["control_map"]["wheel_right"]).max, rrc.roomba.WHEEL_PWM_MIN, rrc.roomba.WHEEL_PWM_MAX, invert_axis=(options["control_map"]["wheel_right"] in options["invert_axis_list"]), center_deadband=options["drive_axis_deadband"], pwm_limit=options["cli_args"]["limit_speed"]) cleaning_motors = rrc.roomba.CleaningMotors( roomba, controller.absinfo(options["control_map"]["cleaning_motor_speed"]).min, controller.absinfo(options["control_map"]["cleaning_motor_speed"]).max) while not shutdown_event.is_set(): ev = controller.read_one() if not ev: time.sleep(0.01) continue # `drive_update` is used to determine if there's a change to the drive wheel speed # With my DS4, there's a large amount of jitter on the analog stick centers # that causes a lot of extra events, so the Roomba's wheel speeds will only # be updated if there is a change outside of the deadband. drive_update = False if ev.code == options["control_map"]["wheel_left"]: drive_update = left_wheel_axis.update(ev.value) elif ev.code == options["control_map"]["wheel_right"]: drive_update = right_wheel_axis.update(ev.value) elif ev.code == options["control_map"]["wheel_full_speed"]: logging.debug(evdev.categorize(ev)) wheel_full_speed = bool(ev.value) logging.info( f"Full speed {'enabled' if wheel_full_speed else 'disabled'}.") drive_update = True elif ev.code == options["control_map"]["cleaning_motor_speed"]: logging.debug("%s, %s", evdev.categorize(ev), ev.value) _ = cleaning_motors.store_axis(ev.value) elif ev.code == options["control_map"][ "cleaning_motor_set_toggle"] and ev.value == 1: logging.debug(evdev.categorize(ev)) cleaning_motors.apply_stored_speed() elif ev.code == options["control_map"]["auto_clean"] and ev.value == 1: logging.debug(evdev.categorize(ev)) logging.info("Auto cleaning mode...") roomba.start_cleaning() elif ev.code == options["control_map"]["seek_dock"] and ev.value == 1: logging.debug(evdev.categorize(ev)) logging.info("Seek dock...") roomba.start_seek_dock() elif ev.code == options["control_map"]["restart_oi"] and ev.value == 1: logging.debug(evdev.categorize(ev)) logging.info("Restarting ROI...") # Roomba automatically turns off cleaning motors when ROI is restarted, # so update the cleaning_motors.running state to reflect this. cleaning_motors.running = False roomba.change_mode_to_passive() time.sleep(1) if options["cli_args"]["unsafe"]: roomba.change_mode_to_full() else: roomba.change_mode_to_safe() logging.info("ROI restarted.") else: continue if drive_update: left_wheel_pwm = left_wheel_axis.to_pwm(wheel_full_speed) right_wheel_pwm = right_wheel_axis.to_pwm(wheel_full_speed) logging.debug("left_wheel_pwm=%s, right_wheel_pwm=%s", left_wheel_pwm, right_wheel_pwm) roomba.send_drive_pwm(right_wheel_pwm, left_wheel_pwm)
class BleGamePad: STEERING_AXIS = ecodes.ABS_X THROTTLE_AXIS = ecodes.ABS_Y MODE_AXIS = ecodes.ABS_RY STATUS_AXIS = ecodes.ABS_RZ # TODO: ecodes for butan when recording starts def __init__(self, path): self.device = InputDevice(path); self.inputs = { self.STEERING_AXIS: 0, self.THROTTLE_AXIS: 0, self.MODE_AXIS: 0, self.STATUS_AXIS: 0, } # self.driving = False def run(self): """ Query and process relevant evdev events. """ for event in self.device.read_loop(): # if not self.esc_started: # if event.code == ecodes.BTN_START: # self.esc_started = True if event.type == ecodes.EV_KEY: print(event.code) # testing dpad/hat if event.type == ecodes.EV_ABS: if event.code in self.inputs: self.inputs[event.code] = self.process_axis(event.code, event.value) def is_started(self): """ Check if tx is in drive mode""" return self.inputs['STATUS_AXIS'] < 0 def norm(self, val, v_min, v_max, low=0.0, high=1.0): """ Norm a number. """ return (high - low) * (val - v_min) / (v_max - v_min) + low def norm_axis(self, axis, low=0.0, high=1.0): """ Norm an axis. """ ax_val = self.inputs[axis] ax_info = self.device.absinfo(axis) ax_min = ax_info.min ax_max = ax_info.max return self.norm(ax_val, ax_min, ax_max, low, high) def get_steering(self, low=-1.0, high=1.0): """ Return normed steering input. """ return self.norm_axis(ecodes.ABS_X, low, high) def get_throttle(self, low=-1.0, high=1.0): """ Return normed combined throttle input. """ return self.norm(self.THROTTLE_AXIS, -1.0, 1.0, low, high) # TODO: verify axis info def process_axis(self, axis, val): """ Constrain/process abs event. """ ax_info = self.device.absinfo(axis) if val > ax_info.max: val = ax_info.max elif val < ax_info.min: val = ax_info.min if abs(val) < ax_info.flat: return 0 if abs(self.inputs[axis] - val) < ax_info.fuzz: return self.inputs[axis] # else return val
elif power > 0: GPIO.output(self.in1, GPIO.HIGH) GPIO.output(self.in2, GPIO.LOW) self.p.ChangeDutyCycle( max(0, min(abs(power * (100 - self.MP) + self.MP), 100))) # print("fwd") else: GPIO.output(self.in1, GPIO.LOW) GPIO.output(self.in2, GPIO.HIGH) self.p.ChangeDutyCycle( max(0, min(abs(power * (100 - self.MP) - self.MP), 100))) # print("bckwd") minimumSensitivity = 0 leftMotor = Motor(24, 23, 25, 0) rightMotor = Motor(27, 22, 17, 0) gamepad = InputDevice('/dev/input/event2') while (1): overall = (gamepad.absinfo(10).value - gamepad.absinfo(9).value) / gamepad.absinfo(9).max angle = (gamepad.absinfo(0).value - gamepad.absinfo(0).max / 2) / gamepad.absinfo(0).max leftMotor.setPower(overall - angle) rightMotor.setPower(overall + angle) print(overall)
class XBoxController: """ A class to represent an XBox One Controller. """ STEERING_AXIS = ecodes.ABS_X THROTTLE_AXIS_POS = ecodes.ABS_RZ THROTTLE_AXIS_NEG = ecodes.ABS_Z def __init__(self, path): self.device = InputDevice(path) self.inputs = { self.STEERING_AXIS: 0, self.THROTTLE_AXIS_POS: 0, self.THROTTLE_AXIS_NEG: 0, } self.esc_started = False def run(self): """ Query and process relevant evdev events. """ for event in self.device.read_loop(): if not self.esc_started: if event.code == ecodes.BTN_START: self.esc_started = True elif event.type == ecodes.EV_ABS: if event.code in self.inputs: self.inputs[event.code] = self.process_axis(event.code, event.value) def is_started(self): """ Check if esc has been started/calibrated. """ return self.esc_started def norm(self, val, v_min, v_max, low=0.0, high=1.0): """ Norm a number. """ return (high - low) * (val - v_min) / (v_max - v_min) + low def norm_axis(self, axis, low=0.0, high=1.0): """ Norm an axis. """ ax_val = self.inputs[axis] ax_info = self.device.absinfo(axis) ax_min = ax_info.min ax_max = ax_info.max return self.norm(ax_val, ax_min, ax_max, low, high) def get_steering(self, low=-1.0, high=1.0): """ Return normed steering input. """ return self.norm_axis(ecodes.ABS_X, low, high) def get_throttle(self, low=-1.0, high=1.0): """ Return normed combined throttle input. """ t_pos = self.norm_axis(ecodes.ABS_RZ) t_neg = self.norm_axis(ecodes.ABS_Z) return self.norm(t_pos-t_neg, -1.0, 1.0, low, high) def process_axis(self, axis, val): """ Constrain/process abs event. """ ax_info = self.device.absinfo(axis) if val > ax_info.max: val = ax_info.max elif val < ax_info.min: val = ax_info.min if abs(val) < ax_info.flat: return 0 if abs(self.inputs[axis] - val) < ax_info.fuzz: return self.inputs[axis] # else return val def stop(self): """ Closes evdev InputDevice. """ self.device.close()