Skip to main content

Cyberwave is in Private Beta.

Request early access to get access to the Cyberwave dashboard.

twin.get_frame() is the single entry point for still images. It has two independent parameters:
  • source=where the pixels are produced (default "cloud").
  • format=how you want them back: "bytes", "numpy", "pil", or "path" (write a JPEG and return the file path). Default: "bytes".
For continuous WebRTC video and audio streaming, see Streaming.

Runtime mode — cw.affect() (cloud only)

Sim vs. live is not a source= option. Set it once on the client with cw.affect() and it applies to twin.get_frame() as well as other twin getters/setters. By default the runtime mode is live.
cw.affect(...)What robot.get_frame() sees (source="cloud")
"simulation"Latest frame from the simulator bucket (virtual camera in the scene).
"live"Latest frame from the live / teleoperation bucket (edge or active stream mirrored to the platform).
cw.affect("simulation")
sim_jpeg = robot.get_frame()    # sim latest-frame — no edge hardware required

cw.affect("live")
live_jpeg = robot.get_frame()   # live latest-frame — what the UI / teleop path sees
When the client is in simulation runtime mode, only source="cloud" is allowed. local, zenoh, and remote_edge raise — those transports are for on-machine / edge workflows, not the sim-first client default.

Frame sources — source=

Pick the transport that matches where your script runs relative to the camera.
Works from anywhere with API access — notebooks, Colab, CI. Calls the platform /latest-frame API. No local driver, Zenoh, or stream required.Fail-soft: returns None if the endpoint has no frame yet. Sim vs. live bucket is determined by cw.affect().
jpeg  = robot.get_frame()                                   # bytes from latest-frame
arr   = robot.get_frame("numpy")                            # decoded array
wrist = robot.get_frame("numpy", sensor_id="wrist_cam")     # multi-camera twins

Quick reference

sourceRuns fromNeeds
cloudAnywhere with API keyTwin has a latest-frame; cw.affect() for sim vs live
remote_edgeAnywhere with MQTT to twinDriver supports take_photo
localSame process as start_streaming()Active CameraStreamer, or local OpenCV device
zenohSame host / Zenoh LAN as driverDriver publishing cw.data frames

Output format and bursts

path = robot.get_frame("path")                                  # temp JPEG on disk
path = robot.get_frame("path", path="/tmp/frame.jpg", source="local")

folder = robot.get_frames(5, interval_ms=200)                   # numbered JPEGs in a temp dir
frames = robot.get_frames(5, format="bytes")                    # list of raw JPEG bytes
twin.get_latest_frame() remains for backward compatibility (raises on error). Deprecated aliases on twin.camera (latest_frame, capture, read, snapshot, edge_photo, …) and the older capture_frame helper delegate to get_frame with a DeprecationWarning. New code should use get_frame.

Camera & sensor discovery

Discover the CV2 (standard webcam) devices attached to your machine:
from cyberwave.sensor import CV2VideoTrack, CV2CameraStreamer, CameraConfig, Resolution

# Supported resolutions for a camera
supported = CV2VideoTrack.get_supported_resolutions(camera_id=0)
print(f"Supported: {[str(r) for r in supported]}")

# Camera info
info = CV2VideoTrack.get_camera_info(camera_id=0)

# Build a streamer from a config
config = CameraConfig(resolution=Resolution.HD, fps=30, camera_id=0)
streamer = CV2CameraStreamer.from_config(cw.mqtt, config, twin_uuid="...")

RealSense (RGB + Depth)

from cyberwave.sensor import RealSenseDiscovery, RealSenseConfig, RealSenseStreamer, Resolution

if RealSenseDiscovery.is_available():
    devices = RealSenseDiscovery.list_devices()
    for dev in devices:
        print(f"{dev.name} (SN: {dev.serial_number})")

    info = RealSenseDiscovery.get_device_info()
    print(f"Color resolutions: {info.get_color_resolutions()}")
    print(f"Depth resolutions: {info.get_depth_resolutions()}")

# Auto-detect and create a streamer from device capabilities
streamer = RealSenseStreamer.from_device(
    cw.mqtt,
    prefer_resolution=Resolution.HD,
    prefer_fps=30,
    enable_depth=True,
    twin_uuid="your_twin_uuid",
)

# Or use a validated manual configuration
config = RealSenseConfig(
    color_resolution=Resolution.HD,
    depth_resolution=Resolution.VGA,
    color_fps=30,
    depth_fps=15,
    enable_depth=True,
)
is_valid, errors = config.validate()
streamer = RealSenseStreamer.from_config(cw.mqtt, config, twin_uuid="...")
Raspberry Pi / ARM64: pip install cyberwave[realsense] installs the Python wrapper, but you must also have the librealsense SDK. On Raspberry Pi OS (ARM64) there are no pre-built packages — build from source per the Raspberry Pi setup guide.

Camera Features

Supported camera types and how cameras integrate with workflows.