Classes¶
What a class is¶
A class is a blueprint. Think of a class as the plan for a house: it lists the number of floors, the number of rooms, and so on.
From that plan you build an object. One class can produce many objects, each with its own details.
# create class definition
class House:
# default attributes of a House
number_of_floors = 2
number_of_rooms = 3
# create a House object
my_house = House()
print(my_house.number_of_floors) # 2
print(my_house.number_of_rooms) # 3
my_taller_house = House()
my_taller_house.number_of_floors = 4
print(my_taller_house.number_of_floors) # 4
The values stored in an object are its attributes. Read or change one by
putting a . after the object name.
Changing my_taller_house does not affect my_house. They are separate
objects.
Indentation matters here too
Everything indented under class House: belongs to the class.
Class methods¶
A class can contain functions. A function inside a class is called a method. A method can read and change the attributes of its own object.
class Room:
room_width = 0.0
room_length = 0.0
def calculate_area(self):
return self.room_width * self.room_length
my_room = Room()
my_room.room_length = 5.5
my_room.room_width = 6.0
print(my_room.calculate_area()) # 33.0
Call a method the same way you read an attribute: a . after the object
name, then the method name with parentheses.
The self keyword¶
self is the first argument of every method. It refers to the specific object
the method was called on, so self.room_width means "the width of this
room" and not the width of every room.
You never pass self in yourself. Python does it for you when you write
my_room.calculate_area().
A class can have as many methods as you need.
Where you already see this¶
MARLIN is built from classes. Robot, Thruster, Servo, and IMU are all
classes:
from marlin import Robot, Thruster
robot = Robot() # create a Robot object
robot.configure(effectors={"M1": Thruster})
robot.thruster("M1").set_duty(30) # create a Thruster object, then call a method on it
print(robot.battery_voltage) # read an attribute
robot is an object. configure() and run() are methods. battery_voltage
and running are attributes.
How a class becomes real hardware¶
Thruster is the blueprint. Plugging a thruster into port M1 and naming that
port in configure() is what turns the blueprint into one object that
controls one physical thruster.
flowchart LR
cls["Thruster<br/>the class, a blueprint"]
conf["You declare port M1 as a Thruster<br/>inside configure()"]
obj["The Thruster object for M1<br/>created by configure()"]
use["You fetch that object<br/>and call set_duty(30) on it"]
hw["The thruster plugged into<br/>socket M1 on the robot<br/>spins at 30%"]
cls --> conf --> obj
obj --> use --> hw
You never write Thruster() yourself. configure() builds the objects, and
robot.thruster("M1") hands you the one for that port.
A robot with everything plugged in¶
A robot with two thrusters, a servo, and an IMU needs one line of configuration per socket, and each line produces one object:
flowchart LR
subgraph hardware["The physical robot"]
direction TB
pM1["socket M1<br/>thruster"]
pM8["socket M8<br/>thruster"]
pM2["socket M2<br/>servo"]
pS1["socket S1<br/>IMU"]
end
subgraph code["Your Python program"]
direction TB
oM1["a Thruster object<br/>robot.thruster(M1)"]
oM8["a Thruster object<br/>robot.thruster(M8)"]
oM2["a Servo object<br/>robot.servo(M2)"]
oS1["an IMU object<br/>robot.imu(S1)"]
end
oM1 -->|"set_duty(30)"| pM1
oM8 -->|"set_duty(30)"| pM8
oM2 -->|"angle(90)"| pM2
pS1 -->|"read()"| oS1
In code the port name is a piece of text, so it needs quotes:
robot.thruster("M1").
Two things worth noticing:
M1andM8are both built from the sameThrusterclass, but they are two separate objects.set_duty()on one does not move the other, exactly likemy_houseandmy_taller_houseabove.- Effectors point outwards and sensors point inwards. You call methods on an
effector to make it move. You read from a sensor with
read().
The port name in the code must match the socket the hardware is plugged into.
If they disagree, MARLIN stops your program during configure() rather than
letting the robot move the wrong part. See
Hardware configuration.
Going further¶
Classes are a part of Object Oriented Programming (OOP). There is much more to OOP in Python. This page covers only the basics you need for your robot.
OOP is used in most modern languages, so it is worth researching further once you are comfortable with what is here.
Full documentation: https://docs.python.org/3/tutorial/classes.html
What to read next¶
You now have the Python you need. Continue with the MARLIN API guide, starting at Program structure.