working first implementation
This commit is contained in:
parent
14ffc19da8
commit
41e5ec2706
5 changed files with 717 additions and 0 deletions
318
arrange_spread2.py
Normal file
318
arrange_spread2.py
Normal file
|
@ -0,0 +1,318 @@
|
|||
import svg
|
||||
import random
|
||||
|
||||
# rounds to the next biggest even number
|
||||
def roundeven(num):
|
||||
return (num+1)/2*2
|
||||
|
||||
def arrange_in_layer(abin, pwidth, pheight, rot_article=False):
|
||||
# articles are longer than wider
|
||||
# default rotation: width: x-direction
|
||||
# height: y-direction
|
||||
|
||||
layer = list()
|
||||
rest = list()
|
||||
root = {'x': 0, 'y': 0,
|
||||
'width': pwidth, 'height': pheight,
|
||||
'article': None,
|
||||
'down': None,
|
||||
'right': None}
|
||||
|
||||
# traverse the tree until a node is found that is big enough for article
|
||||
# with size width x height and return this node or None if not found
|
||||
def find_node(root, width, height):
|
||||
if root is None:
|
||||
return None
|
||||
elif root['article']:
|
||||
return (find_node(root['right'], width, height)
|
||||
or find_node(root['down'], width, height))
|
||||
elif width <= root['width'] and height <= root['height']:
|
||||
return root
|
||||
else:
|
||||
return None
|
||||
|
||||
# after finding a node where an article fits, put article into the node and
|
||||
# create childnodes
|
||||
def split_node(node, width, height, article):
|
||||
node['article'] = article
|
||||
node['article']['PlacePosition']['X'] = node['x']+width/2
|
||||
node['article']['PlacePosition']['Y'] = node['y']+height/2
|
||||
if node['width'] > 0 and node['height']-height > 0:
|
||||
node['down'] = {'x': node['x'], 'y': node['y']+height,
|
||||
'width': node['width'],
|
||||
'height': node['height']-height,
|
||||
'article': None,
|
||||
'down': None,
|
||||
'right': None}
|
||||
else:
|
||||
node['down'] = None
|
||||
if node['width']-width > 0 and height > 0:
|
||||
node['right'] = {'x': node['x']+width, 'y': node['y'],
|
||||
'width': node['width']-width,
|
||||
'height': height,
|
||||
'article': None,
|
||||
'down': None,
|
||||
'right': None}
|
||||
else:
|
||||
node['right'] = None
|
||||
return node
|
||||
|
||||
# for each article in abin, check and place article at a node. If it doesnt
|
||||
# fit, try to rotate. If it still doesnt fit, append to rest
|
||||
for article in abin:
|
||||
# output format only accepts integer positions, round article sizes up
|
||||
# to even numbers
|
||||
owidth, oheight = article['Article']['Length'], article['Article']['Width']
|
||||
if rot_article:
|
||||
article['Orientation'] = 2
|
||||
width, height = roundeven(oheight), roundeven(owidth)
|
||||
else:
|
||||
article['Orientation'] = 1
|
||||
width, height = roundeven(owidth), roundeven(oheight)
|
||||
|
||||
node = find_node(root, width, height)
|
||||
if (node):
|
||||
node = split_node(node, width, height, article)
|
||||
else:
|
||||
# rotate article
|
||||
# output format only accepts integer positions, round article sizes up
|
||||
# to even numbers
|
||||
if rot_article:
|
||||
article['Orientation'] = 1
|
||||
width, height = roundeven(owidth), roundeven(oheight)
|
||||
else:
|
||||
article['Orientation'] = 2
|
||||
width, height = roundeven(oheight), roundeven(owidth)
|
||||
node = find_node(root, width, height)
|
||||
if (node):
|
||||
node = split_node(node, width, height, article)
|
||||
else:
|
||||
# rotate back
|
||||
if rot_article:
|
||||
article['Orientation'] = 2
|
||||
else:
|
||||
article['Orientation'] = 1
|
||||
rest.append(article)
|
||||
|
||||
# gather all articles that were
|
||||
def find_articles(node):
|
||||
if not node['article']:
|
||||
return
|
||||
layer.append(node['article'])
|
||||
if node['right']:
|
||||
find_articles(node['right'])
|
||||
if node['down']:
|
||||
find_articles(node['down'])
|
||||
|
||||
find_articles(root)
|
||||
|
||||
return root, layer, rest
|
||||
|
||||
# generate a list of random articles of three different type
|
||||
# each type is of the same size and color
|
||||
# numbers of articles of each type linearly depend on their area
|
||||
# articles are generated with more width that height
|
||||
def generate_bin():
|
||||
abin = []
|
||||
for i in 1,2,3:
|
||||
w, h = random.randint(20,150), random.randint(20,150)
|
||||
if h > w:
|
||||
w, h = h, w
|
||||
color = random.randint(0,255), random.randint(0,255), random.randint(0,255)
|
||||
for j in range(200000/(w*h)):
|
||||
abin.append({'x':0, 'y':0, 'width':w, 'height':h, 'color':color})
|
||||
return abin
|
||||
|
||||
# given a node tree with articles inside, spread them out over the full
|
||||
# available area evenly
|
||||
def spread_articles(root):
|
||||
def get_width(article):
|
||||
if article['Orientation'] == 1:
|
||||
return article['Article']['Length']
|
||||
else:
|
||||
return article['Article']['Width']
|
||||
|
||||
def get_height(article):
|
||||
if article['Orientation'] == 1:
|
||||
return article['Article']['Width']
|
||||
else:
|
||||
return article['Article']['Length']
|
||||
|
||||
# get only nodes on the left branch of the tree. This is all nodes below
|
||||
def get_down_nodes(node):
|
||||
if node is None or not node['article']:
|
||||
return []
|
||||
else:
|
||||
return [node] + get_down_nodes(node['down'])
|
||||
|
||||
# move this node and its whole subtree down
|
||||
def move_tree_down(node, y):
|
||||
if not node['article']:
|
||||
return
|
||||
node['article']['PlacePosition']['Y'] += y
|
||||
if node['right']:
|
||||
move_tree_down(node['right'], y)
|
||||
if node['down']:
|
||||
move_tree_down(node['down'], y)
|
||||
|
||||
# for each child on the very left, spread vertically and adjust subtree y
|
||||
# position accordingly
|
||||
def spread_vertically(node):
|
||||
downnodes = get_down_nodes(node)
|
||||
# process innermost nodes before outer nodes
|
||||
for n in downnodes:
|
||||
if n['right']:
|
||||
spread_vertically(n['right'])
|
||||
if len(downnodes) == 0:
|
||||
return
|
||||
elif len(downnodes) == 1:
|
||||
# arrange them in the center of parent
|
||||
# treat the article height as even and round the gap size to the
|
||||
# next smallest even number
|
||||
gap = (node['height']-roundeven(get_height(downnodes[0]['article'])))/4*2
|
||||
move_tree_down(node, gap)
|
||||
else:
|
||||
# get the sum of all heights of the leftmodes articles as if they
|
||||
# had even heights
|
||||
sumdownnodes = sum([roundeven(get_height(n['article'])) for n in downnodes])
|
||||
# do some fancy math to figure out even gap sizes between
|
||||
# the nodes
|
||||
d, m = divmod((node['height']-sumdownnodes)/2, len(downnodes)-1)
|
||||
gaps = (m)*[(d+1)*2]+((len(downnodes)-1)-m)*[d*2]
|
||||
# iteratively move trees down by vgap except for first row
|
||||
for node, gap in zip(downnodes[1:], gaps):
|
||||
move_tree_down(node, gap)
|
||||
|
||||
# for a given node, return a tuple consisting of a list of nodes that
|
||||
# make out the longest row in horizontal direction and a list of nodes that
|
||||
# start a shorter end
|
||||
def get_max_horiz_nodes(node):
|
||||
if node is None or not node['article']:
|
||||
return [], []
|
||||
elif node['down'] and node['down']['article']:
|
||||
# if the node has an article below, check out the rightbranch
|
||||
rightbranch, sr = get_max_horiz_nodes(node['right'])
|
||||
rightbranch = [node] + rightbranch
|
||||
# as well as the down branch
|
||||
downbranch, sd = get_max_horiz_nodes(node['down'])
|
||||
# get information about the last article in each branch
|
||||
ar = rightbranch[len(rightbranch)-1]['article']
|
||||
ad = downbranch[len(downbranch)-1]['article']
|
||||
# and return as the first tuple entry the branch that stretches the
|
||||
# longest while having as the second tuple entry the nodes that
|
||||
# were dismissed as starting shorter branches
|
||||
if ar['PlacePosition']['X']+get_width(ar)/2 > ad['PlacePosition']['X']+get_width(ad)/2:
|
||||
return rightbranch, sr+[downbranch[0]]
|
||||
else:
|
||||
return downbranch, sd+[rightbranch[0]]
|
||||
else:
|
||||
# if there is no article below, just recursively call itself on the
|
||||
# next node to the right
|
||||
rightbranch, short = get_max_horiz_nodes(node['right'])
|
||||
return [node] + rightbranch, short
|
||||
|
||||
# move a node and the article inside to the right and reduce node width
|
||||
# recursively call for children
|
||||
def move_tree_right(node, x):
|
||||
if not node['article']:
|
||||
return
|
||||
node['article']['PlacePosition']['X'] += x
|
||||
node['x'] += x
|
||||
node['width'] -= x
|
||||
if node['right']:
|
||||
move_tree_right(node['right'], x)
|
||||
if node['down']:
|
||||
move_tree_right(node['down'], x)
|
||||
|
||||
# for each child on the very right, spread horizontally and adjust subtree
|
||||
# x position accordingly
|
||||
def spread_horizontally(node):
|
||||
maxhoriznodes, short = get_max_horiz_nodes(node['right'])
|
||||
maxhoriznodes = [node] + maxhoriznodes
|
||||
if len(maxhoriznodes) == 0:
|
||||
return
|
||||
elif len(maxhoriznodes) == 1:
|
||||
# arrange them in the center of parent
|
||||
# treat article width as even and round the gap size to the next
|
||||
# smallest even number
|
||||
gap = (node['width']-roundeven(get_width(maxhoriznodes[0]['article'])))/4*2
|
||||
maxhoriznodes[0]['article']['PlacePosition']['X'] += gap
|
||||
else:
|
||||
# get the sum of all widths of the articles that make the longest
|
||||
# row of articles as if they had even widths
|
||||
summaxhoriznodes= sum([roundeven(get_width(n['article'])) for n in maxhoriznodes])
|
||||
# do some fancy math to figure out even gap sizes between the nodes
|
||||
d, m = divmod((node['width']-summaxhoriznodes)/2, len(maxhoriznodes)-1)
|
||||
gaps = (m)*[(d+1)*2]+((len(maxhoriznodes)-1)-m)*[d*2]
|
||||
# iteratively move trees right by hgap except for first node
|
||||
for node, gap in zip(maxhoriznodes[1:], gaps):
|
||||
move_tree_right(node, gap)
|
||||
# recursively call for all nodes starting a shorter subtree
|
||||
for node in short:
|
||||
spread_horizontally(node)
|
||||
|
||||
# spread nodes vertically
|
||||
spread_vertically(root)
|
||||
|
||||
# and horizontally
|
||||
for node in get_down_nodes(root):
|
||||
spread_horizontally(node)
|
||||
|
||||
# sanity checks
|
||||
def sanity_check(layer):
|
||||
def intersects(a1, a2):
|
||||
return (a1['x'] < a2['x']+a2['width']
|
||||
and a1['x']+a1['width'] > a2['x']
|
||||
and a1['y'] < a2['y']+a2['height']
|
||||
and a1['y']+a1['height'] > a2['y'])
|
||||
odds = list()
|
||||
overhangs = list()
|
||||
inters = list()
|
||||
for article1 in layer:
|
||||
if (article1['x']%2 != 0
|
||||
or article1['y']%2 != 0):
|
||||
odds.append(article1)
|
||||
if (article1['x'] < 0
|
||||
or article1['y'] < 0
|
||||
or article1['x']+article1['width'] > pwidth
|
||||
or article1['y']+article1['height'] > pheight):
|
||||
overhangs.append(article1)
|
||||
for article2 in layer:
|
||||
if article1 == article2:
|
||||
continue
|
||||
if intersects(article1, article2):
|
||||
inters.append((article1, article2))
|
||||
for odd in odds:
|
||||
print "odd:", odd
|
||||
for overhang in overhangs:
|
||||
print "overhang:", overhang
|
||||
for inter in inters:
|
||||
print "intersect:", inter
|
||||
if len(odds) or len(overhangs) or len(inters):
|
||||
print layer
|
||||
exit(1)
|
||||
|
||||
# draw layer of articles
|
||||
def draw_layer(filename, layer):
|
||||
scene = svg.Scene(filename, (pwidth, pheight))
|
||||
for a in layer:
|
||||
scene.add(svg.Rectangle((a['x'], a['y']),(a['width'], a['height']),a['color']))
|
||||
scene.write()
|
||||
|
||||
# return all articles in a node tree
|
||||
def find_articles(node):
|
||||
if node is None or not node['article']:
|
||||
return []
|
||||
else:
|
||||
return [node['article']] + find_articles(node['right']) + find_articles(node['down'])
|
||||
|
||||
if __name__ == "__main__":
|
||||
abin = generate_bin()
|
||||
pwidth, pheight = 800, 600
|
||||
abin = sorted(abin, key=lambda article: article['width']*article['height'], reverse=True)
|
||||
root, layer, rest = arrange_in_layer(abin, pwidth, pheight)
|
||||
draw_layer('test1', layer)
|
||||
spread_articles(root)
|
||||
layer = find_articles(root)
|
||||
draw_layer('test2', layer)
|
||||
sanity_check(layer)
|
79
bruteforce2.py
Normal file
79
bruteforce2.py
Normal file
|
@ -0,0 +1,79 @@
|
|||
import sys
|
||||
import subprocess
|
||||
import itertools
|
||||
import shutil
|
||||
from util import xmlfiletodict, dicttoxmlfile, get_pallet, get_articles, get_packlist_dict
|
||||
from arrange_spread2 import arrange_in_layer, spread_articles, find_articles
|
||||
import cPickle
|
||||
from binascii import b2a_base64
|
||||
|
||||
def get_layers(bins, pallet, rot_article=False, rot_pallet=False):
|
||||
for abin in bins:
|
||||
bins[abin] = sorted(bins[abin], key=lambda article: article['Article']['Length']*article['Article']['Width'], reverse=True)
|
||||
plength, pwidth = (pallet['Dimensions']['Length'], pallet['Dimensions']['Width'])
|
||||
root, layer, rest = arrange_in_layer(bins[abin], plength, pwidth, rot_article=rot_article)
|
||||
while layer:
|
||||
spread_articles(root)
|
||||
|
||||
occupied_area = 0
|
||||
for article in layer:
|
||||
length, width = article['Article']['Length'], article['Article']['Width']
|
||||
occupied_area += length*width
|
||||
|
||||
# print "layer occupation:", occupied_area/float(plength*pwidth)
|
||||
if occupied_area/float(plength*pwidth) <= 0.7:
|
||||
rot_article, rot_pallet = (yield None, layer)
|
||||
else:
|
||||
rot_article, rot_pallet = (yield layer, None)
|
||||
|
||||
root, layer, rest = arrange_in_layer(rest, plength, pwidth, rot_article=rot_article)
|
||||
|
||||
def main():
|
||||
if len(sys.argv) != 3:
|
||||
print "usage:", sys.argv[0], "order.xml packlist.xml"
|
||||
exit(1)
|
||||
|
||||
orderline = xmlfiletodict(sys.argv[1])
|
||||
pallet = get_pallet(orderline)
|
||||
articles = get_articles(orderline)
|
||||
bins = dict()
|
||||
|
||||
for article in articles:
|
||||
abin = bins.get(article['Article']['Height'])
|
||||
if abin:
|
||||
abin.append(article)
|
||||
else:
|
||||
bins[article['Article']['Height']] = [article]
|
||||
|
||||
scores = list()
|
||||
|
||||
stuff1 = list()
|
||||
|
||||
#for order in itertools.product([True, False], repeat=12):
|
||||
for order in [[True]*12,]:
|
||||
rests = list()
|
||||
layers = list()
|
||||
|
||||
it = get_layers(bins, pallet, order[0], False)
|
||||
layer, rest = it.next()
|
||||
if layer:
|
||||
layers.append(layer)
|
||||
if rest:
|
||||
rests.append(rest)
|
||||
|
||||
fail = True
|
||||
for rot_article in order[1:]:
|
||||
try:
|
||||
layer, rest = it.send((rot_article, False))
|
||||
if layer:
|
||||
layers.append(layer)
|
||||
if rest:
|
||||
rests.append(rest)
|
||||
except StopIteration:
|
||||
fail = False
|
||||
break
|
||||
if fail:
|
||||
raise Exception("finished early")
|
||||
print b2a_base64(cPickle.dumps((layers, rests, pallet))),
|
||||
if __name__ == "__main__":
|
||||
main()
|
81
bruteforce3.py
Normal file
81
bruteforce3.py
Normal file
|
@ -0,0 +1,81 @@
|
|||
import sys
|
||||
import subprocess
|
||||
import itertools
|
||||
import shutil
|
||||
from util import xmlfiletodict, dicttoxmlfile, get_pallet, get_articles, get_packlist_dict
|
||||
from arrange_spread2 import arrange_in_layer, spread_articles, find_articles
|
||||
import cPickle
|
||||
import marshal
|
||||
from binascii import a2b_base64
|
||||
import tempfile
|
||||
import os
|
||||
|
||||
def evaluate_layers_rests(layers, rests, scores, pallet):
|
||||
rest_layers = list()
|
||||
# sort rests by space they cover and move them to the center of the pile
|
||||
# append them to the layer list
|
||||
for rest in sorted(rests, key=lambda rest: sum([article['Article']['Length']*article['Article']['Width'] for article in rest]), reverse=True):
|
||||
plength, pwidth = (pallet['Dimensions']['Length'], pallet['Dimensions']['Width'])
|
||||
root, layer, rest = arrange_in_layer(rest, plength, pwidth)
|
||||
|
||||
com_x = 0
|
||||
com_y = 0
|
||||
for article in layer:
|
||||
com_x += article['PlacePosition']['X']
|
||||
com_y += article['PlacePosition']['Y']
|
||||
com_x, com_y = com_x/len(layer), com_y/len(layer)
|
||||
|
||||
diff_x, diff_y = plength*0.5-com_x, pwidth*0.5-com_y
|
||||
|
||||
for article in layer:
|
||||
article['PlacePosition']['X'] += diff_x
|
||||
article['PlacePosition']['Y'] += diff_y
|
||||
|
||||
rest_layers.append(layer)
|
||||
|
||||
for permut_layers in itertools.permutations(layers):
|
||||
pack_sequence = 1
|
||||
pack_height = 0
|
||||
articles_to_pack = list()
|
||||
|
||||
for layer in list(permut_layers)+rest_layers:
|
||||
pack_height += layer[0]['Article']['Height']
|
||||
#if pack_height > pallet['Dimensions']['MaxLoadHeight']:
|
||||
# break
|
||||
for article in layer:
|
||||
article['PackSequence'] = pack_sequence
|
||||
article['PlacePosition']['Z'] = pack_height
|
||||
articles_to_pack.append(article)
|
||||
pack_sequence += 1
|
||||
|
||||
packlist = get_packlist_dict(pallet, articles_to_pack)
|
||||
|
||||
_, tmp = tempfile.mkstemp()
|
||||
dicttoxmlfile(packlist, tmp)
|
||||
|
||||
# ugly, ugly, ugly, ugly hack - dont copy this...
|
||||
score = float(subprocess.check_output("../palletandtruckviewer-3.0/palletViewer -o "
|
||||
+sys.argv[1]+" -p "+tmp
|
||||
+" -s ../icra2011TestFiles/scoreAsPlannedConfig1.xml --headless | grep Score", shell=True).split(' ')[1].strip())
|
||||
scores.append(score)
|
||||
if score > max(scores+[0]):
|
||||
shutil.move(tmp, sys.argv[2])
|
||||
else:
|
||||
os.remove(tmp)
|
||||
|
||||
def main():
|
||||
scores = list()
|
||||
for arg in sys.argv[3:]:
|
||||
layers, rests, pallet = cPickle.loads(a2b_base64(arg))
|
||||
evaluate_layers_rests(layers, rests, scores, pallet)
|
||||
|
||||
print max(scores)
|
||||
#print "max:", max(scores)
|
||||
#print "min:", min(scores)
|
||||
#mean = sum(scores)/len(scores)
|
||||
#print "mean:", mean
|
||||
#from math import sqrt
|
||||
#print "stddev:", sqrt(sum([(x-mean)**2 for x in scores])/len(scores))
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
42
svg.py
Normal file
42
svg.py
Normal file
|
@ -0,0 +1,42 @@
|
|||
import os
|
||||
|
||||
class Scene:
|
||||
def __init__(self, name, size):
|
||||
self.name = name
|
||||
self.items = []
|
||||
self.size = size
|
||||
|
||||
def add(self, item):
|
||||
self.items.append(item)
|
||||
|
||||
def svgstr(self):
|
||||
svgstr = "<?xml version=\"1.0\"?>\n"
|
||||
svgstr += "<svg width=\"%d\" height=\"%d\">\n"%self.size
|
||||
svgstr += " <g style=\"fill-opacity:1.0; stroke:black; stroke-width:1;\">\n"
|
||||
for item in self.items:
|
||||
svgstr += item.svgstr()
|
||||
svgstr += " </g>\n</svg>\n"
|
||||
return svgstr
|
||||
|
||||
def write(self, filename=None):
|
||||
if not filename:
|
||||
filename = self.name + ".svg"
|
||||
with open(filename, "w") as f:
|
||||
f.write(self.svgstr())
|
||||
|
||||
class Rectangle:
|
||||
def __init__(self, pos, size, color):
|
||||
self.pos = pos
|
||||
self.size = size
|
||||
self.color = color
|
||||
|
||||
def svgstr(self):
|
||||
svgstr = " <rect x=\"%d\" y=\"%d\" "%self.pos
|
||||
svgstr += "width=\"%d\" height=\"%d\" "%self.size
|
||||
svgstr += "style=\"fill:#%02x%02x%02x;\"/>\n"%self.color
|
||||
return svgstr
|
||||
|
||||
if __name__ == "__main__":
|
||||
scene = Scene('test', (400, 400))
|
||||
scene.add(Rectangle((0,0),(100,100),(255,0,0)))
|
||||
scene.write()
|
197
util.py
Normal file
197
util.py
Normal file
|
@ -0,0 +1,197 @@
|
|||
from xml.etree import ElementTree
|
||||
|
||||
def xmltodict(element):
|
||||
if not isinstance(element, ElementTree.Element):
|
||||
raise ValueError("must pass xml.etree.ElementTree.Element object")
|
||||
|
||||
def xmltodict_handler(parent_element):
|
||||
result = dict()
|
||||
for element in parent_element:
|
||||
if len(element):
|
||||
obj = xmltodict_handler(element)
|
||||
else:
|
||||
obj = element.text
|
||||
|
||||
if result.get(element.tag):
|
||||
if hasattr(result[element.tag], "append"):
|
||||
result[element.tag].append(obj)
|
||||
else:
|
||||
result[element.tag] = [result[element.tag], obj]
|
||||
else:
|
||||
result[element.tag] = obj
|
||||
return result
|
||||
|
||||
return {element.tag: xmltodict_handler(element)}
|
||||
|
||||
|
||||
def dicttoxml(element):
|
||||
if not isinstance(element, dict):
|
||||
raise ValueError("must pass dict type")
|
||||
if len(element) != 1:
|
||||
raise ValueError("dict must have exactly one root key")
|
||||
|
||||
def dicttoxml_handler(result, key, value):
|
||||
if isinstance(value, list):
|
||||
for e in value:
|
||||
dicttoxml_handler(result, key, e)
|
||||
elif isinstance(value, basestring):
|
||||
elem = ElementTree.Element(key)
|
||||
elem.text = value
|
||||
result.append(elem)
|
||||
elif isinstance(value, int) or isinstance(value, float):
|
||||
elem = ElementTree.Element(key)
|
||||
elem.text = str(value)
|
||||
result.append(elem)
|
||||
elif value is None:
|
||||
result.append(ElementTree.Element(key))
|
||||
else:
|
||||
res = ElementTree.Element(key)
|
||||
for k, v in value.items():
|
||||
dicttoxml_handler(res, k, v)
|
||||
result.append(res)
|
||||
|
||||
result = ElementTree.Element(element.keys()[0])
|
||||
for key, value in element[element.keys()[0]].items():
|
||||
dicttoxml_handler(result, key, value)
|
||||
return result
|
||||
|
||||
def xmlfiletodict(filename):
|
||||
return xmltodict(ElementTree.parse(filename).getroot())
|
||||
|
||||
def dicttoxmlfile(element, filename):
|
||||
ElementTree.ElementTree(dicttoxml(element)).write(filename)
|
||||
|
||||
def xmlstringtodict(xmlstring):
|
||||
return xmltodict(ElementTree.fromstring(xmlstring).getroot())
|
||||
|
||||
def dicttoxmlstring(element):
|
||||
return ElementTree.tostring(dicttoxml(element))
|
||||
|
||||
def get_pallet(orderline):
|
||||
p = orderline['Message']['PalletInit']['Pallets']['Pallet']
|
||||
return {
|
||||
'PalletNumber': int(p['PalletNumber']),
|
||||
'Description': p['Description'],
|
||||
'Dimensions': {
|
||||
'MaxLoadHeight': int(p['Dimensions']['MaxLoadHeight']),
|
||||
'MaxLoadWeight': int(p['Dimensions']['MaxLoadWeight']),
|
||||
'Length': int(p['Dimensions']['Length']),
|
||||
'Width': int(p['Dimensions']['Width']),
|
||||
}
|
||||
}
|
||||
|
||||
def get_articles(orderline):
|
||||
articles = list()
|
||||
for o in orderline['Message']['Order']['OrderLines']['OrderLine']:
|
||||
for barcode in o['Barcodes']['Barcode']:
|
||||
articles.append(
|
||||
{'ApproachPoint1': {'X': 0, 'Y': 0, 'Z': 0},
|
||||
'ApproachPoint2': {'X': 0, 'Y': 0, 'Z': 0},
|
||||
'ApproachPoint3': {'X': 0, 'Y': 0, 'Z': 0},
|
||||
'Article': { 'Description': o['Article']['Description'],
|
||||
'ID': int(o['Article']['ID']),
|
||||
'Type': int(o['Article']['Type']), # currently only Type=1 is allowed
|
||||
'Family': int(o['Article']['Family']),
|
||||
'Length': int(o['Article']['Length']), # should be larger than width
|
||||
'Width': int(o['Article']['Width']),
|
||||
'Height': int(o['Article']['Height']),
|
||||
'Weight': int(o['Article']['Weight']) # in grams
|
||||
},
|
||||
'Barcode': barcode,
|
||||
'Orientation': 1, # 1: 0 deg the long side parallel to X direction
|
||||
# 2: 90 deg the long side parallel to Y direction
|
||||
'PackSequence': 0,
|
||||
'PlacePosition': {'X': 0, 'Y': 0, 'Z': 0}
|
||||
}
|
||||
)
|
||||
return articles
|
||||
|
||||
def get_packlist_dict(pallet, articles):
|
||||
pallet['Packages'] = {'Package': articles}
|
||||
return {'Response':
|
||||
{'PackList':
|
||||
{'OrderID': '1',
|
||||
'PackPallets':
|
||||
{'PackPallet': pallet }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if __name__ == "__main__":
|
||||
tree = ElementTree.parse('../icra2011TestFiles/GT/gt_d1r1.wpacklist.xml')
|
||||
#tree = ElementTree.parse('../icra2011TestFiles/palDay1R1Order.xml')
|
||||
root = tree.getroot()
|
||||
xmldict = xmltodict(root)
|
||||
|
||||
from pprint import pprint
|
||||
#for package in xmldict['PackList']['PackPallets']['PackPallet']['Packages']['Package']:
|
||||
# pprint(package)
|
||||
|
||||
|
||||
root = dicttoxml(xmldict)
|
||||
|
||||
xmldict = xmltodict(root)
|
||||
pprint(xmldict)
|
||||
|
||||
packages = [{'ApproachPoint1': {'X': '0',
|
||||
'Y': '0',
|
||||
'Z': '0'},
|
||||
'ApproachPoint2': {'X': '0',
|
||||
'Y': '0',
|
||||
'Z': '0'},
|
||||
'ApproachPoint3': {'X': '0',
|
||||
'Y': '0',
|
||||
'Z': '0'},
|
||||
'Article': {'Description': '3',
|
||||
'Family': '0',
|
||||
'Height': '41',
|
||||
'ID': '3',
|
||||
'Length': '44',
|
||||
'Type': '0',
|
||||
'Weight': '500',
|
||||
'Width': '132'},
|
||||
'Barcode': None,
|
||||
'Orientation': '1',
|
||||
'PackSequence': '1',
|
||||
'PlacePosition': {'X': '286',
|
||||
'Y': '330',
|
||||
'Z': '41'},
|
||||
'StackHeightBefore': '0'},
|
||||
{'ApproachPoint1': {'X': '0',
|
||||
'Y': '0',
|
||||
'Z': '0'},
|
||||
'ApproachPoint2': {'X': '0',
|
||||
'Y': '0',
|
||||
'Z': '0'},
|
||||
'ApproachPoint3': {'X': '0',
|
||||
'Y': '0',
|
||||
'Z': '0'},
|
||||
'Article': {'Description': '4',
|
||||
'Family': '0',
|
||||
'Height': '41',
|
||||
'ID': '4',
|
||||
'Length': '66',
|
||||
'Type': '0',
|
||||
'Weight': '550',
|
||||
'Width': '132'},
|
||||
'Barcode': None,
|
||||
'Orientation': '1',
|
||||
'PackSequence': '54',
|
||||
'PlacePosition': {'X': '33',
|
||||
'Y': '66',
|
||||
'Z': '164'},
|
||||
'StackHeightBefore': '0'}]
|
||||
|
||||
packlist = {'Response': {'PackList': {'OrderID': '1',
|
||||
'PackPallets': {'PackPallet': {'BruttoWeight': '63000',
|
||||
'Description': None,
|
||||
'Dimensions': {'Length': '308',
|
||||
'MaxLoadHeight': '406',
|
||||
'MaxLoadWeight': '99999',
|
||||
'Width': '396'},
|
||||
'NumberofPackages': '54',
|
||||
'Overhang': {'Length': '0',
|
||||
'Width': '0'},
|
||||
'Packages': {'Package': packages},
|
||||
'PalletNumber': '1'}}}}}
|
||||
|
Loading…
Reference in a new issue