Multi-robot Programmatic Access
Scripts to iterate through robots and iteratively activate or control them
Using the Freedom REST API, it is exceedingly simple for you to programmatically control large numbers of robots remotely.
Set up your Credentials
You will want to save API credentials to ~/.config/freedomrobotics/credentials
with a payload of:
{
"token":"T000000000000",
"secret":"S00000000000
}
You can create a new token in the freedom App by going to
TEAM SETTINGS -> TOKENS -> CUSTOM then CREATE API TOKEN.
Create API Token: API Secret
You can only ever get your secret the first time, so please save it.
List all your Devices
Below, in a few lines, you can easily list all devices in your account. The examples below it show how to filter these devices by fleet, physical type, activity and other dimensions and then how to send commands back to them.
Each device has a JSON representation. A few of the keys you should know are:
account
- the account the device is indevice
- the freedom ID of the devicename
- the human readable name of the device you have given itfleet
- the logical grouping the device belongs totype
- the physical type of device, such as "spot-mini 1.0"- utc_last_received.data - the utc time in seconds when data was last received from the robot
import json
import requests
headers = {
'content-type': 'application/json',
'mc_token': credentials['token'],
'mc_secret': credentials['secret']
}
url = "https://api.freedomrobotics.ai/accounts/" + account + "/devices"
response = requests.get(url, headers=headers)
devices = json.loads(response)
for device in devices:
print(device)
By Activity
# Time is stored in UTC seconds since 1970
# NOTE: JS uses msecs, so divide by 1000
current_time = time.time()
LAST_ACTIVE_TIME_ATT = "utc_last_received.data"
active_devices = []
inactive_devices = []
for device in devices:
# Define active as a device which has uploaded data in the last minute
if LAST_ACTIVE_TIME_ATT not in device or current_time - device[LAST_ACTIVE_TIME_ATT] > 60:
inactive_devices.append(device)
else:
active_devices.append(device)
print("You have " + str(len(active_devices)) + " active devices and " +
str(len(inactive_devices)) + " inactive devices.")
By Alerts
You can search for devices with alerts and filter based on a specific type or level of alert.
for device in devices:
# If there are any triggered alerts
if len(device['mc.alerts.triggered']) > 0:
for alert in device['mc.alerts.triggered']:
if alert['level'] in ['error', 'fatal']:
print(device['name'] + " has an issue you should look at...")
By Fleet
You can easily segment so you are only interacting with devices from a specific fleet to update just the ones you want.
fleets = {}
for device in devices:
if device['fleet'] not in fleets:
fleets[device['fleet']] = []
fleets[device['fleet']].append(device)
By Type
Each robot has a physical type which represents the underlying hardware and version, such as "Spot-Mini 1.0".
types = {}
for device in devices:
if device['type'] not in types:
types[device['type']] = []
types[device['type']].append(device)
Send a Command to all Devices
Below shows you how to easily send a command in to all your devices. You can easily augment this to only send it to devices which are online, in a specific fleet or of a specific type.
import json
import requests
def send_data( headers, account, device, topic, topic_type, data):
payload = [{
'message': data,
'platform': 'ros',
'topic': topic,
'type': topic_type,
'expiration_secs': 5
}]
url = "https://api.freedomrobotics.ai/accounts/" +
account + "/devices/" + device +"/commands"
r = requests.put(url, headers=headers, data=json.dumps(payload))
for device in devices:
# Only update a specific fleet
if device["fleet"] is "california_04:
send_data(headers,
device["account"],device["device"],
"/commands",
"std_msgs/String",
{"data":"return_to_dock"}
)
Trigger a Script on all Devices
You can also trigger scripts locally on a subset of your robots for deploy, update and validation of data - or just to reset your usb bus if there is an issue.
import json
import requests
def trigger_script( headers, account, device, package, script_path, args):
payload = [{
'data': {
'package': package,
'script_path': script_path,
'args': args
},
'platform': 'mission_control_controller',
'command': 'local_script',
'expiration_secs':100
}]
url = "https://api.freedomrobotics.ai/proto/accounts/" +
account + "/devices/" + device +"/commands"
r = requests.put(url, headers=headers, data=json.dumps(payload))
for device in devices:
# Only update a specific fleet
if device["fleet"] is "california_04:
# remote trigger the script
trigger_script(headers,
device["account"], device["device"],
"acme_robotics",
"scripts/update_firmware_stack.sh",
" --now"
)
Updated about 3 years ago