API Reference

Controlling the supercars

Controller

class anki.Controller(*, timeout: float = 10)

This object controls all vehicle connections. With it you can connect to any number of vehicles and disconnect cleanly.

Parameters:

timeoutfloat The time until the controller gives up searching for a vehicle.

async connect_many(amount: int, vehicle_ids: Collection[int | None] | None = None) tuple[anki.control.vehicle.Vehicle, ...]

Connect to <amount> non-charging Supercars

Parameters:
  • amountint The amount of vehicles to connect to

  • vehicle_idsOptional[Iterable[int]] The vehicle ids passed to the Vehicle instances

Returns:

The connected supercars

Return type:

tuple[Vehicle]

Raises:
  • ValueError – The amount of requested supercars does not match the length of :param vehicle_ids:

  • VehicleNotFound – No supercar was found in the set timeout

  • ConnectionTimedoutException – A connection attempt to one of the supercars timed out

  • ConnectionDatabusException – A databus error occured whilst connecting to a supercar

  • ConnectionFailedException – A generic error occured whilst connecting to a supercar

  • RuntimeError – A vehicle with the specified id already exists. This will only be raised when using a custom id.

async connect_one(vehicle_id: int | None = None) Vehicle

Connect to one non-charging Supercar and return the Vehicle instance

Parameters:

vehicle_idOptional[int] The id given to the Vehicle instance on connection

Returns:

The connected supercar

Return type:

Vehicle

Raises:
  • VehicleNotFound – No supercar was found in the set timeout

  • ConnectionTimedoutException – The connection attempt to the supercar did not succeed within the set timeout

  • ConnectionDatabusException – A databus error occured whilst connecting to the supercar

  • ConnectionFailedException – A generic error occured whilst connection to the supercar

  • RuntimeError – A vehicle with the specified id already exists. This will only be raised when using a custom id.

async connect_specific(address: str, vehicle_id: int | None = None) Vehicle

Connect to a supercar with a specified MAC address

Parameters:
  • addressstr The MAC-address of the vehicle to connect to. Needs to be uppercase seperated by colons

  • vehicle_idint The id passed to the Vehicle object on its creation

Returns:

The connected supercar

Return type:

Vehicle

Raises:
  • VehicleNotFound – No supercar was found in the set timeout

  • ConnectionTimedoutException – The connection attempt to the supercar did not succeed within the set timeout

  • ConnectionDatabusException – A databus error occured whilst connecting to the supercar

  • ConnectionFailedException – A generic error occured whilst connection to the supercar

  • RuntimeError – A vehicle with the specified id already exists. This will only be raised when using a custom id.

async disconnect_all()

Disconnects from all the connected supercars

Raises:
  • DisconnectTimedoutException – A disconnection attempt timed out

  • DisconnectFailedException – A disconnection attempt failed for unspecific reasons

async scan(scan_vehicle: ~anki.control.vehicle.Vehicle | None = None, /, align_pre_scan: bool = True, scanner_class: type[anki.control.scanner.BaseScanner] = <class 'anki.control.scanner.Scanner'>) list[anki.misc.track_pieces.TrackPiece]

Assembles a digital copy of the map and adds it to every connected vehicle.

Parameters:
  • scan_vehicleOptional[Vehicle] When passed a Vehicle object, this Vehicle will be used as a scanner. Otherwise one will be selected automatically.

  • align_pre_scanbool When set to True, the supercars can start from any position on the map and align automatically before scanning. Disabling this means your supercars need to start between START and FINISH

  • scanner_classtype The type of scanner used

Returns:

The resulting map

Return type:

list[TrackPiece]

Raises:

DuplicateScanWarning – The map was already scanned in. This scan will be skipped.

Vehicle

class anki.Vehicle(id: int, device: BLEDevice, client: BleakClient | None = None, controller: Controller | None = None, *, battery: BatteryState)

This class represents a supercar. With it you can control all functions of said supercar.

Parameters:
  • idint The id of the Vehicle object

  • devicebleak.BLEDevice The BLE device representing the supercar

  • clientOptional[bleak.BleakClient] A client wrapper around the BLE device

Note

You should not create this class manually, use one of the connect methods in the Controller.

async align(speed: int = 300, *, target_previous_track_piece_type: TrackPieceType = TrackPieceType.FINISH)

Align to the start piece.

Parameters:

speedint The speed the vehicle should travel at during alignment

battery_change(func: Callable[[], None])

Register a callback to execute on changes to the battery state.

Note

It is not guaranteed that the battery state has actually changed from the last callback. Further note that this function is not called on startup.

Raises:

ValueError – The function passed is not an event handler

property battery_state: BatteryState

The state of the supercar’s battery

async change_lane(lane: BaseLane, horizontalSpeed: int = 300, horizontalAcceleration: int = 300, *, _hopIntent: int = 0, _tag: int = 0)

Change to a desired lane

Parameters:
  • laneBaseLane The lane to move into. These may be Lane3 or Lane4

  • horizontalSpeedOptional[int] The speed the vehicle will move along the track at in mm/s

  • horizontalAccelerationOptional[int] The acceleration in mm/s² the vehicle will move horizontally with

Note

Due to a hardware limitation vehicles won’t reliably perform lane changes under 300mm/s speed.

async change_position(roadCenterOffset: float, horizontalSpeed: int = 300, horizontalAcceleration: int = 300, *, _hopIntent: int = 0, _tag: int = 0)

Change to a position offset from the track centre

Parameters:
  • roadCenterOffsetfloat The target offset from the centre of the track piece in mm

  • horizontalSpeedint The speed the vehicle will move along the track at in mm/s

  • horizontalAccelerationint The acceleration in mm/s² the vehicle will move horizontally with

Note

Due to a hardware limitation vehicles won’t reliably perform lane changes under 300mm/s speed.

async connect()

Connect to the Supercar Don’t forget to call Vehicle.disconnect on program exit!

Raises:
  • ConnectionTimedoutException – The connection attempt to the supercar did not succeed within the set timeout

  • ConnectionDatabusException – A databus error occured whilst connecting to the supercar

  • ConnectionFailedException – A generic error occured whilst connection to the supercar

property current_lane3: Lane3 | None

Short-hand for

Vehicle.get_lane(Lane3)
property current_lane4: Lane4 | None

Short-hand for

Vehicle.get_lane(Lane4)
property current_track_piece: TrackPiece | None

The TrackPiece the vehicle is currently located at

Note

This will return None if either scan or align is not completed

delocalized(func: Callable[[], None])

A decorator marking this function to be execute when the vehicle has delocalized*.

Parameters:

funcfunction The listening function

Note

It is not guaranteed that the handler will be called when the vehicle is delocalized. Furthermore, it is not guaranteed that the handler will not be called when the vehicle is still localized. This method should only be used for informational purposes!

async disconnect() bool

Disconnect from the Supercar

Note

Remember to execute this for every connected Vehicle once the program exits. Not doing so will result in your supercars not connecting sometimes as they still think they are connected.

Returns:

  • bool

  • The connection state of the Vehicle instance. This should always be False

Raises:
  • DisconnectTimedoutException – The attempt to disconnect from the supercar timed out

  • DisconnectFailedException – The attempt to disconnect from the supercar failed for an unspecified reason

get_lane(mode: type[_Lane]) _Lane | None

Get the current lane given a specific lane type

Parameters:

modeBaseLane A class such as Lane3 or Lane4 inheriting from BaseLane. This is the lane system being used

Returns:

The lane the vehicle is on. This may be none if no lane information is available (such as at the start of the program, when the vehicles haven’t moved much)

Return type:

Optional[BaseLane]

property id: int

The id of the Vehicle instance. This is set during initialisation of the object.

property is_connected: bool

True if the vehicle is currently connected

property map: tuple[anki.misc.track_pieces.TrackPiece, ...] | None

The map the Vehicle instance is using. This is None if the Vehicle does not have a map supplied.

property map_position: int | None

The position of the Vehicle instance on the map. This is None if Vehicle.align() has not yet been called.

async ping()

Send a ping to the vehicle

pong(func)

A decorator marking an function to be executed when the supercar responds to a ping

Parameters:

funcfunction The function to mark as a listener

Returns:

The function being passed in

Return type:

function

remove_delocalized_watcher(func: Callable[[], None])

Remove a delocalization event handler that was added by Vehicle.delocalized().

Parameters:

funcfunction The function to be removed

Raises:

ValueError – The function passed is not an event handler

remove_track_piece_watcher(func: Callable[[], None])

Remove a track piece event handler added by Vehicle.track_piece_change()

Parameters:

funcfunction The function to remove as an event handler

Raises:

ValueError – The function passed is not an event handler

property road_offset: float | None

The offset from the road centre. This is None if the supercar did not send any information yet. (Such as when it hasn’t moved much)

async set_light_pattern(r: int, g: int, b: int)

Set the engine light (the big one) at the top of the vehicle

Warning

This function is deprecated due to a hardware bug causing it not to function. It will not execute.

async set_lights(light: int)

Set the lights of the vehicle in accordance with a bitmask

Warning

This function is deprecated due to not functioning properly. It will not execute.

async set_speed(speed: int, acceleration: int = 500)

Set the speed of the Supercar in mm/s

Parameters:
  • speedint The speed in mm/s

  • accelerationOptional[int] The acceleration in mm/s²

property speed: int

The speed of the supercar in mm/s. This is None if the supercar has not moved or Vehicle.setSpeed() hasn’t been called yet.

async stop()

Stops the Supercar

track_piece_change(func: Callable[[], None])

A decorator marking a function to be executed when the supercar drives onto a new track piece

Parameters:

funcfunction The listening function

Returns:

The function that was passed in

Return type:

function

async turn(type: int = 3, trigger: int = 0)

Warning

This does not yet function properly. It is advised not to use this method

async wait_for_track_change() TrackPiece | None

Waits until the current track piece changes.

Returns:

The new track piece. None if Vehicle.map() is None (for example if the map has not been scanned yet)

Return type:

TrackPiece

Scanner

class anki.control.scanner.Scanner(vehicle: Vehicle)

A scanner object performs a simple map scan without any alignment.

Parameters:

vehicleVehicle The vehicle to perform the scan with

async align(vehicle: Vehicle, *, target_previous_track_piece_type: TrackPieceType = TrackPieceType.FINISH) None

Aligns a vehicle to the START piece

Parameters:

vehicleVehicle The vehicle to align

async scan() list[anki.misc.track_pieces.TrackPiece]

Perform the scan

Custom Scanning

class anki.control.scanner.BaseScanner(vehicle: Vehicle)

Abstract base class for all custom scanners. Any subclasses of this must override the methods BaseScanner.scan() BaseScanner.align().

Parameters:

vehicleVehicle The vehicle used for the scanning operation.

abstract async align(vehicle: Vehicle, *, target_previous_track_piece_type: TrackPieceType = TrackPieceType.FINISH) None

This method should be used to align a vehicle to the START piece. It is required for this method to work without a functional scan.

Parameters:

vehicleVehicle The vehicle to be aligned.

abstract async scan() list[anki.misc.track_pieces.TrackPiece]

This method should scan in the map using various functionalities. The returned list of track pieces should begin with a type of TrackPieceType.START and end with TrackPieceType.FINISH.

Returns:

The scanned map

Return type:

list[TrackPiece]

Vehicle models

BatteryState

class anki.control.vehicle.BatteryState(full_battery: bool, low_battery: bool | None, on_charger: bool, charging: bool | None = None)

Represents the state of a supercar

classmethod from_charger_info(payload: bytes)

Constructs a BatteryState instance from a CHARGER_INFO message.

Parameters:

payloadbytes The payload of the CHARGER_INFO message

Returns:

classmethod from_int(state: int)

Constructs a BatteryState from an integer representation

Parameters:

stateint The integer state passed by the discovery process

Returns:

Lights

enum anki.Lights(value)
Member Type:

int

Valid values are as follows:

HEADLIGHTS = <Lights.HEADLIGHTS: 0>
BRAKELIGHTS = <Lights.BRAKELIGHTS: 1>
FRONTLIGHTS = <Lights.FRONTLIGHTS: 2>
ENGINELIGHTS = <Lights.ENGINELIGHTS: 3>

Track models

TrackPiece

class anki.TrackPiece(loc: int, type: TrackPieceType, clockwise: bool)

This class represents the different pieces of the track. It includes the type of the track piece and whether or not it turns clockwise.

You should not be creating these manually.

Parameters:
  • locint The loc value send by the supercar. I’m not sure what it means either

  • typeTrackPieceType The type of track piece

  • clockwisebool Whether or not this track piece turns in a clockwise direction

TrackPieceType

enum anki.TrackPieceType(value)

An enumerator for all supported track piece types.

Thank you to https://github.com/BerndMuller/JAnki/

Valid values are as follows:

START = <TrackPieceType.START: [33]>
FINISH = <TrackPieceType.FINISH: [34]>
STRAIGHT = <TrackPieceType.STRAIGHT: [36, 39, 40, 48, 51]>
CURVE = <TrackPieceType.CURVE: [17, 18, 20, 23, 24, 27]>
INTERSECTION = <TrackPieceType.INTERSECTION: [10]>
LAUNCH_START = <TrackPieceType.LAUNCH_START: [43]>

Lane support

BaseLane

class anki.BaseLane(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)

The base class for all Lanes. This class does not provide any lanes of its own, but can be inherited from to create your own lane system. Pre-configured children of this class are Lane3 and Lane4

classmethod by_name(name: str)

Get a lane by the lane’s name.

Parameters:

namestr The name of the lane

Raises:

ValueError – The name passed does not refer to an existing lane

classmethod get_closest_lane(position: float) Self

Returns the lane closest to the entered position.

Parameters:

positionfloat The position offset from the centre of the road in millimetres.

Raises:

RuntimeError – The this method is being called with does not have any specified lanes.

Lane3

enum anki.Lane3(value)

A lane class that supports 3 different lanes. Values indicate the millimetre distance from the road centre.

Member Type:

float

Valid values are as follows:

LEFT = <Lane3.LEFT: -60.0>
MIDDLE = <Lane3.MIDDLE: 0.0>
RIGHT = <Lane3.RIGHT: 60.0>

Lane4

enum anki.Lane4(value)

A lane class that supports 4 different lanes. Values indicate the millimetre distance from the road centre.

Member Type:

float

Valid values are as follows:

LEFT_2 = <Lane4.LEFT_2: -60.0>
LEFT_1 = <Lane4.LEFT_1: -30.0>
RIGHT_1 = <Lane4.RIGHT_1: 30.0>
RIGHT_2 = <Lane4.RIGHT_2: 60.0>

Exceptions

exception anki.errors.AnkiError

Base class for all errors raised by this library

exception anki.errors.ConnectionDatabusError

A data-bus error occured whilst connecting to the vehicle

exception anki.errors.ConnectionFailedError

Could not connect to the vehicle

exception anki.errors.ConnectionTimedoutError

The attempt to connect with the vehicle timed out

exception anki.errors.DisconnectFailedError

The attempt to disconnect from the vehicle failed

exception anki.errors.DisconnectTimedoutError

The disconnect attempt timed out

exception anki.errors.DuplicateScanWarning

The map has already been scanned, but scan has been called anyway. This is not dangerous, but unneccessary

exception anki.errors.MalformedPacketWarning

Received package did not conform to the Protocol. See https://anki.github.io/drive-sdk/docs/programming-guide

exception anki.errors.TrackPieceDecodeWarning

The TrackPiece received from the vehicle was invalid

exception anki.errors.VehicleNotFoundError

Could not find a Supercar