sciro.robotics¶
Stubs for sciro.robotics (PeakHub firmware) – control helpers.
EXPERIMENTAL: the API may still change between releases.
- class sciro.robotics.Control¶
Bases:
ControlA drivebase / motor controller, with its built-in logger exposed.
- limits(speed: Number | None = None, acceleration: Number | None = None, torque: Number | None = None) None¶
- limits() Tuple[int, int, int]
Configures the maximum speed, acceleration, and torque.
If no arguments are given, this will return the current values.
The new
accelerationandspeedlimit will become effective when you give a new motor command. Ongoing maneuvers are not affected.- Parameters:
speed (Number, deg/s or Number, mm/s) – Maximum speed. All speed commands will be capped to this value.
acceleration (Number, deg/s² or Number, mm/s²) – Slope of the speed curve when accelerating or decelerating. Use a tuple to set acceleration and deceleration separately. If one value is given, it is used for both.
torque (torque: mNm) – Maximum feedback torque during control.
- pid(kp: Number | None = None, ki: Number | None = None, kd: Number | None = None, integral_deadzone: Number | None = None, integral_rate: Number | None = None) None¶
- pid() Tuple[int, int, int, int, int]
Gets or sets the PID values for position and speed control.
If no arguments are given, this will return the current values.
- Parameters:
kp (int) – Proportional position control constant. It is the feedback torque per degree of error: µNm/deg.
ki (int) – Integral position control constant. It is the feedback torque per accumulated degree of error: µNm/(deg s).
kd (int) – Derivative position (or proportional speed) control constant. It is the feedback torque per unit of speed: µNm/(deg/s).
integral_deadzone (Number, deg or Number, mm) – Zone around the target where the error integral does not accumulate errors.
integral_rate (Number, deg/s or Number, mm/s) – Maximum rate at which the error integral is allowed to grow.
- stall_tolerances(speed: Number | None = None, time: Number | None = None) None¶
- stall_tolerances() Tuple[int, int]
Gets or sets stalling tolerances.
If no arguments are given, this will return the current values.
- Parameters:
speed (Number, deg/s or Number, mm/s) – If the controller cannot reach this speed for some
timeeven with maximum actuation, it is stalled.time (Number, ms) – How long the controller has to be below this minimum
speedbefore we say it is stalled.
- target_tolerances(speed: Number | None = None, position: Number | None = None) None¶
- target_tolerances() Tuple[int, int]
Gets or sets the tolerances that say when a maneuver is done.
If no arguments are given, this will return the current values.
- Parameters:
speed (Number, deg/s or Number, mm/s) – Allowed deviation from zero speed before motion is considered complete.
position (Number, deg or distance: mm) – Allowed deviation from the target before motion is considered complete.
- scale: int¶
Scaling factor between the controlled integer variable and the physical output. For example, for a single motor this is the number of encoder pulses per degree of rotation.
- class sciro.robotics.DriveBase(left_motor: Motor, right_motor: Motor, wheel_diameter: Number, axle_track: Number)¶
Bases:
DriveBasepybricks.robotics.DriveBase(the same class on the hub). The stub adds thelogonheading_control/distance_controland the PeakHub extensions ofstraight().- heading_control: Control = <pybricks._common.Control object>¶
The robot turn angle and turn rate are controlled by a PID controller. You can use this attribute to change its settings. See the motor control attribute for an overview of available methods. The
heading_controlattribute has the same functionality, but the settings apply to every degree of rotation of the whole drive base (viewed from the top) instead of degrees turned by one motor.
- distance_control: Control = <pybricks._common.Control object>¶
The traveled distance and drive speed are controlled by a PID controller. You can use this attribute to change its settings. See the motor control attribute for an overview of available methods. The
distance_controlattribute has the same functionality, but the settings apply to every millimeter driven by the drive base, instead of degrees turned by one motor.
- straight(distance, then=Stop.HOLD, wait=True, speed=None, heading=None, exit_speed=0)¶
Drives straight for
distancemm, as in Pybricks, with three PeakHub extensions (keyword use recommended):speed: drive speed in mm/s for this move only;Noneuses thestraight_speedsetting.heading: absolute heading in degrees to hold during the move instead of the heading at its start (the gyro heading withuse_gyro(True), else the wheel-based one since the lastreset()). Any value is accepted: the nearest whole-turn equivalent of the current heading is targeted, soheading=90while the internal heading reads 450 corrects by 0 degrees, never by a full turn.Nonekeeps the Pybricks behavior.exit_speed: speed in mm/s the robot has when it reaches the target; it keeps driving at that speed until the next command, so the nextstraight()(ordrive()) blends in without a stop. Impliesthen=Stop.NONE; any other explicitthenraisesValueError. Clamped to the move’s drive speed.0(default) stops or holds asthensays.then=Stop.NONEwithoutexit_speedkeeps the upstream meaning: continue at the drive speed.
- turn(angle, then=Stop.HOLD, wait=True, absolute=False, turn_rate=None)¶
Turns in place, as in Pybricks, with one PeakHub extension:
turn_rate: turn rate in deg/s for this move only;Noneuses theturn_ratesetting, which is left untouched either way.absolute=Trueturns to the given heading rather than by it, taking the nearest whole-turn equivalent, so the correction is always within +/-180 degrees (the same rule asstraight(heading=)).
- curve(radius, angle, then=Stop.HOLD, wait=True, speed=None, exit_speed=0)¶
Drives an arc of
angledegrees along a circle ofradiusmm. Upstream dropped this method in favor ofarc(), but the firmware still has it, so it is declared here to keep it usable without a type error.arc()takes the same extensions and is preferred in new code.speed: drive speed in mm/s along the arc for this move only. The matching turn rate is derived from it, so the linear speed is what governs the duration;Noneuses thestraight_speedandturn_ratesettings.exit_speed: speed in mm/s the robot has when it reaches the end of the arc. The turn rate is brought to zero at that point, so the robot leaves on the tangent and keeps driving straight atexit_speeduntil the next command. This makes a curve-to-straight handover smooth; without it a continuing move keeps rotating at the arc’s turn rate and the next command has to cancel that rotation. The price is that the last fraction of the path is slightly flatter than a true arc. Impliesthen=Stop.NONE; any other explicitthenraisesValueError.
- arc(radius, angle=None, distance=None, then=Stop.HOLD, wait=True, speed=None, exit_speed=0)¶
Drives an arc, as in Pybricks, with the same two PeakHub extensions as
curve():speedin mm/s for this move only (the turn rate is derived from it), andexit_speed, which ends the arc at that speed with the turn rate at zero so the robot exits on the tangent and keeps driving straight.exit_speedimpliesthen=Stop.NONE.
- heading_target(angle) / heading_target() float¶
Steers a running
straight()(PeakHub): replaces the heading setpoint without touching the distance trajectory (position, speed, exit speed and end condition stay). Absolute heading in degrees, float, same frame and nearest-whole-turn rule asstraight(heading=). The heading controller branches off its current reference on a new trajectory, so small steps (the usual < 1 degree per 10 ms) are smooth and large ones are limited by theturn_rate/turn_accelerationsettings. Without an argument returns the current heading target.Typical use, a line follower as a setpoint generator:
db.straight(dist, speed=v, exit_speed=e, heading=course, wait=False) while not db.done(): data = await floor.all_sensor_data() db.heading_target(course + K * data[0]) await wait(10)
Raises
OSErrorwhen nostraight()is running (drive(),turn(),curve(),arc()and an idle drivebase are not steerable).
- angle() float: deg¶
Gets the estimated rotation angle of the drive base.
When the gyro is used for this drive base, this gives the gyro angle. Otherwise, it gives the estimated angle estimated from the motor displacement.
- Returns:
Accumulated angle since last reset.
- brake()¶
Stops the robot by passively braking the motors.
- distance() int: mm¶
Gets the estimated driven distance.
- Returns:
Driven distance since last reset.
- done() bool¶
Checks if an ongoing command or maneuver is done.
- Returns:
Trueif the command is done,Falseif not.
- drive(speed, turn_rate)¶
Starts driving at the specified speed and turn rate. Both values are measured at the center point between the wheels of the robot.
- Parameters:
speed (Number, mm/s) – Speed of the robot.
turn_rate (Number, deg/s) – Turn rate of the robot.
- hold()¶
Stops the robot and actively holds it in place.
- move_by(dx, dy, then=Stop.HOLD)¶
Moves the robot by an amount given as X-and-Y coordinates on the robot drive area. The X-axis is what was forward when the program started. The Y-axis is 90° left of that. You can reset this by resetting the heading.
The robot first turns to the required heading and then drives the straight-line distance. Because the heading target is absolute, the result is independent of the robot’s current heading.
- Parameters:
dx (Number, mm) – X-distance on the drive area.
dy (Number, mm) – Y-distance on the drive area.
then (Stop) – What to do after coming to a standstill.
- Raises:
ValueError – If one of the distances is more than 30 m.
- reset(distance=0, angle=0)¶
Resets the estimated driven distance and heading angle.
This also calls
stop()to stop ongoing movements. If your robot is controlled withuse_gyro()set toTrue, calling this method will also set the gyro to the given angle.- Parameters:
distance (Number, mm) – New value of the driven distance.
angle (Number, deg) – New heading angle of the robot.
- settings(straight_speed: Number | None = None, straight_acceleration: Number | Tuple[Number, Number] | None = None, turn_rate: Number | None = None, turn_acceleration: Number | Tuple[Number, Number] | None = None) None¶
- settings() Tuple[int, int | Tuple[int, int], int, int | Tuple[int, int]]
Configures the drive base speed and acceleration.
If you give no arguments, this returns the current values as a tuple.
The initial values are automatically configured based on your wheel diameter and axle track. They are selected such that your robot drives at about 40% of its maximum speed.
The speed values given here do not apply to the
drive()method, since you provide your own speed values as arguments in that method.Speed and rate values are treated as absolute; negative values are converted to positive automatically.
- Parameters:
straight_speed (Number, mm/s) – Straight-line speed of the robot.
straight_acceleration (Number or Tuple[Number, Number], mm/s²) – Straight-line acceleration and deceleration of the robot. Provide a single value to use the same acceleration and deceleration. Provide a tuple with two values to set them separately.
turn_rate (Number, deg/s) – Turn rate of the robot.
turn_acceleration (Number or Tuple[Number, Number], deg/s²) – Angular acceleration and deceleration of the robot. Provide a single value to use the same acceleration and deceleration. Provide a tuple with two values to set them separately.
- stalled() bool¶
Checks if the drive base is currently stalled.
It is stalled when it cannot reach the target speed or position, even with the maximum actuation signal.
- Returns:
Trueif the drive base is stalled,Falseif not.
- state() Tuple[int, int, int, int]¶
Gets the state of the robot.
As with the
angle()methods, the reported angle and turn rate are those of the gyro if the gyro is used. Otherwise they are estimated from the motor displacement.- Returns:
Tuple of distance, drive speed, angle, and turn rate of the robot.
- stop()¶
Stops the robot by letting the motors spin freely.
- class sciro.robotics.PIDController(kp: float, ki: float = 0.0, kd: float = 0.0, integral_limit: float | None = None, output_limit: float | None = None, reset_after: int | None = 100, stopwatch: StopWatch | None = None, log: RingBuffer | None = None, name: str = 'PID')¶
Bases:
objectDiscrete PID controller:
output = kp*e + ki*integral(e) + kd*de/dt.ki = kd = 0gives a plain P or PD controller.integral_limitclamps the I term (anti-windup),output_limitthe total output;Nonemeans unlimited. A gap between updates longer thanreset_aftermilliseconds restarts the controller (a new movement);Nonenever.stopwatchis the time source (default: an ownStopWatch);logaRingBufferwithLOG_FIELDS(seemake_log()).- LOG_FIELDS: Tuple[Tuple[str, str], ...]¶
t_ms, dt, error, p, i, d, output– the row layout of the log.
- kp: float¶
- ki: float¶
- kd: float¶
- integral_limit: float | None¶
- output_limit: float | None¶
- reset_after: int | None¶
- log: RingBuffer | None¶
- name: str¶
- output: float¶
The last output.
- integral: float¶
- make_log(seconds: float, rate: int = 100) RingBuffer¶
Attach and return a RingBuffer for
secondsof updates atrateHz.
- reset() None¶
Forget the integral, the last error and the last update time.
- update(error: float, derivative: float | None = None, p_limit: float | None = None) float¶
One controller step; returns the output.
erroris setpoint minus measurement.derivativeis d(error)/dt when measured (e.g. minus the gyro rate for a heading error);Nonedifferentiates the error numerically.p_limitclamps the P term for this step only, e.g. a braking profile that leaves the D term free to damp.