PyCozmo¶
Overview¶
https://github.com/zayfod/pycozmo
PyCozmo
is a pure-Python communication library, alternative SDK, and application for the
Cozmo robot . It allows controlling a Cozmo robot directly, without
having to go through a mobile device, running the Cozmo app.
The library is loosely based on the Anki Cozmo Python SDK and the cozmoclad (“C-Like Abstract Data”) library.
This project is a tool for exploring the hardware and software of the Digital Dream Labs (originally Anki) Cozmo robot. It is unstable and heavily under development.
Usage¶
Basic:
import time
import pycozmo
with pycozmo.connect() as cli:
cli.set_head_angle(angle=0.6)
time.sleep(1)
Advanced:
import pycozmo
cli = pycozmo.Client()
cli.start()
cli.connect()
cli.wait_for_robot()
cli.drive_wheels(lwheel_speed=50.0, rwheel_speed=50.0, duration=2.0)
cli.disconnect()
cli.stop()
PyCozmo vs. the Cozmo SDK¶
A Cozmo SDK application (aka “game”) acts as a client to the Cozmo app (aka “engine”) that runs on a mobile device.
The low-level communication happens over USB and is handled by the cozmoclad
library.
In contrast, an application using PyCozmo basically replaces the Cozmo app and acts as the “engine”. PyCozmo handles the low-level UDP communication with Cozmo.
+------------------+ +------------------+ +------------------+
| SDK app | Cozmo SDK | Cozmo app | Cozmo | Cozmo |
| "game" | cozmoclad | "engine" | protocol | "robot" |
| | ----------------> | Wi-Fi client | ----------------> | Wi-Fi AP |
| | USB | UDP client | UDP/Wi-Fi | UDP Server |
+------------------+ +------------------+ +------------------+
Requirements¶
- Python 3.6.0 or newer
- Pillow 6.0.0 - Python image library
- FlatBuffers - serialization library
- dpkt - TCP/IP packet parsing library
Installation¶
Using pip:
pip install --user pycozmo
pycozmo_resources.py download
From source:
git clone https://github.com/zayfod/pycozmo.git
cd pycozmo
python setup.py install --user
pycozmo_resources.py download
From source, for development:
git clone git@github.com:zayfod/pycozmo.git
cd pycozmo
python setup.py develop --user
pip install --user -r requirements-dev.txt
pycozmo_resources.py download
Support¶
Bug reports and changes should be sent via GitHub:
https://github.com/zayfod/pycozmo
DDL Robot Discord server, channel #development-cozmo:
Disclaimer¶
This project is not affiliated with Digital Dream Labs or Anki.
PyCozmo Architecture¶
Overview¶
PyCozmo is designed as a multithreaded library.
It is organized in three layers with each higher layer building on the ones below it:
- low-level connection layer
- client or SDK layer
- application layer
Each layer provides it’s own API and can be used independently.
The following diagram illustrates the library architecture.
^
|
+-----------------------------------------+ |
| | |
| Brain | |
| | |
| | |
+-----+--------------+--------------+-----+ |
^ | ^ |
| | | |
+-----------+ +-----+-----+ | | | Application
| | | | | | | Layer
| Heartbeat | | Reaction | | | |
| Thread | | Thread | | | |
| | | | | | |
+-----+-----+ +-----+-----+ | | |
| ^ | Commands | Events |
| | | | |
| +-+ | | |
| |-| Event | | |
| |-| Queue | | |
| +-+ | | |
| ^ | | |
| | | | v
+------------->+ Reactions | |
| v | ^
+-----+--------------+--------------+-----+ |
| | |
| Client | |
| | |
| | |
+-----+--------------+--------------+-----+ |
| | ^ | SDK
v | | | Layer
+-+ | | |
Animation |-| | Commands | Events |
Queue |-| | | |
+-+ | | |
| | | |
v v | |
+-----------+ +-----+-----+ +-----+--------------+-----+ |
| | | | | | |
| Face | | Animation | | Connection | v
| Generator +------>+ Thread | | Thread |
| | | | | | ^
+-----------+ +-----+-----+ +-----+--------------+-----+ |
| | ^ |
+------------->+ | |
| | |
v | |
+-+ +-+ |
Outgoing |-| |-| Incoming |
Message |-| |-| Message |
Queue +-+ +-+ Queue |
| ^ |
v | | Connection
+-----+-----+ +-----+-----+ | Layer
| | | | |
| Send | | Receive | |
| Thread | | Thread | |
| | | | |
+---------+-+ +--+--------+ |
| ^ |
| | |
| | |
v | |
+-+-------+-+ |
| | |
| UDP | |
| Socket | |
| | |
+-----------+ |
v
Connection Layer¶
The connection layer implements the Cozmo communication protocol.
The receive thread reads Cozmo protocol frames, encapsulated in UDP datagrams, from the UDP socket. It maintains a receive window for incoming packets and sends a stream of incoming packets in the correct order over the incoming message queue to the connection thread.
The send thread reads a stream of outgoing packets from the outgoing message queue, builds Cozmo protocol frames and sends them over the UDP socket. It maintains a send window and resends packets that are not acknowledged in time.
The connection thread reads a stream of incoming packets from the incoming message queue and dispatches them to registered handler functions. It sends ping packets on a regular basis to maintain connection with the robot.
Client Layer (SDK)¶
The client layer provides access to robot on-board functions.
It allows sending commands and registering handler function for incoming packets and events.
It performs:
- camera image reconstruction
- display image encoding
- audio encoding
- animation and audio playback
- procedural face generation
The animation controller synchronizes animations, audio playback, and image display. It works as a separate thread that aims to send images and audio to the robot at 30 frames per second. All on-board function of the robot are synchronized to this framerate, including images, audio playback, backpack and cube LED animations.
Application Layer¶
The application layer implements high-level off-board functions:
- reactions and behaviors
- personality engine
- computer vision (CV) camera image processing
Events from the client layer are converted to reactions. The reaction thread reads events from its incoming event queue and handles them appropriately. Reactions normally trigger behaviors.
The heartbeat thread drives the personality engine and timers for activities and behaviors.
Cozmo Protocol¶
Overview¶
The Cozmo protocol is a UDP-based variant of the selective repeat automatic-repeat request (ARQ) protocol.
The Cozmo app (aka “engine”) acts as a client and Cozmo (aka “robot”) acts as a server.
The two exchange frames, encapsulated in UDP packets.
Each frame can contain 0, 1, or more packets.
See protocol_declaration.py
for packet details.
Network Setup¶
The robot acts as a Wi-Fi access point. It always uses an SSID that follows the form “Cozmo_XXXXXX”, where XXXXXX are upper-case hexadecimal digits. It acts as a DHCP server and assigns Wi-Fi clients an IP address in the range 172.31.1.0/24 .
The app searches for robot APs. If it finds only one, it will associate with it automatically. If it finds more than one, it will allow the user to select one manually.
The robot acts as a server. It always uses the IP address 172.31.1.1 and will expect UDP packets on port 5551. It will only accept packets originating from an IP address in the range 172.31.1.0/24 .
The app acts as a client and initiates connections. It will only accept packets originating from the IP address 172.31.1.1 .
+--------------------+ +--------------------+
| Cozmo app | | Cozmo |
| "engine" | UDP/Wi-Fi | "robot" |
| Wi-Fi client | ---------------------> | Wi-Fi AP |
| UDP client | | UDP Server |
+--------------------+ +--------------------+
172.31.1.0/24 172.31.1.1:5551
Frames¶
Each frame has the following structure:
Field Length Description
---------------------------------------------------------------------------------
id 7 Always "COZ\x03RE\x01"
type 1 Frame type
first_seq 2 First packet sequence number in the frame or 0
seq 2 Last packet sequence number in the frame or 0
ack 2 Peer packet sequence number acknowledgement
packets - 0 or more encapsulated packets
Frame types:
Type Source Description
---------------------------------------------------------------------------------
0x01 engine Reset
0x02 robot Reset ACK
0x03 engine Disconnect
0x04 engine Engine packet - single
0x07 engine Engine packets - zero or more
0x09 robot Robot packets - zero or more
0x0b engine Out-of-band engine ping
Packets¶
Packet types:
Type OOB Source Description
---------------------------------------------------------------------------------
0x02 n robot Connect
0x03 n engine Disconnect
0x04 n both Command
0x05 y robot Event
0x0a y engine Keyframe
0x0b y engine Ping
Out of band packets do not get assigned sequence IDs.
Packet content is Cozmo firmware version specific.
Commands and events are identified by an 8-bit ID. IDs in the range 0-0xaf are sent by the engine. IDs in the range 0xb0-0xff are sent by the robot.
IDs in the range 0xf0-0xff are used for out-of-band updates. These are packets that are not tracked by a sequence ID and thus not retransmitted. Only their latest received value is considered important.
ID Min Max Name
---------------------------------------------------------------------------------
0x03 31 31 LightStateCenter
0x04 40 40 CubeLights
0x05 5 5 ObjectConnect
0x0b 1 1 SetHeadLight
0x0c 1 1
0x10 5 5 CubeId
0x11 21 21 LightStateSide
0x25 0 0 Enable
0x32 16 16 DriveWheels
0x33 10 10 TurnInPlaceAtSpeed
0x34 4 4 DriveLift
0x35 4 4 DriveHead
0x36 17 17 SetLiftHeight
0x37 17 17 SetHeadAngle
0x39 20 20 TurnInPlace
0x3b 0 0 StopAllMotors
0x3d DriveStraight
0x45 24 24
0x4b 8 8 EnableBodyACC
0x4c 2 2 EnableCamera
0x50 2 2
0x54 2 2
0x57 7 7 SetCameraParams
0x60 1 1 EnableStopOnCliff
0x64 2 2 SetRobotVolume
0x66 1 1 EnableColorImages
0x80 4 4
0x81 12 144 * NvStorageOp
0x8d 0 0
0x8e 744 744 OutputAudio
0x8f 0 0 OutputSilence
0x93 3 3
0x94 3 3
0x97 4 188 * DisplayImage
0x98 10 10
0x99 4 4
0x9a 0 0
0x9b 1 1
0x9d 1 1
0x9e 1 1
0x9f 0 0 EnableAnimationState
0xa0 16 16
0xaf 1026 1026 FirmwareUpdate
0xb0 8 40 * UnknownB0
0xb2 16 16
0xb4 21 21 ObjectMoved
0xb5 8 8 ObjectStoppedMoving
0xb6 12 12 ObjectTapped
0xb9 10 10 ObjectTapFiltered
0xc2 0 0 RobotDelocalized
0xc3 0 0 RobotPoked
0xc4 1 1 AcknowledgeAction
0xc8 29 29
0xc9 6 6 HardwareInfo
0xca 1 1
0xcb 1 1
0xcd 12 1036 * NvStorageOpResult
0xce 9 9 ObjectPowerLevel
0xcf 8 8
0xd0 13 13 ObjectConnectionState
0xd1 3 3
0xd2 44 44
0xd7 9 9 ObjectUpAxisChanged
0xec 4 4
0xed 12 12 BodyInfo
0xee 449 449 FirmwareSignature
0xef 7 7 FirmwareUpdateResult
0xf0 91 91 RobotState
0xf1 15 15 AnimationState
0xf2 24 1172 * ImageChunk
0xf3 9 9 ObjectAvailable
0xf4 17 17 ImageImuData
Connection Establishment¶
The engine sends a reset frame (0x01) to the robot with first_seq and seq set to 1 and ack set to 0.
The robot responds with a robot packets frame (0x09) with first_seq and seq set to 1 and ack set to 1, containing a connect packet (0x02). This establishes the connections.
The engine maintains the connection by periodically sending ping frames (0x0b). The robot responds with robot packet frames (0x09), containing a copy of the engine’s ping in a ping packet (0x0b). The pings have a sequence ID and a time stamp and allow the engine to measure round-trip time.
If the robot stops receiving ping frames for more than 5 s it will disconnect and display the message “COZMO 01”.
The engine can gracefully close the connection in one of two ways:
- by sending a disconnect frame (0x03)
- by sending an engine packets frame (0x07), containing a disconnect packet (0x03).
As long as a connection is established, the engine and the robot can exchange packets.
The engine sends packets in frames of types 0x04 and 0x07.
The robot sends packets in frames of type 0x09.
Capturing Cozmo Communication¶
Overview¶
Capturing the communication between the Cozmo app and Cozmo is very valuable for understanding how Cozmo works.
One way to achieve this is by placing a Linux machine between the two as shown on the following diagram.
+---------------+ Wi-Fi +---------------+ Wi-Fi +---------------+
| | | | | |
| Mobile Device | ---------------------> | Linux Machine | ---------------------> | Cozmo |
| | wlan1 | | wlan0 | |
+---------------+ +---------------+ +---------------+
The Linux machine acts as a Wi-Fi client on one interface (wlan0) and associates with Cozmo. It acts as a Wi-Fi access point (AP) on the other interface and allows a mobile device, running the Cozmo app to associate with it.
With appropriate network configuration such a setup allows capturing Cozmo communication in pcap files using tcpdump.
Prerequisites¶
- Cozmo robot
- Mobile device with the Cozmo app
- (Ubuntu) Linux machine with 2 Wi-Fi interfaces (e.g. a Raspberry Pi)
- The following tools installed:
Connecting to Cozmo¶
Ensure that wireless tools and wpa_supplicant are installed.
$ sudo apt-get install wireless-tools wpasupplicant
Wake up Cozmo but placing it on the charging platform.
Make Cozmo display it’s Wi-Fi PSK key by rising and lowering its lift.
Get Cozmo’s Wi-Fi SSID by scanning for Wi-Fi devices:
$ sudo iwlist wlan0 scan
wlan0 Scan completed :
Cell 01 - Address: 5E:CF:7F:XX:XX:XX
ESSID:"Cozmo_XXXXXX"
Protocol:IEEE 802.11bg
Mode:Master
Frequency:2.412 GHz (Channel 1)
Encryption key:on
Bit Rates:54 Mb/s
Extra:rsn_ie=30180100000fac020200000fac04000fac020100000fac020000
IE: IEEE 802.11i/WPA2 Version 1
Group Cipher : TKIP
Pairwise Ciphers (2) : CCMP TKIP
Authentication Suites (1) : PSK
Quality=100/100 Signal level=100/100
Open wpa_supplicant’s configuration file:
$ sudo vi /etc/wpa_supplicant/wpa_supplicant.conf
Configure wpa_supplicant to automatically connect to Cozmo by adding the following:
network={
ssid="Cozmo_XXXXXX"
psk="XXXXXXXXXXXX"
}
Load the new configuration (or reboot):
$ sudo wpa_cli -i wlan0 reconfigure
OK
At this point the Linux machine should be associated with Cozmo:
$ ip addr
...
3: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 80:1f:02:XX:XX:XX brd ff:ff:ff:ff:ff:ff
inet 172.31.1.172/24 brd 172.31.1.255 scope global wlan0
valid_lft forever preferred_lft forever
inet6 fe80::1d4b:9d3b:c6f0:f5b1/64 scope link
valid_lft forever preferred_lft forever
Cozmo should respond to ping:
$ ping 172.31.1.1
PING 172.31.1.1 (172.31.1.1) 56(84) bytes of data.
64 bytes from 172.31.1.1: icmp_seq=1 ttl=128 time=1.94 ms
64 bytes from 172.31.1.1: icmp_seq=2 ttl=128 time=2.28 ms
...
Masquerading as a Cozmo¶
Install hostapd and dnsmasq:
$ sudo apt-get install hostapd dnsmasq
Edit dhcpdcd`s configuration file:
$ sudo vi /etc/dhcpcd.conf
Disable wpa_supplicant on wlan1 and configure a static IP address by adding the following:
interface wlan1
nohook wpa_supplicant
static ip_address=192.168.50.1/24
Edit dnsmasq’s configuration file:
$ sudo vi /etc/dnsmasq.conf
Configure DHCP on wlan1 by adding the following:
interface=wlan1
dhcp-range=192.168.50.50,192.168.50.100,255.255.255.0,24h
Restart dnsmasq
$ sudo systemctl start dnsmasq
Create a configuration file for hostapd:
$ sudo vi /etc/hostapd/hostapd.conf
Configure a Wi-Fi AP with WPA2 PSK on wlan1 by adding the following:
interface=wlan1
hw_mode=g
channel=1
wmm_enabled=0
macaddr_acl=0
auth_algs=1
ignore_broadcast_ssid=0
wpa=2
wpa_key_mgmt=WPA-PSK
wpa_pairwise=TKIP
rsn_pairwise=CCMP
ssid=Cozmo_111111
wpa_passphrase=XXXXXXXXXXXX
The SSID should be different from Cozmo’s SSID and should follow the form Cozmo_XXXXXX
, where XXXXXX are
upper-case hexadecimal digits as this is what the Cozmo app looks for.
The passphrase should consist of exactly 12 upper-case hexadecimal digits as this is what the Cozmo app expects.
Edit /etc/default/hostapd
:
$ sudo vi /etc/default/hostapd
Configure the newly created configuration file:
DAEMON_CONF="/etc/hostapd/hostapd.conf"
Enable and start hostapd:
$ sudo systemctl unmask hostapd
$ sudo systemctl enable hostapd
$ sudo systemctl start hostapd
Ensure that IP forwarding is enabled on boot:
$ sudo vi /etc/sysctl.conf
The following line should be uncommented:
net.ipv4.ip_forward=1
Ensure that IP forwarding is enabled:
$ sudo sysctl net.ipv4.ip_forward=1
The Cozmo app always tries to communicate with Cozmo using the IP address 172.31.1.1 .
Configure masquerading on wlan0 so that packets, coming from the Cozmo app, with source IP in the range 192.168.50.0/24, reach Cozmo with the wlan0 IP address of the Linux machine.
$ sudo iptables -t nat -A POSTROUTING -o wlan0 -j MASQUERADE
This is necessary, because Cozmo only responds to UDP packets with source IP address in the range 172.31.1.0/24 .
Capturing Communication¶
Ensure that tcpdump is installed:
$ sudo apt-get install tcpdump
At this point, it should be possible to capture Cozmo communication using tcpdump:
$ sudo tcpdump -i wlan0 -w cozmo.pcap
Connect to cozmo from the app. The app should find at least 2 Cozmos (one being the masqueraded Linux machine) and a selection screen should show up.
The captured PCAP file can be analyzed with Wireshark or with
pycozmo_dump.py
.
Cozmo Functions¶
Overview¶
Cozmo is a complex distributed embedded system with the following main parts:
- robot
- cubes
- charging platform
The robot can be subdivided into:
- head
- Wi-Fi communication controller (Espressif ESP8266)
- Real-time and Image Processing (RTIP) controller (NXP Kinetis K02)
- body
- Body controller (Nordic nRF51822)
The Wi-Fi communication controller is responsible for the following functions:
- Wi-Fi communication
- over-the-air (OTA) firmware updates
- NV RAM storage
Once Cozmo is powered on, the communications controller remains always powered on to maintain Wi-Fi communication.
On connection, the robot transmits its serial number with the HardwareInfo
message and firmware version with the
FirmwareSignature
message.
The RTIP controller is responsible for:
- OLED display image decoding
- speaker audio decoding
- camera image encoding
- accelerometers
- gyro
The body controller is in charge of:
- left and right tread motors and encoders encoders
- head motor and encoder
- lift motor and encoder
- backpack LEDs
- backpack button (on newer models only)
- Bluetooth LE communication (to cubes and charging platform)
- IR LED
- cliff sensor
- batter charging
The body is powered on with the Enable
message. The BodyInfo
message communicates the body hardware version,
serial number, and color.
Cubes use Nordic nRF31512 MCU. They are communicated with over Bluetooth LE and provide access to:
- LEDs
- Accelerometers
- Battery voltage
Some charging platforms (aka “pads”) can be communicated with over Bluetooth LE. They contains 3 RGB LEDs that can be controlled, similar to cube LEDs.
The following sections provide more details on the use of each function.
Wi-Fi¶
Wi-Fi is activated automatically when the head board is powered on. The robot operates in access point (AP) mode.
cozmoclad
defines a SetBodyRadioMode
message that seems to allow changing the Wi-Fi channel but it is unclear
how it can be used with the Cozmo protocol.
WifiOff
Shutdown
Backpack LEDs¶
The 5 Backpack LEDs can be set controlled with 2 messages:
lightStateCenter
- controls the top, middle, and bottom RGB LEDs.LightStateSide
- controls the left and right red-only LEDs.
Each color is defined by a 5-bit value for a total of 32768 colors.
See examples/backpack_lights.py
for example usage.
Backpack Button¶
v1.5 and newer Cozmo models have a backpack button.
Button press and release events are communicated by the ButtonPressed
message. It is immediately available on
connection and does not require Enable
to be used.
The RobotState
message has a backpack_touch_sensor_raw
field but
it seems that it’s value does not change as a result of button presses.
See examples/events.py
for example usage.
Wheels¶
The left and the right motor speeds can be controlled directly using the DriveWheels
and TurnInPlaceAtSpeed
messages. The motors can be stopped using the StopAllMotors
message.
The actual speed of wheels is measured with Hall magnetic sensors. The values for each wheel can be
read through the lwheel_speed_mmps
and rwheel_speed_mmps
fields of the RobotState
message.
In addition, the and TurnInPlace
message can be used to turn to a specific angle.
Localization¶
The robot maintains a world frame internally. It’s position and orientation with respect to it are transmitted every
30 ms or about 33 times per second with the RobotState
message.
If the robot is unable to maintain correct position and orientation, for example because it is picked up or pushed, it
will communicate this with a RobotDelocalized
message.
The origin (0,0,0) of the world frame as well as “pose ID” can be set with the SetOrigin
message. This is usually done
on initial connection and and on receiving a RobotDelocalized
message.
The timestamp in RobotState
messages can be synchronized using the SyncTime
message.
Path Tracking¶
The robot can traverse paths, composed of lines, arcs, and turns in place, described in world frame coordinates. The
AppendPathSegLine
, AppendPathSegArc
, and AppendPathSegPointTurn
messages can be used to build paths.
The last composed path can be executed using the ExecutePath
message. One of it’s arguments can be used to request
the reception of PathFollowingEvent
message when path traversing finishes.
The status
filed of the RobotState
message has a robot_pathing
flag that indicates whether the robot is currently
traversing a path. The curr_path_segment
filed indicates which segment is being traversed.
The ClearPath
message can be used to destroy an already composed path. The TrimPath
message can be used to delete
path segments from the beginning or the end of a composed path.
See examples/path.py
and examples/go_to_pose.py
for example usage.
Head¶
The head motor can be controlled directly, using the DriveHead
and SetHeadAngle
messages. SetHeadAngle
is always
followed by an AcknowledgeAction
message before the head starts moving.
The actual head angle can be read through the head_angle_rad
field of the RobotState
message. The head_in_pos
flag
of the status
field indicates whether the head is in position or in motion.
The motor can be stopped using the StopAllMotors
message.
The robot measures the angle of the head, relative to its lowest possible position. This measurement is automatically
triggered on connection. The head can be forced to an unknown angle for example as a result of a fall.
In such situations, the robot recalibrates the head motor automatically. Calibration can also be triggered on request,
using the StartMotorCalibration
message. The MotorCalibration
message indicates whether calibration is in progress.
See examples/extremes.py
for example usage.
Lift¶
The head motor can be controlled directly, using the DriveLift
and SetLiftHeight
messages. SetLiftHeight
is always
followed by an AcknowledgeAction
message before the lift start moving.
The actual lift height can be read through the lift_height_mm
field of the RobotState
message. The lift_inpos
flag
of the status
field indicates whether the lift is in position or in motion.
The motor can be stopped using the StopAllMotors
message.
The robot measures the angle of the lift, relative to its lowest possible position. It is calibrated similar to the head motor.
See examples/extremes.py
for example usage.
OLED display¶
Images can be displayed on the robot’s OLED 128x64 display using the DisplayImage
message. To reduce display burn-in,
consecutive images are interleaved and only half of the display’s rows can be used at a time and the effective display
resolution is 128x32.
The Cozmo protocol uses a special run-length encoding to compress images.
Display and audio are synchronized by audio messages (OutputAudio
and OutputSilence
).
AnimationState
message which can be enabled using the EnableAnimationState
message provide statistics on display
usage.
See examples/display_image.py
and examples/display_lines.py
for example usage.
Speaker¶
The OutputAudio
message can be used to transmit 744 audio samples at a time.
The samples are 8-bit and u-law encoded.
Speaker volume can be adjusted with the SetRobotVolume
message.
AnimationState
message which can be enabled using the EnableAnimationState
message provide statistics on audio
usage.
See examples/audio.py
for example usage.
Camera¶
Cozmo can send a stream of camera images in 320x240 (QVGA) resolution at a rate of ~15 frames per second.
The EnableCamera
message enables camera image reception and the EnableColorImages
message allows switching between
grayscale and color images.
The camera gain, exposure time, and auto exposure can be controlled with the SetCameraParams
message.
Images are encoded in JPEG format and transmitted as a series of ImageChunk
messages. The header of the JPEG files is
not transmitted to save bandwidth.
The ImageImuData
message provides accelerometer readings at the time of capturing every image to allow for motion
blur compensation.
See examples/camera.py
for example usage.
IR LED¶
The IR LED (aka head light) can improve the camera performance in dark environments.
The IR LED can be turned on and off using the SetHeadLight
message.
Accelerometers¶
The RobotState
message communicates accelerometer readings which represent acceleration along the x, y, and z axes.
In addition, the robot automatically detects and communicates 2 types of events. The RobotPoked
message is sent if
the robot has been moved rapidly by an external force along the x or y axes. The FallingStarted
and FallingStopped
messages are send if the robot is moving rapidly along the z axis.
See examples/events.py
for example usage.
Gyro¶
The RobotState
message communicates gyro readings which represent angular velocity around the x, y, and z axes.
See examples/events.py
for example usage.
Cliff Sensor¶
The robot has a “cliff sensor” that measures the distance to ground below the robot. This allows detecting cliffs and detecting when the robot is being picked up or put down.
The RobotState
message communicates the raw cliff sensor readings.
In addition, the robot can be made to automatically stop when a cliff is detected with the EnableStopOnCliff
message.
See examples/events.py
for example usage.
Battery voltage¶
The RobotState
message communicates raw battery voltage readings.
NV RAM Storage¶
The robot provides access to some amount of non-volatile memory (aka NV RAM) intended to store two main types of data:
- unit-specific parameters (ex. camera calibration data and cube IDs)
- mobile app data (ex. sparks and unlocked games and tricks)
The NV RAM storage is backed by the head’s ESP8266 controller external SPI flash. It is a NOR flash which drives the following specifics for its use:
- an erase operation is needed before a write operation
- data is erased in pages
The NvStorageOp
message allows performing read, erase, and write operations. Data is addressed by the tag
field and
only the values enumerated by NvEntryTag
can be used. Using any other address results in a NV_BAD_ARGS
. Tags
smaller than 0x80000000 are direct NOT flash memory addresses. Tags larger than 0x80000000 are virtual addresses that
seem to be stored in the NVEntry_FactoryBaseTagWithBCOffset
area.
NvStorageOpResult
messages communicate results of NvStorageOp
operations.
A backup through the mobile app, preserves the data behind the following keys:
- NVEntry_GameSkillLevels
- NVEntry_Onboarding
- NVEntry_GameUnlocks
- NVEntry_FaceEnrollData
- NVEntry_FaceAlbumData
- NVEntry_NurtureGameData
- NVEntry_InventoryData
- NVEntry_LabAssignments
See examples/nvram.py
for example usage.
Firmware Updates¶
Cozmo firmware updates are distributed in “cozmo.safe” files that seem to contain firmware images for all three of Cozmos controllers - the Wi-Fi communication controller, the RTIP controller, and the body controller.
The “cozmo.safe” files start with a firmware signature in JSON format:
{
"version": 2381,
"git-rev": "408d28a7f6e68cbb5b29c1dcd8c8db2b38f9c8ce",
"date": "Tue Jan 8 10:27:05 2019",
"time": 1546972025,
"messageEngineToRobotHash": "9e4a965ace4e09d86997b87ba14235d5",
"messageRobotToEngineHash": "a259247f16231db440957215baba12ab",
"build": "DEVELOPMENT",
"wifiSig": "69ca03352e42143d340f0f7fac02ed8ff96ef10b",
"rtipSig": "36574986d76144a70e9252ab633be4617a4bc661",
"bodySig": "695b59eff43664acd1a5a956d08c682b3f8bd2c8"
}
This is the same signature, delivered with the FirmwareSignature
message on initial connection establishment.
See docs/versions.md
for more examples.
There seem to be individual signatures for each controller but the structure of the cozmo.safe
files is not known.
The firmware image is transferred as-is from the engine to the robot, using FirmwareUpdate
messages. It is divided
into 1024 B chunks that are numbered consecutively, starting with 0. Each chunk is confirmed by the robot with a
FirmwareUpdateResult
message with status
field set to 0.
Firmware transfer completion is indicated by the engine with e FirmwareUpdate
message with chunk ID set to 0xFFFF and
data set to all-zeros. The robot confirms firmware update completion by sending a FirmwareUpdateResult
message that
repeats the last chunk ID and has a status
field set to 10.
Bluetooth LE¶
“Objects”, that can be connected to over Bluetooth LE announce their availability with an ObjectAvailable
message
periodically. The ObjectAvailable
message contains the object type (e.g. light cube 1, 2, 3 or charging pad) and
the object factory ID which identifies it uniquely.
The ObjectConnect
message is used to initiate or terminate a connection to objects, using their factory ID.
Connection establishment and termination is announced with the ObjectConnectionState
message. It contains a temporary
“object ID” that is used to identify the object for the duration of the connection with it.
Cube LEDs¶
Cubes have 4 RGB LEDs that can be controlled individually.
A cube has to be “selected” first, using the CubeId
message. A subsequent CubeLights
message sets the state of all
4 cube LEDs.
Cubes can be programmed to perform simple LED light animations autonomously using the LightState
structure and the
CubeId.rotation_period_frames
field.
See examples/cube_lights.py
and examples/cube_light_animation.py
for example usage.
Cube Battery Voltage¶
Cube battery voltage is communicated periodically with ObjectPowerLevel
messages.
Cube Accelerometers¶
Cube accelerometer value reception can be enabled with the StreamObjectAccel
message and are communicated every 30 ms
with the ObjectAccel
message.
In addition, the robot performs basic cube accelerometer ata processing and provides basic events with the following messages:
ObjectMoved
ObjectStoppedMoving
ObjectUpAxisChnaged
ObjectTapped
ObjectTapFiltered
Animations¶
To play animations, AnimationState
message have to be enabled first using the EnableAnimationState
message.
Animations are controlled with the StartAnimation
, EndAnimation
, and AbortAnimation
messages.
Keyframes are transferred with the AnimHead
, AnimLift
, AnimBody
, AnimBackpackLights
, RecordHeading
,
TurnToRecordedHeading
, and OutputAudio
messages.
See examples/anim.py
for example usage.
Cozmo Off-Board Functions¶
Cozmo mobile application resources consist of:
- audio files
- animations
- animation group descriptions
- behaviors
- reaction triggers
- emotions
- activities
- text-to-speech models
Robot firmware images are also distributed as part of the app resources.
Directory structure¶
cozmo_resources/
assets/
animationGroupMaps/
animationGroups/
animations/
cubeAnimationGroupMaps/
faceAnimations/
RewardedActions/
config/
engine/
animations/
behaviorSystem/
activities/
behaviors/
emotionevents/
firmware/
lights/
backpackLights/
cubeLights/
sound/
English(US)
tts/
Animations¶
Cozmo “animations” allow animating the following aspects of the robot:
- body movement
- lift movement
- head movement
- face images
- backpack LED animations
- audio
Cozmo animations are series of keyframes, stored in binary files in FlatBuffers
format. Animation data structures are declared in FlatBuffers format in
files/cozmo/cozmo_resources/config/cozmo_anim.fbs
. The animation files are available in the following directory of
the Android mobile application:
files/cozmo/cozmo_resources/assets/animations
Face images are generated procedurally. They are described by 43 parameters - 5 for the face and 19 for each eye. The face as a whole can be translated, scaled, and rotated. Each individual eye can be translated, scaled, and rotated. The 4 corners of each eye can be controlled and each eye has a lower and upper lid.
The following presentation from Anki provides some background information on Cozmo animations:
Animation groups¶
Animation groups are sets of animations with the same purpose.
Behaviors¶
Behaviors can be thought of as small applications that perform a specific function using the robot client API.
Reactions¶
Reactions map robot events to behaviors.
Emotions¶
Emotions are modeled as value functions that change in one of the following ways:
- over time, driven by a decay function
- as a result of reactions
- as a result of behaviors
Activities¶
Activities are sets of behaviors with a rule how to choose
Cozmo Firmware Versions¶
Cozmo firmware images can be found under com.anki.cozmo/files/cozmo/cozmo_resources/config/engine/firmware
in the
Cozmo app.
Production Versions¶
{
"version": 2381,
"git-rev": "408d28a7f6e68cbb5b29c1dcd8c8db2b38f9c8ce",
"date": "Tue Jan 8 10:27:05 2019",
"time": 1546972025,
"messageEngineToRobotHash": "9e4a965ace4e09d86997b87ba14235d5",
"messageRobotToEngineHash": "a259247f16231db440957215baba12ab",
"build": "DEVELOPMENT",
"wifiSig": "69ca03352e42143d340f0f7fac02ed8ff96ef10b",
"rtipSig": "36574986d76144a70e9252ab633be4617a4bc661",
"bodySig": "695b59eff43664acd1a5a956d08c682b3f8bd2c8"
}
{
"version": 2380,
"git-rev": "6ef227df0d64427f95cb943e01d8ac3956646e4d",
"date": "Thu Dec 20 17:33:45 2018",
"time": 1545356025,
"messageEngineToRobotHash": "3aed3b94dbf19e11b2775ff980874213",
"messageRobotToEngineHash": "c5a95cb6f44c1b89a42784d0c637fda8",
"build": "DEVELOPMENT",
"wifiSig": "8694122d7de45ee085c488274d28b69b7b1f2f44",
"rtipSig": "8acba259c7b440dc0a3467ae73f262a224f036db",
"bodySig": "14d4420c42432211ae4cda4f78a41841b03a6b40"
}
{
"version": 2315,
"git-rev": "d96caf034da1c4a33d70d2c1e3bc5732ec68594a",
"date": "Thu Nov 9 15:37:45 2017",
"time": 1510270665,
"messageEngineToRobotHash": "5d963ecd52d4ae18af796f14f02a3f60",
"messageRobotToEngineHash": "d07d1f4dea884725adefd33de221a49f",
"build": "DEVELOPMENT",
"wifiSig": "2749d9fb97a138aa7b56429c3a587baf6dadfb6f",
"rtipSig": "0605ff5cd1f37cf75573caac3678ecba12b9bebe",
"bodySig": "76dc76aa624fac230603101206d3a4e2e50e76cb"
}
{
"version": 2313,
"git-rev": "7381fe56705992ffd03bef1bb1a7b2e7258e9bc2",
"date": "Tue Nov 7 21:13:04 2017",
"time": 1510117984,
"messageEngineToRobotHash": "838bbe94628fd10783e40f6b6b9874df",
"messageRobotToEngineHash": "6ae9b7733e469f4fef89479d63e214ba",
"build": "DEVELOPMENT",
"wifiSig": "5bfbabc73e0ec5e20a072b6ab87b60da8a51310a",
"rtipSig": "349d2224cc00e56ee50a5b4ecb905a5ba64c791d",
"bodySig": "5ac6821655294e88b5fb852427bd99120af16fb5"
}
{
"version": 2214,
"git-rev": "c363ccc897bc3748d234f80c21e4c8a33757d063",
"date": "Wed Aug 9 11:01:32 2017",
"time": 1502301692,
"messageEngineToRobotHash": "861bbc71828456c0f073c4464bdcb21e",
"messageRobotToEngineHash": "2dc8419f768f6f3fd4843cbb0a86f7f7",
"build": "DEVELOPMENT",
"wifiSig": "da7eb444c13475eb67b0c13336b24021b8cf540f",
"rtipSig": "4cba42517073e77967ce8c7340376713001b4d0a",
"bodySig": "74a1776d1c6a4213ccfbb0ad2c4099eafdf7ad0c"
}
{
"version": 2158,
"git-rev": "44c8d8a1d3a2b09b54da0ff4b6ceee75ec66e267",
"date": "Thu Jun 15 10:00:23 2017",
"time": 1497546023,
"messageEngineToRobotHash": "71beec8d11144f3a3718d2cc5ea602f3",
"messageRobotToEngineHash": "4018b2e764ec08f5fcacdb6358847cb0",
"build": "DEVELOPMENT",
"wifiSig": "e3f4a7e29b76321e3563f50e0b09c89378b5dc97",
"rtipSig": "64efe94218e8eaac3576f2405bc5f01f020b0b7a",
"bodySig": "d0c34ed006c71abe45ac735e4bb68bf1153b082b"
}
{
"version": 1889,
"git-rev": "e541e4247376d7945fd42a82a826b443effbeff2",
"date": "Thu Mar 23 17:15:50 2017",
"time": 1490314550,
"messageEngineToRobotHash": "7098b4a266c0ccc2102a61fda53b8999",
"messageRobotToEngineHash": "9b83f21da9120fdeebfeabe84af81c32",
"build": "DEVELOPMENT",
"wifiSig": "266d1d4f91c5ee069e628550a0331e8b0eb90f2b",
"rtipSig": "bc90e2949be66851fb7ac035f5de9b52ff69fd14",
"bodySig": "ccbb209db374f21ef233945f1515a70b8fe43114"
}
{
"version": 1859,
"git-rev": "11a52d6a4f2c5d89cef7085b836e8d0f2525808b",
"date": "Mon Mar 20 23:29:56 2017",
"time": 1490077796,
"messageEngineToRobotHash": "54195812be0de998a4ebde795364d62b",
"messageRobotToEngineHash": "90d8f3273055624b8444fbcbef555ee8",
"build": "DEVELOPMENT",
"wifiSig": "79dca08e85f21311e5551e38ecf0d3dab6ce006f",
"rtipSig": "72519cd2bfb11bc799915dd8506a67b0ae5186da",
"bodySig": "8746362ebc89e6235e3da103b9e9c0133cc3d1c1"
}
{
"version": 1299,
"git-rev": "6ced81297ac14067662acbed79cecac7f5eacd28",
"date": "Mon Nov 21 15:25:58 2016",
"time": 1479770758,
"messageEngineToRobotHash": "61879d8808f0308cd8ae6340ddfe06e6",
"messageRobotToEngineHash": "5914fda0b97c7aadaf0e4d97fc72610f",
"wifiSig": "6cd4d9263e7a5b5da9eedc33e32c8baeb04a0ea6",
"rtipSig": "24591dd715955eef0c1c7f0d89b4b41c122cbb26",
"bodySig": "412ce6fc22f7407cb2e87eaacee3e9c4d7ca47ea"
}
Factory Versions¶
Cozmo factory firmwares identify with large version numbers.
Seen on Cozmo with HW v1.5:
{
"build": "FACTORY",
"version": 10501,
"date": "Fri Apr 14 20:28:21 2017",
"time": 1492201868
}
{
"build": "FACTORY",
"version": 10502,
"date": "Mon Aug 7 09:21:24 2017",
"time": 1502122884
}
Seen on development Cozmo with HW v1.7:
{
"build": "FACTORY",
"version": 10700,
"date": "Thu Mar 28 14:18:13 2019",
"time": 1553807893
}
Cozmo Hardware Versions¶
Hardware Version 4¶
- fall 2016
- does not have a button
- come with platforms with LEDs?
2020-09-23 19:12:56.567 pycozmo.general INFO Firmware version 2381.
2020-09-23 19:12:56.568 pycozmo.robot INFO hardware.revision: Hardware 1.0
2020-09-23 19:12:56.598 pycozmo.general INFO Body S/N 0x088xxxxx, HW version 4, color 0.
Hardware Version 5¶
- fall 2017
- has an off button (EU Certification)
- observed to have factory firmware v10501
- teardown - https://www.microcontrollertips.com/teardown-anki-cozmo-vector/
2020-09-26 12:31:32.421 pycozmo.general INFO Firmware version 2381.
2020-09-26 12:31:32.422 pycozmo.robot INFO hardware.revision: Hardware 1.5
2020-09-26 12:31:32.453 pycozmo.general INFO Body S/N 0x088xxxxx, HW version 5, color 3.
Hardware Version 6¶
- fall 2018
- has an off button (Japan certification)
Hardware Version 7¶
- fall 2019
- has an on/off button
- observed with development units
- observed to have factory firmware v10700
- observed to report undocumented color “5”
2020-09-24 20:04:35.823 pycozmo.general INFO Firmware version 10700.
2020-09-24 20:04:35.831 pycozmo.robot INFO hardware.revision: Hardware 1.7
2020-09-24 20:04:35.856 pycozmo.general INFO Body S/N 0x088xxxxx, HW version 7, color 5.
ESP8266¶
The ESP8266 is the main Cozmo controller, responsible for Wi-Fi communication.
SPI Flash Memory Map¶
The SPI flash size is 2 MB.
The below memory map has been reconstructed based on a SPI flash memory dump and NvEntryTag
values.
Offset Length Type Description
---------------------------------------------------------------------------------
0x00000000 0x00001000 Code Bootloader.
0x00001000 0x00001000 Data Unknown. The first 4 bytes are the head serial number.
0x00002000 0x00001000 Data Unknown.
0x00003000 0x0007b800 Code Application image 1.
0x0007e800 0x00001800 Data Application image 1 signature. See versions.md .
0x00080000 0x0005e000 Code Recovery image / factory firmware.
0x000de000 0x00000030 Data Birth certificate.
0x000de030 0x00021fd0 Data Factory data.
0x00100000 0x00003000 Data Unknown.
0x00103000 0x0007b800 Code Application image 2
0x0017e800 0x00001800 Data Application image 2 signature. See versions.md .
0x00180000 0x00018000 Data Application data.
0x00198000 0x00028000 Data Empty.
0x001c0000 0x0001e000 Data Factory reserved 1.
0x001de000 0x0001e000 Data Factory reserved 2. Empty?
0x001fc000 0x00001000 Data Unknown.
0x001fd000 0x00001000 Data Wi-Fi configuration 1.
0x001fe000 0x00001000 Data Wi-Fi configuration 2.
0x001ff000 0x00001000 Data Unknown.
pycozmo package¶
pycozmo.audiokinetic.exception |
AudioKinetic WWise exceptions. |
pycozmo.audiokinetic.soundbank |
AudioKinetic WWise SoundBank representation and reading. |
pycozmo.audiokinetic.soundbanksinfo |
AudioKinetic WWise SoundbanksInfo.xml representation and reading. |
pycozmo.audiokinetic.wem |
AudioKinetic WWise WEM file representation and reading. |
pycozmo.expressions.expressions |
Facial expression definitions. |
pycozmo.activity |
Activity representation and reading. |
pycozmo.anim |
Animation clip representation, reading, and preprocessing. |
pycozmo.anim_controller |
Animation controller for audio, image, and animation playback. |
pycozmo.anim_encoder |
Reading and writing of Cozmo animations in FlatBuffers (.bin) and JSON format. |
pycozmo.audio |
Cozmo audio encoding. |
pycozmo.behavior |
Behavior representation and reading. |
pycozmo.brain |
Brain class - high level behavior and emotion engine. |
pycozmo.camera |
Camera image decoding. |
pycozmo.client |
Cozmo protocol client and high-level API. |
pycozmo.conn |
Cozmo protocol low-level client and server connection. |
pycozmo.emotions |
Emotion representation and reading. |
pycozmo.event |
Event declaration and dispatching. |
pycozmo.exception |
Exception declarations. |
pycozmo.filter |
ID filtering for logging. |
pycozmo.frame |
Cozmo protocol frame representation and encoding and decoding. |
pycozmo.image_encoder |
Cozmo image run-length encoding and decoding. |
pycozmo.lights |
Helper routines for working with colors and lights. |
pycozmo.logging |
|
pycozmo.object |
Cozmo objects (cubes, platforms, etc.). |
pycozmo.procedural_face |
Cozmo procedural face rendering. |
pycozmo.protocol_ast |
Cozmo protocol abstract syntax tree (AST) types. |
pycozmo.protocol_base |
Cozmo protocol implementation base. |
pycozmo.protocol_declaration |
Cozmo protocol abstract syntax tree (AST) declaration. |
pycozmo.protocol_encoder |
Cozmo protocol packet encoder classes, based on protocol version 2381. |
pycozmo.protocol_generator |
Cozmo protocol packet encoder code generator. |
pycozmo.protocol_utils |
Cozmo protocol encoding helper classes and functions. |
pycozmo.robot |
Robot constants and helper code. |
pycozmo.robot_debug |
Cozmo firmware debug message decoding. |
pycozmo.run |
Helper functions for running PyCozmo applications. |
pycozmo.util |
Utility classes and functions. |
pycozmo.window |
Cozmo protocol sliding window implementation. |