Git Product home page Git Product logo

iml130 / pfdl Goto Github PK

View Code? Open in Web Editor NEW
9.0 2.0 2.0 6.62 MB

A Production Flow Description Language for an Order-Centric Production

Home Page: https://iml130.github.io/pfdl/

License: MIT License

Python 98.99% ANTLR 1.01%
order-controlled-production domain-specific-language industry-40 antlr4-grammar antlr4-python3 petri-nets python3 scheduler tasks description-language production industry-4 python

pfdl's Introduction

Production Flow Description Language

pfdl_logo

Tests Lint Check Code Coverage Build and deploy Docu REUSE status

DISCLAIMER: This project is not intended for everyday use and made available without any support. However, we welcome any kind of feedback via the issue tracker or by e-mail.


The Production Flow Description Language (PFDL) is a domain specific language for the description of production orders in the manufacturing of the future. With the help of the PFDL customized products and their production steps can be described.

This project consists of the PFDL Grammar and Scheduler. The Scheduler is the main part of the language. It parses PFDL files and generates a Petri net for scheduling the production task if the given file is valid.

For more infos visit the official 📚 Documentation.

Quick Installation

The fastest way to get the PFDL Scheduler running is by installing the PyPi package via pip in a virtual environment:

python3 -m venv venv-pfdl source venv-pfdl/bin/activate pip install pfdl-scheduler

Requirements

  • Pip packages from requirements.txt (pip install -r requirements.txt)
  • GraphViz (if you want to use the scheduler/run the scheduler_demo.py)

How to Start

Validation

If you just want to validate your PFDL files run the following command from the root directory of the project. All errors will be printed in the console, so if nothing is shown the file valid.

python validate_pfdl_file.py --file_path <path_to_pfdl_file>

You can also use the flag --folder_path to check all PFDL files within a folder.

Scheduler

To make use of the scheduler you can import the scheduler class and use it like in the scheduler_demo.py. We will provide a pip package for the scheduler module later so there is no need to run it anymore. If you want to run the scheduler from the command line, you can execute the scheduler_demo.py which is a small example program to demonstrate the use of the scheduler class. Run the following command from the root directory of the project.

python scheduler_demo.py <path_to_pfdl_file>

It will parse the given file and validates it. If the program is valid a petri net will be generated in the root directory.

Tests

We also provivde unit tests e.g. for the static semantic validaton methods. To run all the test files you can use a testing environment (e.g. Testing in VSCode) or just execute the following command in the projects root directory:

python -m unittest discover -v

Use the PFDL Scheduler as Submodule

If you want to use the PFDL Scheduler in your existing project you can use this project as a submodule. To run the Scheduler succesfully from your python code you have to add the pfdl_scheduler folder to the sys path somewhere before using (importing) it:

import sys
import os
import inspect

currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
sys.path.insert(0, currentdir + "/pfdl_scheduler")

# you can use the PFDL Scheduler classes now
from pfdl_scheduler.scheduler import Scheduler

Troubleshooting

No PetriNet is generated / there is an error while generating the net

Check if you correctly installed GraphViz (On Windows you need to put the bin folder inside the GraphViz folder into the PATH environment variable. On Ubuntu it should be fine if you install GraphViz via apt-get)

License

PDFL is licensed under the MIT License. See LICENSE for details on the licensing terms.

Academic Attribution

If you use the PFDL for research, please include the following reference in any resulting publication.

@INPROCEEDINGS{PFDL_Detzner_2022,
  author={Detzner, Peter and Ebner, Andreas and Hörstrup, Maximilian and Kerner, Sören},
  booktitle={2022 22nd International Conference on Control, Automation and Systems (ICCAS)}, 
  title={PFDL: A Production Flow Description Language for an Order-Controlled Production}, 
  year={2022},
  volume={},
  number={},
  pages={1099-1106},
  doi={10.23919/ICCAS55662.2022.10003953}}

pfdl's People

Contributors

ltoenning avatar marbre avatar maxhoerstr avatar oliverstolzbo avatar ptrdtznr avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

pfdl's Issues

Missing Input and Output Variables for productionTasks

In productionTasks it is not possible to define/declare input and output variables. As a result, additional tasks must be defined for the use of conditions, even if the condition is only applied to a single service. This makes the petri nets unnecessarily complex, as places and transitions are introduced that are not required for the process.

As possible solution could be to either declare variables outside of Tasks as global variables (data type of the variable, variable name)

cr_data_type cr =
      {
            parts_count = 3,
            sheet_parts = [0,0,0]
        }
Task productionTask
    In cr:datatype
    Loop i To cr.parts_count
        Painting
            In
                cr.sheet_parts[i]
End

or it should be possible to define literal values as input for a production task, as allowed by all other defined tasks

Task productionTask
    In 
        cr_data_type{
            parts_count = 3,
            sheet_parts = [0,0,0]
        }
    Loop i To cr.parts_count
        Painting
            In
                cr.sheet_parts[i]
End

A similar concept should exist for output variables, so that the result of a pfdl process can be transferred to further processes

Improve error messages for semantic errors

Currently not all semantic error messages are printed correctly or at all. Due to the fact that the semantic check is executed after the parsing, a way of saving the context infos had to be implemented. Currently, not all informations about the specific parts of the program are saved. Find a way to preserve the context information for every bit of PFDL code in the SemanticErrorChecker to provide proper error messages.

An example for this issue is shown below:

image

The attribute not an attribute is not defined in the Struct Color. The error highlight should appear in the same row as the attribute and not at the Struct name. Currently, the SemanticErrorChecker do not have enough information to display it at the correct position.

Should we switch to Conventional Commits?

To unify the style of our commits, we could use Conventional Commits. It provides a set of rules on how to write a commit message.

An example commit message looks like the following:

<type>[optional scope]: <description>

[optional body]

[optional footer(s)]

Here, type is an identifier like "fix" or "feat".

Missing Output for Parallel Loop Conditions

In parallel Loop Conditions it is possible to hand over a specific position of an array variable to a task/service. E.g.

Parallel Loop i To cr.parts_count
        paintingAndCuttingTask
            In
                cr.sheet_parts[i]

However, it is not possible to specify such a field position as output. As a consequence, it is not possible to specify an output for parallel loops since there will be a loss of data if the whole array is defined as input and output, e.g.

cr{
 sheet_parts = [0,0,0],
 parts_count = 3
}

Parallel Loop i cr.parts_count
    paintingAndCuttingTask
       In
          cr.sheet_parts
       Out
          cr.sheet_parts

Here, each of the parallel tasks get the initial input value sheet_parts = [0,0,0]. Since the output of each task writes the variable cr.sheet_parts, the results of the first two paintingAndCuttingTasks that are finished are lost and only the one that finished last is saved.

CI doesn't cover GH Action configuration

Sending #33 and #34, I realized that GitHub Actions are not triggered if the configuration of an Action is altered. This shouldn't be the case as modifications to the configs have the potential to break the CI but one won't notice before modifying code.

Type of array elements in instantiated struct is not set

If a struct is instantiated, for example in a Service call, the struct can contain an array. This array has no information about the type of its elements. For simple datatypes like number or string, it can be set through the values of the array. If the values of the array are also structs, which has to be instantiated too, it is not known to which struct defintion they belong.
It could be set in the semantic validation when the Struct instances are checked.

Inform dashboard about token changes in a Petri Net in a lightweight format

Since Petri Net updates often only consist of changing the token labels of single nodes, it is not necessary to resend the whole dotfile every time to update the SWAP-IT dashboard. Instead, the dotfile should only be resent in the case of major changes in the graph (such as node movement or addition). In the case of token updates only, it would be sufficient to send the node IDs whose token has been updated (added or removed). This would improve the performance of the dashboard and reduce network traffic.

TypeError when executing a counting Loop after a Parallel Loop

I receive the following TypeError for a PFDL description that includes a Counting Loop aafter a Parallel Loop. The error occurs when the counting Loop starts.

Traceback (most recent call last):
File "C:\Users\flo47663\Desktop\EE-SWAP\executionengine\start_execution_engine.py", line 42, in
main_loop.run_until_complete(ee.main())
File "C:\Users\flo47663\Anaconda3\lib\asyncio\base_events.py", line 647, in run_until_complete
return future.result()
File "C:\Users\flo47663\Desktop\EE-SWAP\executionengine\AuftragsAgentServer\execution_engine.py", line 75, in main
scheduler.fire_event(event)
File "C:\Users\flo47663\Desktop\EE-SWAP\executionengine/pfdl_scheduler\pfdl_scheduler\scheduler.py", line 181, in fire_event
if self.petri_net_logic.fire_event(event):
File "C:\Users\flo47663\Desktop\EE-SWAP\executionengine/pfdl_scheduler\pfdl_scheduler\petri_net\logic.py", line 127, in fire_event
self.evaluate_petri_net()
File "C:\Users\flo47663\Desktop\EE-SWAP\executionengine/pfdl_scheduler\pfdl_scheduler\petri_net\logic.py", line 99, in evaluate_petri_net
callback()
File "C:\Users\flo47663\Desktop\EE-SWAP\executionengine/pfdl_scheduler\pfdl_scheduler\scheduler.py", line 378, in on_counting_loop_started
self.loop_counters[task_context.uuid][loop.counting_variable] + 1
TypeError: unsupported operand type(s) for +: 'ParallelLoopCounter' and 'int'

The executed pfdl is:

Struct Order
order_id:number
stand:Stand_Segment
segments: Light_Segment[]
number_light_segments: number
End

Struct Stand_Segment
stand_shape:string
stand_height:number
stand_id:string
End

Struct Light_Segment
color: string
diameter: number
segment_id:string
End

Struct Raw_Material
blanks:Blank[]
blank_number:number
End

Struct Blank
blank_type:string
blank_id: string
part_id:number
End

Task productionTask
Parallel
manufacture_light_segments
In
Order
{
"order_id":1000,
"stand":{
"stand_shape":"plate",
"stand_height":3,
"stand_id": "Default"
},
"segments":
[
{
"color": "red",
"diameter": 5,
"segment_id": "Default"
}
],
"number_light_segments": 5
}
manufacture_stand_segment
In
Order
{
"order_id":1000,
"stand":{
"stand_shape":"plate",
"stand_height":3,
"stand_id": "Default"
},
"segments":
[
{
"color": "red",
"diameter": 5,
"segment_id": "Default"
}
],
"number_light_segments": 5
}
End

Task manufacture_light_segments
In
order: Order
Parallel Loop i To order.number_light_segments
manufacture_light_segment
In
order
Loop i To order.number_light_segments
Gluing
In
order

End

Task manufacture_stand_segment
In
order: Order
GetPartsFromWarehouse
In
ResourceAssignment
order
Milling
In
ResourceAssignment
order
End

Task manufacture_light_segment
In
order: Order
GetPartsFromWarehouse
In
order
Coating
In
order
End

Clean up the grammar specification

The grammar can be cleaned up to make it more clearer / more understandable.
Some examples:

image

  • The number rule is only used in the value rule
  • INTEGER and FLOAT could be moved into the value rule

image

  • Same case for the parameter rule, it could be moved up to the call input rule

Changes like these, would make the grammar and the parser code smaller -> More clearer

Improve the documentation

The documentation needs to be polished up, because some things are missing. For example more detailed descriptions for the examples or typos in the text.

Error when handing over Variables and Literals from Task to Task

When handing over structs and literals from one task to another, I receive different errors regarding the order of literals and variables. The corresponding PFDL
temp.txt
(stored in a txt file) is attached to this Issue.

The Error occurs when handing over input parameter from the manufactre_light_segments task to the manufacture_light_segment task:

Task manufacture_light_segments
In
order: SWAP_Order
order_1: SWAP_Order
cc: Coating_Capabilities
Parallel Loop i To order.number_light_segments
manufacture_light_segment
In
Light_Segment{
"color": "green",
"diameter": 5,
"segment_id": "Default"
}
order
order_1
cc

        Out
            order:SWAP_Order
            test:SWAP_Order

....
End

Task manufacture_light_segment
In
segments: Light_Segment
order: SWAP_Order
order_1: SWAP_Order
cc: Coating_Capabilities
....
End

With the current handover, i receive the error:

Type of TaskCall parameter 'order' does not match with type 'Light_Segment' of Input Parameter 'segments' in Task 'manufacture_light_segment'
File ./PFDL_Examples/patient_zero.pfdl, in line 226:7
Type of TaskCall parameter 'cc' does not match with type 'SWAP_Order' of Input Parameter 'order_1' in Task 'manufacture_light_segment'
File ./PFDL_Examples/patient_zero.pfdl, in line 226:7
Type of TaskCall parameter 'Light_Segment' does not match with type 'Coating_Capabilities' of Input Parameter 'cc' in Task 'manufacture_light_segment'
File ./PFDL_Examples/patient_zero.pfdl, in line 226:7

The error disappears, when the literal values are only handed over after all the variables. I.e. the following definition does not result in an error:

Task manufacture_light_segments
In
order: SWAP_Order
order_1: SWAP_Order
cc: Coating_Capabilities
Parallel Loop i To order.number_light_segments
manufacture_light_segment
In
order
order_1
cc
Light_Segment{
"color": "green",
"diameter": 5,
"segment_id": "Default"
}
Out
order:SWAP_Order
test:SWAP_Order
...
End

Task manufacture_light_segment
In
order: SWAP_Order
order_1: SWAP_Order
cc: Coating_Capabilities
segments: Light_Segment
...
End

The Error persists for each handing over, in which a literal value is handed over before all variable values.

Allow the use of uppercase and lowercase letters for all namings

In the PFDL, only lowercase letters (e.g. fields in structures) or only uppercase letters (e.g. service names) are allowed as the first letter for some components. For users it is sometimes very difficult to understand the error, because the error message, depending on the content of the task can be quite large. The following error message is a result of writing ProductionTask instead of productionTask

mismatched input 'ProductionTask' expecting STARTS_WITH_LOWER_C_STR
File ./PFDL_Examples/test.pfdl, in line 16:5
extraneous input '{' expecting {<EOF>, 'Struct', 'Task', NL}
File ./PFDL_Examples/test.pfdl, in line 20:12
extraneous input 'dedent' expecting {<EOF>, 'Struct', 'Task', NL}
File ./PFDL_Examples/test.pfdl, in line 29:13
extraneous input 'dedent' expecting {<EOF>, 'Struct', 'Task', NL}
File ./PFDL_Examples/test.pfdl, in line 31:34
extraneous input 'Model_generation' expecting {<EOF>, 'Struct', 'Task', NL}
File ./PFDL_Examples/test.pfdl, in line 33:4
extraneous input 'Transport' expecting {<EOF>, 'Struct', 'Task', NL}
File ./PFDL_Examples/test.pfdl, in line 34:4
extraneous input 'dedent' expecting {<EOF>, 'Struct', 'Task', NL}
File ./PFDL_Examples/test.pfdl, in line 36:14
extraneous input 'dedent' expecting {<EOF>, 'Struct', 'Task', NL}
File ./PFDL_Examples/test.pfdl, in line 38:34
extraneous input 'Disassemble_gear' expecting {<EOF>, 'Struct', 'Task', NL}
File ./PFDL_Examples/test.pfdl, in line 40:4
extraneous input '{' expecting {<EOF>, 'Struct', 'Task', NL}
File ./PFDL_Examples/test.pfdl, in line 43:12
extraneous input 'dedent' expecting {<EOF>, 'Struct', 'Task', NL}
File ./PFDL_Examples/test.pfdl, in line 45:13
extraneous input 'dedent' expecting {<EOF>, 'Struct', 'Task', NL}
File ./PFDL_Examples/test.pfdl, in line 47:22
extraneous input 'dedent' expecting {<EOF>, 'Struct', 'Task', NL}
File ./PFDL_Examples/test.pfdl, in line 49:23
extraneous input 'dedent' expecting {<EOF>, 'Struct', 'Task', NL}
File ./PFDL_Examples/test.pfdl, in line 53:18
extraneous input 'dedent' expecting {<EOF>, 'Struct', 'Task', NL}
File ./PFDL_Examples/test.pfdl, in line 55:38
extraneous input 'Transport' expecting {<EOF>, 'Struct', 'Task', NL}
File ./PFDL_Examples/test.pfdl, in line 57:8
extraneous input 'dedent' expecting {<EOF>, 'Struct', 'Task', NL}
File ./PFDL_Examples/test.pfdl, in line 59:18
extraneous input 'dedent' expecting {<EOF>, 'Struct', 'Task', NL}
File ./PFDL_Examples/test.pfdl, in line 61:38
extraneous input 'dedent' expecting {<EOF>, 'Struct', 'Task', NL}
File ./PFDL_Examples/test.pfdl, in line 62:24
extraneous input 'dedent' expecting {<EOF>, 'Struct', 'Task', NL}
File ./PFDL_Examples/test.pfdl, in line 65:14
extraneous input 'dedent' expecting {<EOF>, 'Struct', 'Task', NL}
File ./PFDL_Examples/test.pfdl, in line 67:34
extraneous input 'Transport' expecting {<EOF>, 'Struct', 'Task', NL}
File ./PFDL_Examples/test.pfdl, in line 69:4
extraneous input 'dedent' expecting {<EOF>, 'Struct', 'Task', NL}
File ./PFDL_Examples/test.pfdl, in line 71:14
extraneous input 'dedent' expecting {<EOF>, 'Struct', 'Task', NL}
File ./PFDL_Examples/test.pfdl, in line 73:34
extraneous input 'dedent' expecting {<EOF>, 'Struct', 'Task', NL}
File ./PFDL_Examples/test.pfdl, in line 74:20

In general, it would be very helpful for users to remove these restrictions on namings and allow all namings to start with either an uppercase or a lowercase letter.

Evaluate the use of additional Integration Tests

To test the scheduling in a production environment we need Integration Tests and test files for the scheduling functionality. There are already some Integration tests that run a variety of PFDL files with the scheduler. Evaluate, whether it makes sense to include more Integration Tests (there could also be Integration Tests for the Parsing for example).

Services inside Parallel Conditions

It is not possible to define services inside a parallel condition, but only tasks. However it is possible to use services inside counting loops, while loops and parallel loops. It would be great to enable the use of services inside parallel conditions. otherwise the petri net gets unnecessary places and transitions and becomes more complex.

Implement an interface for the formal representation of the PFDL

Currently the petri net as a formal representation of the PFDL is hard coded in the scheduler. To increase the modularity it could be reasonable to create an interface in the scheduler where arbitrary models (e.g statemachines) can be registered to schedule instead of the petri net. However, the registered callback functions in the scheduler should still work the same way.

Add missing Unit Tests

There are still Unit Tests missing for a few classes and files. To get closer to 100% Code Coverage, Unit Tests for the following classes and files needs to be added:

  • SemanticErrorChecker
  • Model classes
  • PFDLVisitor
  • PetriNet classes
  • API classes
  • Scheduler
  • ErrorHandler and SyntaxErrorHandler
  • Helpers
  • Dashboard

Add information about counting variables in callbacks

The callback functions for task or service calls return information about the called entity. However, if there are calls inside a counting or parallel loop, the callbacks do not provide information about the ith iteration. Consider the following example:

Loop i To cr.parts_count
    millingTask
        In
            cr.sheet_parts[i]

If the task_started callback is triggered multiple times (for multiple iterations) it is necessary to provde the exact value of the counting variable i. Currently, all callbacks only provide the information that there is a variable i and not the value itself.

Implement a plugin system

To allow users to write their own plugins for the PFDL without modifying the core code, we need to implement a plugin system that allows the usage and the import of an arbitrary amount of plugins. In Addition, the existing PFDL code most likely needs to be modified (more modularisation, clearer interfaces, ...) to allow for better plugin developement.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.