Skip to content

Warehouse automation with modular (or other) robots

Notifications You must be signed in to change notification settings

NoosWare/Noos-Open

Repository files navigation

PoRoLog ROSE-AP

License: Apache 2.0

ROSE-AP of the PoRoLog project, offers

  • Easy deployment of the NOOS Open Cloud infrastructure via docker-compose, allowing for robot logistics applications
  • Bootstrapping ROS2 software that can be installed in a ROS2-enabled Robot to automatically connect it to the NOOS Open infrastructure
  • Codin dashboards, via which a Warehouse that uses the NOOS Open infrastructure can inspect its real-time status.

A tutorial is available at https://www.youtube.com/watch?v=_dSlfYfUmKg

This project is part of DIH^2.

Contents

Background

Modern warehouses require for modern logistics solutions. PoRoLog aspires to provide a robotics-based solution that can contribute to automate and/or improve day-to-day workload, so that the warehouse improves its efficiency, optimizes storage capacity, and decrease physical work. Specifically, PoRoLog proposes a new reconfigurable and scalable robotic system for pallet and box transfers in existing logistics warehouses and a new open source software for supervision of groups of robots named NOOS-Open. A real size technology transfer experiment in a real warehouse with Industry and Logistics 4.0 in mind will be performed, resulting in hardware and software available for other SMEs on RAMP for easy replication at European level.


NOOS-Open Installation

Deployment of Noos-Open cloud infrastructure

Noos-Open is supported by a cloud infrastructure, which relies on a Fiware Orion broker and a Mosquitto MQTT broker instance. In the following image, you may see the overall architecture.

Untitled

The deployment of the cloud components of Noos-Open can be achieved using these files: https://github.com/robotics-4-all/porolog-deployment

Important: It is presumed that all commands are executed from the root directory of this repository!

Prerequisites

In order to properly deploy this infrastructure the following packages are required

Software Version
docker 19.03.5-ce, build 633a0ea838 or higher
docker-compose 2.4.1 or higher
  • In order to install docker engine follow the tutorial.
  • In order to install docker-compose follow the tutorial.

Setup

In order to properly configure the setup the environmental variables of .env file must be set approprietly. Also the mosquitto pwfile file must be overridden with the appropriate credentials and be placed in the ./mosquitto directory.

To create a mosquitto pwfile simply run:

mosquitto_passwd -U ./mosquitto/pwfile <user>

Note: You will be prompted to enter the user's password twice.

The MOSQUITTO_USERNAME & MOSQUITTO_USERNAME must in the .env file be updated accordingly to match the credentials given in the pwfile so as the json-iot-agent is able to connect to the mosquitto broker. Optionally the other environmental variables can also be changed.

Finally the host environmental variable must be set to must the domain_name/ip of the host machine.

Execution

To create the infrastructure simply execute the following command:

./launch.sh

Note: The script must have execution privilages. Run the following command as superuser if the priviledges are insufficient.

sudo chmod +x launch.sh

Codin dashboard

Codin is not open-source but it is (and will be) free for use. The dashboards can be exported in JSON formatted files and imported by another user, making the solution easily transferable.

The Codin dashboard created for supporting Noos-Open can be found in this link. You can import it in Codin, declare your deployment's credentials and inspect your robots!

Future work

  • Security on orion context broker via keyrock
  • Mosquitto certificates

Fiware NGSI types

In order for the NOOS open to correctly operate, logistics-specific NGSI data types have been defined, so as to handle the data storage and retrieval. Specifically we have the following types:

  • Warehouse: Holds the necessary information of a whole warehouse.
  • WarehouseKPI: Includes some Key Performance Indicators (KPIs) for the warehouse, for a single day. It is expected that a different WarehouseKPI instance is created each day.
  • Robot: Holds the necessary information about a robot that exists in a Warehouse.
  • RobotKPI: Holds the KPIs of a specific Robot.
  • Room: A Warehouse consists of Rooms
  • Rack: A Room contains Racks
  • Shelf: A Rack contains Shelfs
  • Slot: A Shelf contains Slots
  • Pallet: A Pallet can be placed in a Slot
  • Parcel: A Parcel can be placed in a Slot or exist in a Pallet

Below, you can see how the Warehouse, Room, Rack, Shelf and Slot entities are geometrically connected.

image

Warehouse NGSI type

{
    "id": "-",
    "type": "Warehouse",
    "name": {
        "type": "Text",
        "value": "Bleujour"
    },
    "georeference": {
        "type": "vector",
        "value": {
            "longitude": 43.5746458,
            "lattitude": 1.4514467
        },
        "metadata": {
            "address": {
                "type": "postalAddress",
                "value": {
                    "streetAddress": "37 Av. Jules Julien",
                    "addressRegion": "Toulouse, France",
                    "addressLocality": "-",
                    "postalCode": "31400"
                }
            }
        }
    },
    "blueprint": {
        "type": "string",
        "value": ""
    },
    "dimensions": {
        "type": "vector",
        "value": {
            "width": 100,
            "height": 50,
            "resolution": 0.1
        }
    },
    "annotations": {
        "type": "list",
        "value": []
    },
}

WarehouseKPI NGSI type

{
    "id": "-",
    "type": entity_type,
    "date": {
        "type": "Date",
        "value": {
            "val": "14/06/2022"
        }
    },
    "palleteStorageDensity": {
        "type": "number",
        "value": {
            "val": 1
        }
    },
    "distanceXmassMovedByRobots": {
        "type": "number",
        "value": {
            "val": 1
        }
    },
    "distanceXmassMovedByOperators": {
        "type": "number",
        "value": {
            "val": 1
        }
    },
    "palletsMoved": {
        "type": "number",
        "value": {
            "val": 1
        }
    },
    "parcelsMoved": {
        "type": "number",
        "value": {
            "val": 1
        }
    },
    "savedTimeshareForOperator": {
        "type": "number",
        "value": {
            "val": 1
        }
    },
    "refWarehouse": {
        "type": "Relationship",
        "value": "urn:ngsi-ld:Warehouse:1"
    }
}

Robot NGSI type

{
    "device_id": "Robot1",
    "entity_name": "urn:ngsi-ld:Robot:1",
    "entity_type": "Robot",
    "transport": "MQTT",
    "pose": {
        "type": "pose",
        "x": 0.0,
        "y": 0.0, 
        "z": 0.0
    },
    "path": {
        "type": "list", 
        "points": []
    },
    "origin": {
        "x": 50,
        "y": 50
    },
    "target": {
        "type": "point", 
        "x": 0.0,
        "y": 0.0
    }, 
    "targetProduct": {
        "type": "productID", 
        "val": "Product-001"
    },
    "velocities": {
        "type": "vector2d", 
        "linear": 0.0,
        "angular": 0.0
    },
    "state": {
        "type": "enum", 
        "val": "IDLE"
    },
    "power": {
        "type": "float", 
        "percentage": 1.0
    },
    "heartbeat": {
        "type": "bool", 
        "val": true
    },
    "logs": {
        "type": "string", 
        "val": "I am a default log!"
    },
    "image": {
        "type": "string", 
        "val": ""
    },
    "attributes": [
        {"object_id": "pose", "name": "pose", "type": "pose"}, 
        {"object_id": "path", "name": "path", "type": "list"}, 
        {"object_id": "target", "name": "target", "type": "point"}, 
        {"object_id": "targetProduct", "name": "targetProduct", "type": "productID"}, 
        {"object_id": "velocities", "name": "velocities", "type": "vector2d"}, 
        {"object_id": "state", "name": "state", "type": "enum"},
        {"object_id": "power", "name": "power", "type": "float"}, 
        {"object_id": "heartbeat", "name": "heartbeat", "type": "bool"}, 
        {"object_id": "logs", "name": "logs", "type": "string"},
        {"object_id": "image", "name": "image", "type": "string"}
    ], 
    "static_attributes": [{
        "name":"refWarehouse", "type": "Relationship", "value": "urn:ngsi-ld:Warehouse:1"
    }]
}

RobotKPI NGSI type

{
    "id": "-",
    "type": entity_type,
    'date': {
        'type': 'Date',
        'value': {
            'val': ''
        }
    },
    'boxedMoved': {
        'type': 'number',
        'value': {
            'val': 0
        }
    },
    'palletesMoved': {
        'type': 'number',
        'value': {
            'val': 0
        }
    },
    'distance': {
        'type': 'number',
        'value': {
            'val': 0
        }
    },
    "refRobot": {
        "type": "Relationship",
        "value": "urn:ngsi-ld:Robot:1"
    }
}

Room NGSI type

{
    "id": "-",
    "type": entity_type,
    "floor": {
        "type": "number",
        "value": 0
    },
    "blueprint": {
        "type": "string",
        "value": ""
    },
    "dimensions": {
        "type": "vector",
        "value": {
            "width": 20,
            "height": 20,
            "z": 4.5,
            "resolution": 0.1
        }
    },
    "annotations": {
        "type": "list",
        "value": []
    },
    "groundType": {
        "type": "string",
        "value": ""
    },
    "origin": {
        "type": "vector",
        "value": {
            "x": 25,
            "y": 5
        }
    },
    "refWarehouse": {
        "type": "Relationship",
        "value": "urn:ngsi-ld:Warehouse:1"
    }
}

Rack NGSI type

{
    "id": "-",
    "type": entity_type,
    "maxPayload": {
        "type": "number",
        "value": 300
    },
    "dimensions": {
        "type": "vector",
        "value": {
            "length": 10,
            "width": 1,
            "height": 4,
            "orientation": 0.78539
        }
    },
    "origin": {
        "type": "vector",
        "value": {
            "x": 2,
            "y": 10
        }
    },
    "refRoom": {
        "type": "Relationship",
        "value": "urn:ngsi-ld:Room:1"
    }
}

Shelf NGSI type

{
    "id": "-",
    "type": entity_type,

    "altitude": {
        "type": "number",
        "value": 2.5
    },
    "surfaceNature": {
        "type": "string",
        "value": ""
    },
    "refRack": {
        "type": "Relationship",
        "value": "urn:ngsi-ld:Rack:1"
    }
}

Slot NGSI type

{
    "id": "-",
    "type": entity_type,
    "width": {
        "type": "number",
        "value": 0.5
    },
    "originx": {
        "type": "number",
        "value": 4
    },
    "refShelf": {
        "type": "Relationship",
        "value": "urn:ngsi-ld:Shelf:1"
    }
}

Pallet NGSI type

{
    "id": "-",
    "type": entity_type,
    "dimensions": {
        "type": "vector",
        "value": {
            "length": 0,
            "width": 0,
            "height": 0
        }
    },
    "barcode": {
        "type": "string",
        "value": {
            "val": "xxx"
        }
    },
    "material": {
        "type": "string",
        "value": ""
    },
    "fragile": {
        "type": "bool",
        "value": "false"
    },
    "refSlot": {
        "type": "Relationship",
        "value": "urn:ngsi-ld:Slot:1"
    }
}

Parcel NGSI type

{
    "id": "-",
    "type": entity_type,
    "dimensions": {
        "type": "vector",
        "value": {
            "length": 0.2,
            "width": 0.2,
            "height": 0.2
        }
    },
    "sku": {
        "type": "string",
        "value": "xxx"
    },
    "manufacturer": {
        "type": "string",
        "value": ""
    },
    "manufDate": {
        "type": "Date",
        "value": ""
    },
    "content": {
        "type": "string",
        "value": ""
    },
    "mass": {
        "type": "number",
        "value": 1
    },
    "price": {
        "type": "number",
        "value": 0
    },
    "fragile": {
        "type": "bool",
        "value": "true"
    },
    "itemQuantity": {
        "type": "number",
        "value": 10
    },
    "refPallet": {
        "type": "Relationship",
        "value": "urn:ngsi-ld:Pallet:1"
    }
}

Robot(s) setup

In order to integrate a robotic platform to the NOOS-Open infrastructure, the robot must be ROS2-enabled, at least supporting the ROS2 Navigation stack. Furthermore, its OS must be unix-based, in order to be able to execute Python v3, as well as the Commlib-py library, which acts as the communication channel between the Robot and NOOS-Open.

Bootstrapping software

For easier integration, NOOS-Open provides a bootstrapping ROS2 package that can be easily modified for any ROS2-supporting robot and allow for quick and easy integration with the NOOS-Open infrastructure. This package is located here.

Below follows the instructions to execute it:

Prerequisites

  1. Ubuntu Linux 20.04 
  2. ROS 2 Foxy Fitzroy installed
  3. Gazebo installed
  4. Commlib-py installed 
  5. Ros 2 workspace

Instructions

  1. Copy basic_mobile_robot folder inside ros2_workspace/src
  2. Build the package
cd ~/ros2_workspace

colcon build
  1. Open ~/.bashrc and add the following lines to the end
source ~/ros2_workspace/install/setup.bash
export GAZEBO_MODEL_PATH=$GAZEBO_MODEL_PATH:~/ros2_workspace/src/basic_mobile_robot/models/
  1. Open a terminal and run the launch.file. Gazebo and RVIZ will open with Navigation2
cd ros2_workspace/src/basic_mobile_robot

ros2 launch basic_mobile_robot basic_mobile_bot.launch.py 
  1. In another terminal run the script file
cd ros2_workspace/install/basic_mobile_robot/lib/basic_mobile_robot/

ros2 run basic_mobile_robot py_node.py

Custom robot integration

In the case where anyone wants to implement their own controllers (or some of them), they can write their own Python ROS2 package and create the following Commlib publishers/subscribers with the following data models:

PUBLISHER /<ORION_API_KEY>/<ROBOT_ID>/attrs/battery

{
    percentage: <Float>
}

PUBLISHER /<ORION_API_KEY>/<ROBOT_ID>/attrs/image

{
    val: <String> # The base64 encoded image
}

PUBLISHER /<ORION_API_KEY>/<ROBOT_ID>/attrs/logs

{
    val: <String>
}

PUBLISHER /<ORION_API_KEY>/<ROBOT_ID>/attrs/state

{
    state: <String>
}

PUBLISHER /<ORION_API_KEY>/<ROBOT_ID>/attrs/status

{
    status: <String>
}

SUBSCRIBER /<ORION_API_KEY>/<ROBOT_ID>/attrs/velocities

{
    command: <String> # One of FORWARD, BACKWARD, LEFT, RIGHT, STOP, LIFT, RELEASE
}

PUBLISHER /<ORION_API_KEY>/<ROBOT_ID>/attrs/status

{
    linear: <Float>,
    angular: <Float>
}

PUBLISHER /<ORION_API_KEY>/<ROBOT_ID>/attrs/status

{
    linear: <Float>,
    angular: <Float>
}

PUBLISHER /<ORION_API_KEY>/<ROBOT_ID>/attrs/pose

{
    x: <Float>,
    y: <Float>,
    theta: <Float>
}

PUBLISHER /<ORION_API_KEY>/<ROBOT_ID>/attrs/path

{
    path: [
        {
            x: <Float>,
            y: <Float>
        },
        ...
    ]
}

SUBSCRIBER /<ORION_API_KEY>/<ROBOT_ID>/attrs/target

{
    x: <Float>,
    y: <Float>
}

SUBSCRIBER /<ORION_API_KEY>/<ROBOT_ID>/attrs/goal/entity

{
    type: <String>, # One of Parcel, Pallet, Slot
    id: <String>
}

Step by step tutorial

Step by step tutorial on Noos-Open can be found here: https://www.youtube.com/watch?v=_dSlfYfUmKg


Utilities - Fiware & MQTT broker accompanying files

  • Commlib-py: Robot communication controller, i.e. the software to dispatch information to Fiware broker via MQTT, using Python. This component is commlib-py and is currently open-source
  • Fiware entities JSON: Here you can find a collection of JSON-formatted files that contain the Fiware NGSI types, suitable for logistics applications
  • Hoppscotch Fiware-related REST calls: REST collections for invoking and updating all Fiware entities. Hoppscotch is the open-source alternative of Postman, alleviating its restrictions regarding membership
  • Script: Python script using REST-ee-Fi, via which an initial insertion of mock data to the respective Fiware entities is performed, so as for the Hoppscotch calls to operate
  • Script: Python script that takes as input a Parcel’s ID and retrieves its x,y coordinates in the absolute coordinate frame (warehouse frame)

About

Warehouse automation with modular (or other) robots

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published