Может ли экземпляр дочернего класса использовать методы родительского класса в Python? [закрыто]Python

Программы на Python
Ответить Пред. темаСлед. тема
Anonymous
 Может ли экземпляр дочернего класса использовать методы родительского класса в Python? [закрыто]

Сообщение Anonymous »

Проблема:
У меня есть базовый класс робота (gopigo3), который реализует низкоуровневые методы робота.
У меня также есть класс, наследующий базовый робот класс (easygopigo3), который позволяет использовать методы низкого уровня без всех суетливых деталей.
Я написал базовую программу на Python (test_servos), которая перемещает сервоприводы вокруг перемещения робота по панорамированию и наклону из стороны в сторону, вверх и вниз.
Соответствующая часть класса GoPiGo3 (базовый класс) выглядит следующим образом:
Соответствующая часть класса GoPiGo3 (базовый класс) выглядит следующим образом:
р>

Код: Выделить всё

# https://www.dexterindustries.com/GoPiGo/
# https://github.com/DexterInd/GoPiGo3
#
# Copyright (c) 2017 Dexter Industries
# Released under the MIT license (http://choosealicense.com/licenses/mit/).
# For more information see https://github.com/DexterInd/GoPiGo3/blob/master/LICENSE.md
#
# Python drivers for the GoPiGo3

from __future__ import print_function
from __future__ import division
#from builtins import input
hardware_connected = True
__version__ = "1.3.2"

import subprocess # for executing system calls
try:
import spidev
import fcntl      # for lockf mutex support
except:
hardware_connected = False
print ("Can't import spidev or fcntl")

import math       # import math for math.pi constant
import time
import json

FIRMWARE_VERSION_REQUIRED = "1.0.x" # Make sure the top 2 of 3 numbers match

import pigpio

if hardware_connected:
GPG_SPI = spidev.SpiDev()
GPG_SPI.open(0, 1)
GPG_SPI.max_speed_hz = 500000
GPG_SPI.mode = 0b00
GPG_SPI.bits_per_word = 8

class GoPiGo3(object):
WHEEL_BASE_WIDTH         = 117  # distance (mm) from left wheel to right wheel. This works with the initial GPG3 prototype.  Will need to be adjusted.
WHEEL_DIAMETER           = 66.5 # wheel diameter (mm)
WHEEL_BASE_CIRCUMFERENCE = WHEEL_BASE_WIDTH * math.pi # The circumference of the circle the wheels will trace while turning (mm)
WHEEL_CIRCUMFERENCE      = WHEEL_DIAMETER   * math.pi # The circumference of the wheels (mm)

MOTOR_GEAR_RATIO           = 120 # Motor gear ratio # 220 for Nicole's prototype
ENCODER_TICKS_PER_ROTATION = 6   # Encoder ticks per motor rotation (number of magnet positions) # 16 for early prototypes
MOTOR_TICKS_PER_DEGREE = ((MOTOR_GEAR_RATIO * ENCODER_TICKS_PER_ROTATION) / 360.0) # encoder ticks per output shaft rotation degree

GROVE_I2C_LENGTH_LIMIT = 32

SPI_MESSAGE_TYPE = Enumeration("""
NONE,

GET_MANUFACTURER,
GET_NAME,
GET_HARDWARE_VERSION,
GET_FIRMWARE_VERSION,
GET_ID,

SET_LED,

GET_VOLTAGE_5V,
GET_VOLTAGE_VCC,

SET_SERVO,

SET_MOTOR_PWM,

SET_MOTOR_POSITION,
SET_MOTOR_POSITION_KP,
SET_MOTOR_POSITION_KD,

SET_MOTOR_DPS,

SET_MOTOR_LIMITS,

OFFSET_MOTOR_ENCODER,

GET_MOTOR_ENCODER_LEFT,
GET_MOTOR_ENCODER_RIGHT,

GET_MOTOR_STATUS_LEFT,
GET_MOTOR_STATUS_RIGHT,

SET_GROVE_TYPE,
SET_GROVE_MODE,
SET_GROVE_STATE,
SET_GROVE_PWM_DUTY,
SET_GROVE_PWM_FREQUENCY,

GET_GROVE_VALUE_1,
GET_GROVE_VALUE_2,
GET_GROVE_STATE_1_1,
GET_GROVE_STATE_1_2,
GET_GROVE_STATE_2_1,
GET_GROVE_STATE_2_2,
GET_GROVE_VOLTAGE_1_1,
GET_GROVE_VOLTAGE_1_2,
GET_GROVE_VOLTAGE_2_1,
GET_GROVE_VOLTAGE_2_2,
GET_GROVE_ANALOG_1_1,
GET_GROVE_ANALOG_1_2,
GET_GROVE_ANALOG_2_1,
GET_GROVE_ANALOG_2_2,

START_GROVE_I2C_1,
START_GROVE_I2C_2,
""")

GROVE_TYPE = Enumeration("""
CUSTOM = 1,
IR_DI_REMOTE,
IR_EV3_REMOTE,
US,
I2C,
""")

GROVE_STATE = Enumeration("""
VALID_DATA,
NOT_CONFIGURED,
CONFIGURING,
NO_DATA,
I2C_ERROR,
""")

LED_EYE_LEFT      = 0x02
LED_EYE_RIGHT     = 0x01
LED_BLINKER_LEFT  = 0x04
LED_BLINKER_RIGHT = 0x08
LED_LEFT_EYE      = LED_EYE_LEFT
LED_RIGHT_EYE     = LED_EYE_RIGHT
LED_LEFT_BLINKER  = LED_BLINKER_LEFT
LED_RIGHT_BLINKER = LED_BLINKER_RIGHT
LED_WIFI  = 0x80 # Used to indicate WiFi status. Should not be controlled by the user.

SERVO_1 = 0x01
SERVO_2 = 0x02

MOTOR_LEFT  = 0x01
MOTOR_RIGHT = 0x02

MOTOR_FLOAT = -128

GROVE_1_1 = 0x01
GROVE_1_2 = 0x02
GROVE_2_1 = 0x04
GROVE_2_2 = 0x08

GROVE_1 = GROVE_1_1 + GROVE_1_2
GROVE_2 = GROVE_2_1 + GROVE_2_2

GroveType = [0, 0]
GroveI2CInBytes = [0, 0]

GROVE_INPUT_DIGITAL          = 0
GROVE_OUTPUT_DIGITAL         = 1
GROVE_INPUT_DIGITAL_PULLUP   = 2
GROVE_INPUT_DIGITAL_PULLDOWN = 3
GROVE_INPUT_ANALOG           = 4
GROVE_OUTPUT_PWM             = 5
GROVE_INPUT_ANALOG_PULLUP    = 6
GROVE_INPUT_ANALOG_PULLDOWN  = 7

GROVE_LOW  = 0
GROVE_HIGH = 1

def __init__(self, addr = 8, detect = True, config_file_path="/home/pi/Dexter/gpg3_config.json"):
"""
Do any necessary configuration, and optionally detect the GoPiGo3

* Optionally set the SPI address to something other than 8
* Optionally disable the detection of the GoPiGo3 hardware. This can be used for debugging
and testing when the GoPiGo3 would otherwise not pass the detection tests.

The ``config_file_path`` parameter represents the path to a JSON file. The presence of this configuration file is optional and is only required in cases where
the GoPiGo3 has a skewed trajectory due to minor differences in these two constants: the **wheel diameter** and the **wheel base width**.  In most cases, this won't be the case.

By-default, the constructor tries to read the ``config_file_path`` file and silently fails if something goes wrong: wrong permissions, non-existent file, improper key values and so on.
To set custom values to these 2 constants, use :py:meth:`~easygopigo3.EasyGoPiGo3.set_robot_constants` method and for saving the constants to a file call
:py:meth:`~easygopigo3.EasyGoPiGo3.save_robot_constants` method.

"""

# Make sure the SPI lines are configured for mode ALT0 so that the hardware SPI controller can use them
# subprocess.call('gpio mode 12 ALT0', shell=True)
# subprocess.call('gpio mode 13 ALT0', shell=True)
# subprocess.call('gpio mode 14 ALT0', shell=True)

pi_gpio = pigpio.pi()
pi_gpio.set_mode(9, pigpio.ALT0)
pi_gpio.set_mode(10, pigpio.ALT0)
pi_gpio.set_mode(11, pigpio.ALT0)
pi_gpio.stop()

self.SPI_Address = addr
if detect == True:
try:
manufacturer = self.get_manufacturer()
board = self.get_board()
vfw = self.get_version_firmware()
except IOError:
raise IOError("No SPI response.  GoPiGo3 with address %d not connected." % addr)
if manufacturer != "Dexter Industries" or board != "GoPiGo3":
raise IOError("GoPiGo3 with address %d not connected." % addr)
if vfw.split('.')[0] != FIRMWARE_VERSION_REQUIRED.split('.')[0] or \
vfw.split('.')[1] != FIRMWARE_VERSION_REQUIRED.split('.')[1]:
raise FirmwareVersionError("GoPiGo3 firmware needs to be version %s but is currently version %s" \
% (FIRMWARE_VERSION_REQUIRED, vfw))

# load wheel diameter & wheel base width
# also default ENCODER_TICKS_PER_ROTATION and MOTOR_GEAR_RATIO
# should there be a problem doing that then save the current default configuration
try:
self.load_robot_constants(config_file_path)
except Exception as e:
pass

def get_id(self):
"""
Read the 128-bit GoPiGo3 hardware serial number

Returns touple:
serial number as 32 char HEX formatted string, error
"""
outArray = [self.SPI_Address, self.SPI_MESSAGE_TYPE.GET_ID,\
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
reply = self.spi_transfer_array(outArray)
if(reply[3] == 0xA5):
return ("%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X" % \
(reply[4], reply[5], reply[6], reply[7], reply[8], reply[9], reply[10], reply[11], \
reply[12], reply[13], reply[14], reply[15], reply[16], reply[17], reply[18], reply[19]))
raise IOError("No SPI response")
return "00000000000000000000000000000000"
Соответствующая часть класса easygopigo3 (наследующий класс) выглядит следующим образом:

Код: Выделить всё

#!/usr/bin/env python3
from __future__ import print_function
from __future__ import division
# from builtins import input

import sys
# import tty
# import select
import time
import os
import math
import json
import easysensors
from I2C_mutex import Mutex

__version__ = "1.3.2.1"

try:
from di_sensors import easy_line_follower, easy_distance_sensor, easy_light_color_sensor, easy_inertial_measurement_unit
di_sensors_available = True
except ImportError as err:
di_sensors_available = False
print("Importing di_sensors error: {}".format(err))
except Exception as err:
di_sensors_available = False
print("Importing di_sensors error: {}".format(err))

mutex = Mutex(debug=False)

hardware_connected = True
try:
import gopigo3
except ImportError:
hardware_connected = False
print("Cannot import gopigo3 library")
except Exception as e:
hardware_connected = False
print("Unknown issue while importing gopigo3")
print(e)

# try:
#     from line_follower import line_sensor
#     from line_follower import scratch_line

#     # is_line_follower_accessible not really used, just in case
#     is_line_follower_accessible = True
# except:
#     try:
#         sys.path.insert(0, '/home/pi/GoPiGo/Software/Python/line_follower')
#         import line_sensor
#         import scratch_line
#         is_line_follower_accessible = True
#     except:
#         is_line_follower_accessible = False

##########################

def debug(in_str):
if False:
print(in_str)

#####################################################################
#
# EASYGOPIGO3
#
#####################################################################

class EasyGoPiGo3(gopigo3.GoPiGo3):
"""
This class is used for controlling a `GoPiGo3`_ robot.

With this class you can do the following things with your `GoPiGo3`_:

* Drive your robot in any number of directions.
* Have precise control over the direction of the robot.
* Set the speed of the robot.
* Turn *on* or *off* the blinker LEDs.
* Control the `GoPiGo3`_' Dex's *eyes*, *color* and so on ...

.. needs revisiting

..  warning::

Without a battery pack connected to the `GoPiGo3`_, the robot won't move.

"""

def __init__(self, config_file_path="/home/pi/Dexter/gpg3_config.json", use_mutex=False):
"""
This constructor sets the variables to the following values:

:param str config_file_path = "/home/pi/Dexter/gpg3_config.json": Path to JSON config file that stores the wheel diameter and wheel base width for the GoPiGo3.
:param boolean use_mutex = False: When using multiple threads/processes that access the same resource/device, mutex has to be enabled.
:var int speed = 300: The speed of the motors should go between **0-1000** DPS.
:var tuple(int,int,int) left_eye_color = (0,255,255): Set Dex's left eye color to **turqoise**.
:var tuple(int,int,int) right_eye_color = (0,255,255): Set Dex's right eye color to **turqoise**.
:var int DEFAULT_SPEED = 300: Starting speed value: not too fast, not too slow.
:raises IOError: When the GoPiGo3 is not detected. It also debugs a message in the terminal.
:raises gopigo3.FirmwareVersionError: If the GoPiGo3 firmware needs to be updated. It also debugs a message in the terminal.
:raises Exception: For any other kind of exceptions.

"""
try:
if sys.version_info[0] < 3:
super(self.__class__, self).__init__(config_file_path=config_file_path)
else:
super().__init__(config_file_path=config_file_path)
except IOError as e:
print("FATAL ERROR:\nGoPiGo3 is not detected.")
raise e
except gopigo3.FirmwareVersionError as e:
print("FATAL ERROR:\nTo update the firmware on Raspbian for Robots you need to run DI Software Update and choose Update Robot")
raise e
except Exception as e:
raise e

self.sensor_1 = None
self.sensor_2 = None
self.DEFAULT_SPEED = 300
self.NO_LIMIT_SPEED = 1000
self.set_speed(self.DEFAULT_SPEED)
self.left_eye_color = (0, 255, 255)
self.right_eye_color = (0, 255, 255)
self.use_mutex = use_mutex
Моя процедура «test_servos» хочет использовать индивидуальный серийный номер для каждого робота, чтобы установить соответствующие константы центрирования сервопривода, поскольку они разные. Однако метод, который получает серийный номер робота, является методом базового класса (gopigo3), а не наследующего класса (easygopigo3).
Моя процедура test_servos выглядит так:

Код: Выделить всё

#!/usr/bin/python3.7

import easygopigo3 as easy
import time
import gopigo3 # import the GoPiGo3 drivers

# Instantiate native GoPiGo libraries
difficult_gpg = gopigo3.GoPiGo3() # Create an instance of the GoPiGo3 class.  GPG will be the GoPiGo3 object.

serial_number = difficult_gpg.get_id() # read and display the serial number

# Instantiate easy GoPiGo libraries
easy_gpg = easy.EasyGoPiGo3()
servo_1 = easy_gpg.init_servo('SERVO1')
servo_2 = easy_gpg.init_servo('SERVO2')
sleep_time = 0.50  # pause time in seconds

#Servo constants
if serial_number == "A0F6E45F4E514B4B41202020FF152B11":
# Charlene's servo constants
print("Serial number is", serial_number)
print("Robot is \"Charlene\"")
center_1 = 86
center_2 = 80
right = center_1 - 45
left = center_1 + 45
up = center_2 - 45
down = center_2 + 45

elif serial_number == "A0F6E45F4E514B4B41202020FF152B12":
# Charlie's servo constants
center_1 = 86
center_2 = 80
right = center_1 - 45
left = center_1 + 45
up = center_2 - 45
down = center_2 + 45

else:
print("I don't know who robot", serial_number, "is.")
print("(or if it's even a robot) Aborting!")
quit()

# start
print("Center Both Servos")
servo_1.rotate_servo(center_1)
servo_2.rotate_servo(center_2)
time.sleep(sleep_time)

print("Test Servo 1")
servo_1.rotate_servo(right)
time.sleep(sleep_time)
servo_1.rotate_servo(left)
time.sleep(sleep_time)
servo_1.rotate_servo(center_1)
time.sleep(sleep_time)

print("Test Servo 2")
servo_2.rotate_servo(up)
time.sleep(sleep_time)
servo_2.rotate_servo(down)
time.sleep(sleep_time)

print("Re-Center Both Servos")
servo_1.rotate_servo(center_1)
servo_2.rotate_servo(center_2)
time.sleep(sleep_time)
servo_1.disable_servo()
servo_2.disable_servo()
В приведенном выше коде вы заметите, что я создаю экземпляры обоих классов, чтобы иметь возможность использовать методы базового класса. Однако «дзен» кода «Pythonic» указывает на то, что я должен быть как можно ленивее и использовать минимум кода, необходимый для выполнения работы. Мне кажется, что я должен иметь возможность использовать методы базового класса изнутри наследующего класса, не создавая отдельный экземпляр.
Учитывая всю эту информацию, как мне использовать базовый класс? ' методы в экземпляре моего кода наследующего класса?

Подробнее здесь: https://stackoverflow.com/questions/790 ... -in-python
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «Python»