This release has been yanked by its maintainers, and will be ignored by installers, except when explicitly specified.
Consider using release 0.0.1a7 instead.
bsln
Python SDK and command line for Baseline Robotics robot stations. Drive a real robot station from your own machine: stream joint targets from your script, get a report of each session and download the recordings.
This package contains only the client. It does not contain the server, the station agent or robot code.
This page shows how to control a Baseline Robotics robot station from your computer with Python.
You install the bsln client, connect with your token, and run a short script on a bimanual YAM station.
The script turns one wrist joint by 0.1 rad (about 6 degrees) and then turns it back.
1. Install
You need Python 3.10 or newer. We recommend a virtual environment.
python3 -m venv .venv
source .venv/bin/activate
pip install bsln
2. Get access
Baseline Robotics gives you a bsln token. The token starts with bsln_.
Keep the token secret. Do not put it in your code or in a Git repository.
Use one of these two methods to connect.
Method A: log in once. The command asks for your token.
It saves the URL and the token in ~/.config/bsln/config.json. Only your user can read this file.
bsln login --url https://api.baseline-robotics.com
Method B: environment variables. Set them in each terminal.
export BSLN_URL=https://api.baseline-robotics.com
export BSLN_TOKEN=<your token>
Make sure that the connection works. The command shows your user name and your scopes.
bsln whoami
Extra tokens. You can make more tokens for other computers or scripts. This command makes a token for 30 days and shows it one time. Keep it safe.
python -c "from bsln.sdk import Client; print(Client().create_token(['read', 'write', 'control'], name='second-computer', ttl_days=30)['token'])"
An extra token cannot have more scopes than your token. It expires before your token or at the same time. To stop a token before it expires, contact Baseline Robotics.
3. Find a station
bsln stations
The list shows each station and its status. You can start a session only on a station with the status idle.
The other values are busy (another session is active), fault (the station is stopped) and offline.
4. Run your first session
Save this script as quickstart.py.
"""bsln quickstart: start a session, turn the left wrist a little, stream targets, end the session.
export BSLN_URL=https://api.baseline-robotics.com BSLN_TOKEN=<your bsln token>
python quickstart.py <station id>
"""
import sys
import time
from bsln.sdk import Client
STATION = sys.argv[1]
WRIST = "left_joint6" # the left wrist; units: rad
TURN = 0.1 # rad (about 6 degrees)
client = Client() # uses BSLN_URL and BSLN_TOKEN, or the values from `bsln login`
station = client.station_description(STATION)
print("joints:", station["joint_order"])
print("control rate:", station["control_hz"], "Hz")
high = next(joint["safe_range"][1] for joint in station["joints"] if joint["name"] == WRIST) # in rad
with client.start_session(STATION) as session:
print("session:", session.id)
start = session.get_state()["target"][WRIST] # where the station holds the wrist now
turn = TURN if start + TURN <= high else -TURN # stay in the safe range
# 1. Send one target. The station keeps it. The safety supervisor limits the speed.
session.set_joints({WRIST: start + turn})
time.sleep(2.0)
# 2. Stream targets at the control rate for 3 s. The wrist goes back to its start position in 2 s.
# A streamed target expires after 0.25 s. Then the arm holds its position.
period = 1.0 / station["control_hz"]
begin = time.monotonic()
while (elapsed := time.monotonic() - begin) < 3.0:
done = min(1.0, elapsed / 2.0) # 0 at the start, 1 after 2 s
session.send_targets({WRIST: start + turn * (1.0 - done)})
time.sleep(period)
print("wrist now:", round(session.get_joints()[WRIST], 3), "rad")
usage = session.end() # stop the session. The arms hold their position.
print("usage:", usage)
print("report: bsln session report", session.id)
Run the script. Replace <station id> with an id from bsln stations.
python quickstart.py <station id>
The script does these steps:
- It reads the station description: the joint names, the units, the safe range of each joint and the control rate.
- It starts a session. Only you can control the station during your session.
- It sends one target with
set_joints. The station keeps this target until you send a new one. - It streams targets with
send_targetsfor 3 s. A streamed target expires after 0.25 s. - It ends the session. The arms hold their position.
The script prints the session ID. You need it for the report and for the data.
5. Stop
To stop a session, end it in your script with session.end(). You can also use this command:
bsln session stop <session id>
To find the ID of a session, use this command:
bsln session ls
If your script stops or loses the connection, the arms hold their position. If your script does not connect again in 30 s, bsln ends the session.
6. Emergency stop (e-stop)
Use the e-stop when the robot does something that you do not expect. You can send it at any time.
In your script, use session.estop(). From a terminal, use one of these commands:
bsln estop <station id>
bsln session estop <session id>
After an e-stop:
- The arms stop and hold their position. The motors stay on.
- Your session ends.
- The station gets the status
fault. You cannot start a new session on it. - Only Baseline Robotics can clear the fault. Contact us (see section 9).
7. Get the session report and your data
The report is ready after the session ends. It shows the commands that you sent, the holds, the safety adjustments, the faults, the e-stops and the connection quality.
bsln session report <session id>
This command downloads the recorded data to the folder ./data. The data includes the report as report.json.
bsln session download <session id> --out ./data
8. Limits
| Item | Value |
|---|---|
| Joints | 14: left_joint1 to left_joint6, left_gripper, right_joint1 to right_joint6, right_gripper |
| Units | Arm joints: rad. Do not send degrees. Grippers: 0 (closed) to 1 (open). |
| Control rate | 30 Hz. Send one command for each control step. |
| Messages | 60 messages per second at most. bsln drops more messages and sends you a notice. |
| Deadman | 0.25 s. If no streamed command arrives in this time, the arm holds its position. |
| Safety supervisor | It moves each target into the safe range and limits its speed. It never makes a target larger or faster. |
| Session start | Joints 2 and 3 and the grippers can move a little into the safe range: 0.02 rad or 3 % at most. |
| Faults | A fault stops the station. It stays stopped until Baseline Robotics clears the fault. |
| E-stop | Always permitted. |
The station description (client.station_description(station_id)) gives the exact values for each station.
9. Get help
Contact Baseline Robotics. Tell us:
- the station ID and the session ID,
- the time of the problem (with your time zone),
- the full error message.
Each error message from bsln includes a request ID, for example error 404: session not found (request ID 3f2a...).
Include this request ID. With it, we can find your request in our logs.
Copyright 2026 Baseline Robotics AG. License: Apache-2.0 (see LICENSE and NOTICE).
Metadata
Release files for bsln 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| bsln-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Release files / bsln-0.1.1-py3-none-any.whl
| Download URL | bsln-0.1.1-py3-none-any.whl |
|---|---|
| Size | 39.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
f8a55394e843ed88d1396d5f6d4376e2296bcaee53be4a7bf8e1e8dae6891730
|
|
BLAKE2b-256 checksum How to use checksums |
06e9dc2b98cb339c630e8e376e26258ffcbc46930c7e16a408b3cb5f01036c21
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.15
|
Security for bsln 0.1.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.