Is Luos for me? 🤔

/ JSON API

The JSON formatted data is common and widely used by many programming languages. Luos allows you to convert low-level Luos information into JSON objects, enabling conventional programming languages to interact with your device easily.

To do that, you must add a specific app service called a gate on your device.

How to start using the JSON API

Before using your device through JSON, you have to be connected to the communication flow depending on the node type hosting your gate service.

Then you can start the gate by sending:

{"detection": {}}\r

This command asks the gate to start a topological detection, create a routing table, convert it into JSON and send it back to you.

Routing table messages

Warning: Make sure to read and understand how the routing table works before reading this part.

After the gate starts, the first message you receive is a routing table.

This first message is essential because it contains all the information allowing you to create a code object for your device, including all its features.

Routing table structure

A routing table in JSON consists of a list of the nodes present in the Luos network:

{
   "routing_table":[
      {
         // node 1
      },
      {
         // node 2
      },
      {
         // node 3
      }
      // ...
   ]
}

Nodes information

Each listed node of the network has basic node information and a list of hosted services:

{ // node 1
   "node_id":1,
   "certified":true,
   "port_table":[1, 2],
   "services":[
      {
         // service 1
      },
      {
         // service 2
      }
      // ...
   ]
}

Note: To understand the meanings of uuid and port_table, please refer to the routing table page.

Services

Each listed service of a node has basic services information:

{ // service 1
   "type":"Type",
   "id":1,
   "alias":"Alias"
}

Note: To understand the meanings of type, id and alias, please refer to the service page.

Full routing table example

{
   "routing_table":[
      {
         "node_id":1,
         "certified":true,
         "port_table":[2, 65535],
         "services":[
            {
               "type":"Gate",
               "id":1,
               "alias":"r_right_arm"
            }
         ]
      },
      {
         "node_id":2,
         "certified":true,
         "port_table":[4, 1],
         "services":[
            {
               "type":"State",
               "id":2,
               "alias":"lock"
            },
            {
               "type":"Unknown",
               "id":3,
               "alias":"start_control"
            }
         ]
      },
      {
         "node_id":3,
         "certified":true,
         "port_table":[5, 3],
         "services":[
            {
               "type":"Imu",
               "id":4,
               "alias":"gps"
            }
         ]
      },
      {
         "node_id":4,
         "certified":true,
         "port_table":[65535, 4],
         "services":[
            {
               "type":"Color",
               "id":5,
               "alias":"alarm"
            },
            {
               "type":"Unknown",
               "id":6,
               "alias":"alarm_control"
            }
         ]
      }
   ]
}

Below is a visual representation of this routing table:

Service's information messages

When the JSON routing table is transmitted, the gate updates and streams your network data with services information.

This JSON is a "service" object listing all the services by their alias and the values they send:

{
   "services":{
      "service_alias1":{
         "value1":12.5
      },
      "service_alias2":{
         "value1":13.6,
         "value2":[1, 2, 3, 4]
      }
   }
}

You can use the same JSON object structure to send data to services.

Here is the list of all values that services can use:

Value nameDefinition
power_ratioPercentage of power of an actuator (-100% to 100%)
target_rot_positionActuator's target angular position (can be a number or an array)
limit_rot_positionActuator's limit angular position
limit_trans_positionActuator's limit angular position
limit_powerLimit ratio of an actuator's reduction
limit_currentLimit current value
target_rot_speedActuator's target rotation speed
target_trans_positionActuator's target linear position (can be a number or an array)
target_trans_speedActuator's target linear speed
timeTime value
compliantActuator's compliance status
pidSet of PID values (proportional, integral, derivative)
resolutionSensor's resolution value
offsetOffset value
reductionRatio of an actuator's reduction
dimensionDimension value
voltVoltage value
currentElectric current value
reinitReinitialisation command
controlControl command (play, pause, stop, rec)
colorColor value
io_stateIO state
uuidService's uuid
renameRenaming an alias
revisionFirmware revision
trans_positionTranslation position value
trans_speedTranslation speed value
rot_positionRotation position value
rot_speedRotation speed value
luxLux (light intensity) value
temperatureTemperature value
forceForce value
momentTorque value
powerPower value
linear_accelLinear acceleration value
gravity_vectorGravity vector value
compassCompass value
gyroGyroscope value
accelAcceleration value
eulerEuler angle value
quaternionQuaternion values
rotational_matrixRotational matrix values
headingHeading
pedometerSteps number value
walk_timeWalk time value
luos_revisionLuos's version
luos_statisticsLuos's memory usage statistics [Rx stack, Luos stack, Tx stack, Dropped messages, Loop delay, Send retry max number]

Here is an example of a message sent by a potentiometer service containing the rotation angle of the associated potentiometer:

{
   "services":{
      "potentiometer_m":{
         "rot_position":12.5
      }
   }
}

Here is an example of a message sent by a gate service about Luos statistics:

{
   "services":{
      "gate":{
         "luos_statistics":{
            "msg_stack":60,
            "luos_stack":53,
            "msg_drop":0,
            "loop_ms":16,
            "fail_ratio":0,
            "nak_max":1,
            "collision_max":5,
         }
      }
   }
}

Custom parameters and specific messages

Some messages are specifically handled:

Custom parameters can be defined and sent to services through the JSON API, either with Python (Pyluos) or any other programming language on a computer side. Here is an example of a C function that can be implemented in order to send commands to services in a Luos Network, through a gate:

def sendCmd(s, cmd, sleep_time=0.5):
    cmd = cmd + '\r'
    print(cmd)
    s.write(cmd.encode())
    time.sleep(sleep_time)
s = serial.Serial(sys.argv[1], 1000000)
# detect Luos network
sendCmd(s, '{"detection": {}}')
# set speed mode and compliant mode
sendCmd(s, '{"services": {"controller_moto": {"parameters": 2441}}}')
# set pid parameters
sendCmd(s, '{"services": {"controller_moto": { "pid": [20, 0.02, 90]}}}')
# set speed mode and non compliant mode
sendCmd(s, '{"services": {"controller_moto": {"parameters": 2440}}}')

Parameters are defined by a 16-bit bitfield.

ObjectDefinitionStructureService(s)
parametersenabling or disabling some measurementLink to structure (GitHub)Stepper, Controller-motor, Servo
parametersenabling or disabling some measurementLink to structure (GitHub)Imu

Other specific messages:

ObjectDefinitionService(s)
registerMotor memory register filed with [register_number, value]Dynamixel, void
set_idA set id commandDynamixel, void
wheel_modeThe wheel mode parameter for Dynamixel servomotors True or FalseDynamixel, void
delayreduce services refresh rateGate

Services exclusion messages

Services can be excluded from the network if a problem occurs (see self-healing for more information). In this case, the gate sends an exclusion message indicating that this service is no longer available:

{"dead_service": "service_alias"}

Node assert messages

Nodes can assert if a critical issue occurs (see self-healing for more information). In this case, the gate sends an assertion message indicating that this node is no longer available and some details about the crash:

{
   "assert":{
      "node_id":3,
      "file":"/Users/foo/luos/Examples/Drivers/Button/button.c",
      "line":75
   }
}

Sending large binary data

Binary data such as, for example, a motor trajectory can't be included in a JSON file if it is too large. In order to allow this type of transmission, the size of the binary data is sent through the JSON, followed by the actual data in binary format.

  • If the data is short, it can be displayed inside the JSON as a regular value (see the different values in service's information messages section), or as a table of several values (for example a motor trajectory).

  • If the data is large, the defined value must be a table of one element, containing only the size of the binary data to be transfered in bytes.

The following example shows a transfer of binary data of 1024 bytes.

{
   "services":{
      "service_alias1":{
         "rot_position":[1024]
      }
   }
}
###BINARY_DATA###