No description
Find a file
2012-05-21 11:42:57 +02:00
examples add icra2011 examples 2012-05-20 12:22:06 +02:00
legacy give credit to Jake Gordon and Jim Scott 2012-05-21 11:42:57 +02:00
.gitignore clean up project directory, add proper copyright 2012-05-16 18:35:58 +02:00
add_approach_points.py add all those small scripts 2012-05-16 10:43:22 +02:00
arrange_spread2.py give credit to Jake Gordon and Jim Scott 2012-05-21 11:42:57 +02:00
barcodes.py clean up project directory, add proper copyright 2012-05-16 18:35:58 +02:00
bruteforce2.py clean up project directory, add proper copyright 2012-05-16 18:35:58 +02:00
bruteforce3.py clean up project directory, add proper copyright 2012-05-16 18:35:58 +02:00
COPYING clean up project directory, add proper copyright 2012-05-16 18:35:58 +02:00
densities.py clean up project directory, add proper copyright 2012-05-16 18:35:58 +02:00
descriptions.py clean up project directory, add proper copyright 2012-05-16 18:35:58 +02:00
evaluate.py clean up project directory, add proper copyright 2012-05-16 18:35:58 +02:00
evaluate_multi.py clean up project directory, add proper copyright 2012-05-16 18:35:58 +02:00
num_articles_order.py clean up project directory, add proper copyright 2012-05-16 18:35:58 +02:00
num_articles_packlist.py clean up project directory, add proper copyright 2012-05-16 18:35:58 +02:00
pallets.py clean up project directory, add proper copyright 2012-05-16 18:35:58 +02:00
palletViewer-sharedlib.diff add palletViewer patch for shared library compilation 2012-05-20 09:35:33 +02:00
README.md README.md corrections and additions 2012-05-20 13:54:40 +02:00
run.sh place files into /dev/shm by default, prettify xml, more useful run.sh output 2012-05-20 12:39:11 +02:00
split_multi.py split a multi-pallet packlist into multiple single-pallet packlists 2012-05-16 18:58:20 +02:00
svg.py clean up project directory, add proper copyright 2012-05-16 18:35:58 +02:00
util.py clean up project directory, add proper copyright 2012-05-16 18:35:58 +02:00

about

sisyphus is a piece of software I wrote the context of my graduate automation project. My class was taking part in the IEEE ICRA 2012 Virtual Manufacturing Automation Competition and part of the competition, was to efficiently stack boxes of different sizes on a pallet.

As the knapsack problem is NP hard, sisyphus implements hybrid between heuristic and bruteforce approach.

The heuristic is, to group articles of same height into layers, and then stack those layers on top of each other.

Different techniques to form layers and different orderings of stacking them are then tried out in a bruteforce manner.

get the code

$ git clone git@github.com:josch/sisyphus.git
$ cd sisyphus

compile evaluation library

$ wget http://sourceforge.net/projects/moast/files/Pallet%20Viewer/Version%203/palletandtruckviewer-3.0.tar.gz
$ tar xf palletandtruckviewer-3.0.tar.gz
$ cd palletandtruckviewer-3.0
$ patch -p0 < ../palletViewer-sharedlib.diff
$ autoreconf -fi
$ ./configure --libdir=`pwd`/..
$ make
$ make install-strip
$ cd ..

test evaluation library (optional)

$ python evaluate_multi.py examples/icra2012/packlist_R1.xml examples/icra2012/scorecog.xml

$ python evaluate.py examples/icra2012/Challenge2.order.xml examples/icra2012/packlist_R2.xml examples/icra2012/scorecog.xml

$ python evaluate.py examples/icra2012/Challenge2.order.xml examples/icra2012/packlist_R3.xml examples/icra2012/scorecogoverlap.xml

generate packlist files

$ ./run.sh examples/icra2011/palDay1R1Order.xml packlist.xml examples/icra2011/scoreAsPlannedConfig1.xml

Usage

bruteforce2.py takes an order.xml and tries different strategies to create many lists of layerlists. Each layerlist is built with a different selection of strategies. Available strategies are article rotation and pallet rotation which can both be either true or false. Per default, bruteforce2.py tries all combinations of article and pallet rotations, which means that for each new layer, there are four possibilities how articles can be arranged in it.

A layerlist is the result of one specific combinations of strategies. For example: first layer with article rotation and pallet rotation, second layer without article rotation but with pallet rotation, third layer with neither and so forth.

bruteforce2.py outputs those layerlists one per line in python pickle gzipped and base64 encoded format. Python pickle is used as a fast serialization format. The data is gzipped because it is given to bruteforce3.py as a commandline argument and those must not exceed an OS specific value. The data is base64 encoded to avoid zero bytes, newlines and other whitespace characters in them.

As a result, the output of bruteforce2.py can not only be saved in a file, but you can also used split(1) on it to distribute it onto many machines for evaluations. You can also use head(1), tail(1), sort(1) or uniq(1) on the output.

bruteforce3.py takes as arguments an order.xml, a packlist.xml output file, a scoring.xml file and a number of layerlists, encoded as described above. For each layerlist it will try every possible permutation of how to place them on top of each other and evaluate each of them by using palletViewer.

Multiple instances of bruteforce3.py can be run on the same machine. Before bruteforce3.py exits, it will put a file lock on score_max.lock and read the currently highest score from score_max. If the just calculated score is higher, it will write its own score into score_max and update the contents of packlist.xml as well.

Since score_max always contains the currently highest score, it can always easily be checked during a run, what the currently highest score achieved is.

Since packlist.xml always contains the best packlist found so far, bruteforce3.py can always be aborted in the middle of execution, should it take too long to evaluate while still maintaining the current best packlist. One does not need to wait until run.sh finished execution.

Since score_max contains the highest score, it should be removed before each new run. This is already done by run.sh.

environment variables

bruteforce2

rot_article         - try different article rotations (default: True)
rot_pallet          - try different pallet rotations (default: True)
rot_article_default - default article rotation (default: False)
rot_pallet_default  - default pallet rotation (default: False)
iterations          - maximum number of iterations (default: -1)
randomize           - try random strategies instead of sequential (default: False)

bruteforce3

multi_pallet        - respect pallet max height and spread over multiple pallets (default: False)
permutations        - whether to try all layer permutations or not permute at all (default: True)
iterations          - maximum number of iterations (default: -1)
randomize           - try random strategies instead of sequential (default: False)

For orders that are too big to enumerate all possible permutations of layer strategies and orderings, using randomize and iterations for bruteforce2.py and bruteforce3.py is recommended.

The according line in run.sh could be changed to:

iterations=100 randomize=1 python bruteforce2.py $1 | randomize=1 iterations=1000 xargs --max-procs=4 --max-args=1 python bruteforce3.py $1 $2 $3

utility scripts

add_approach_points.py

    takes a single or multi pallet packlist.xml and adds the three approach
    points to all the articles in it, relative to each articles position

barcodes.py

    takes an order.xml and prints all barcodes in it

densities.py

    takes an order.xml and prints the density of all articles

descriptions.py

    takes an order.xml and prints a table with the description, ID, type,
    family, size and weight of every article

evaluate_multi.py

    takes a multiple pallet packlist.xml and a scoring.xml and prints out
    the score that this packlist achieves

evaluate.py

    takes an order.xml, a single pallet packlist.xml and a scoring.xml and
    prints out the score that this packlist achieves

num_articles_order.py

    takes an order.xml and prints the number of articles within

num_articles_packlist.py

    takes a single or multi pallet packlist.xml and prints the number of
    articles within

pallets.py

    takes an order.xml and prints a table with the length, width, maximum
    load height and maximum load weight

split_multi.py

    takes a multiple pallet packlist.xml and outputs pairs of single pallet
    packlist.xml and order.xml files by appending _$i.xml and _order_$i.xml
    to the original packlist.xml filename, respectively. The integer $i
    starts at 0 and	will be incremented with each subsequent pallet.

evaluation of multi pallet packlists

palletViewer cannot parse multi pallet packlists, hence the packlists have to be split into several single pallet packlists. Each of those packlists is then given to palletViewer for evaluation. The individual results are averaged for a final score. To avoid each of the palletViewer instances complain about missing articles, an according order.xml file is created for each single pallet packlist.xml.

Multi pallet packlists can evaluated like this:

python evaluate_multi.py packlist.xml scoring.xml

Or manually like this:

python split_multi.py packlist.xml
python evaluate.py packlist.xml_order_0.xml packlist_R1.xml_0.xml scoring.xml
python evaluate.py packlist.xml_order_1.xml packlist_R1.xml_1.xml scoring.xml
...

bugs

there is a "memory leak" in bruteforce3.py. Every loop iteration where a new permutation is tried out will stay in memory. This is not needed and should not be the case. This is the reason why run.sh supplies bruteforce3.py with only one layerlist at a time because otherwise, memory consumption would grow too big.

ICRA 2012 VMAC

Sisyphus won the IEEE ICRA 2012 Virtual Manufacturing Automation Competition. Here is some media about our submission:

Round1: ./examples/icra2012/packlist_R1.xml

Round2: ./examples/icra2012/packlist_R2.xml

Round3: ./examples/icra2012/packlist_R3.xml

announcement: http://youtu.be/8fYF-Ldi1NQ

presentation: http://youtu.be/FSqjGiVt50I