forked from Xiong5Heng/GOPT
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
422189e
commit b7ab5f9
Showing
107 changed files
with
16,119 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
/logs/ | ||
/.idea/ | ||
*.pyc | ||
*.csv | ||
logs | ||
log | ||
.vscode |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,81 @@ | ||
# GOPT | ||
The code is under preparation and is coming soon. | ||
<h2 align="center"> | ||
<b>GOPT: Generalizable Online 3D Bin Packing via Transformer-based Deep Reinforcement Learning</b> | ||
|
||
<b><i>RA-L 2024 (Accepted)</i></b> | ||
|
||
<div align="center"> | ||
<a href="https://ieeexplore.ieee.org/abstract/document/10694688" target="_blank"> | ||
<img src="https://img.shields.io/badge/ieee-%2300629B.svg?&style=for-the-badge&logo=ieee&logoColor=white"></a> | ||
<a href="https://arxiv.org/abs/2409.05344" target="_blank"> | ||
<img src="https://img.shields.io/badge/arxiv-%23B31B1B.svg?&style=for-the-badge&logo=arxiv&logoColor=white" alt="Paper arXiv"></a> | ||
</div> | ||
|
||
</h2> | ||
|
||
If you have any questions, feel free to contact me by [email protected]. | ||
|
||
## Introduction | ||
Robotic object packing has broad practical applications in the logistics and automation industry, often formulated by researchers as the online 3D Bin Packing Problem (3D-BPP). However, existing DRL-based methods primarily focus on enhancing performance in limited packing environments while neglecting the ability to generalize across multiple environments characterized by different bin dimensions. To this end, we propose GOPT, a generalizable online 3D Bin Packing approach via Transformer-based deep reinforcement learning (DRL). First, we design a Placement Generator module to yield finite subspaces as placement candidates and the representation of the bin. Second, we propose a Packing Transformer, which fuses the features of the items and bin, to identify the spatial correlation between the item to be packed and available sub-spaces within the bin. Coupling these two components enables GOPT’s ability to perform inference on bins of varying dimensions. | ||
|
||
![overview](./images/overview.png) | ||
|
||
|
||
## Installation | ||
This code has been tested on Ubuntu 20.04 with Cuda 12.1, Python3.9 and Pytorch 2.1.0. | ||
|
||
``` | ||
git clone https://github.com/Xiong5Heng/GOPT.git | ||
cd GOPT | ||
conda create -n GOPT python=3.9 | ||
conda activate GOPT | ||
# install pytorch | ||
conda install pytorch==2.1.0 torchvision==0.16.0 torchaudio==2.1.0 pytorch-cuda=12.1 -c pytorch -c nvidia | ||
# install other dependencies | ||
pip install -r requirements.txt | ||
``` | ||
|
||
## Training | ||
The dataset is generated on the fly, so you can directly train the model by running the following command. | ||
|
||
```bash | ||
python train.py --config cfg/config.yaml --device 0 | ||
``` | ||
|
||
If you do not use the default dataset (the bin is 10x10x10), you can modify the tag `env` in `cfg/config.yaml` file to specify the bin size and the number of items. | ||
Note that most hyperparameters are in the `cfg/config.yaml` file, you can modify them to fit your needs. | ||
|
||
|
||
## Evaluation | ||
|
||
```bash | ||
python eval.py --config cfg/config.yaml --device 0 --ckp /path/to/checkpoint.pth | ||
``` | ||
|
||
If you want to visualize the packing process, you can add the `--render` flag. | ||
```bash | ||
python eval.py --config cfg/config.yaml --device 0 --ckp /path/to/checkpoint.pth --render | ||
``` | ||
|
||
## Demo | ||
<!-- ![demo](./images/demo.gif) --> | ||
<div align="center"> | ||
<img src="./images/demo.gif" alt="A simple demo" width="400"> | ||
</div> | ||
|
||
## Citation | ||
If you find this work useful, please consider citing: | ||
``` | ||
@article{xiong2024gopt, | ||
title={GOPT: Generalizable Online 3D Bin Packing via Transformer-based Deep Reinforcement Learning}, | ||
author={Xiong, Heng and Guo, Changrong and Peng, Jian and Ding, Kai and Chen, Wenjie and Qiu, Xuchong and Bai, Long and Xu, Jianfeng}, | ||
journal={IEEE Robotics and Automation Letters}, | ||
year={2024}, | ||
publisher={IEEE} | ||
} | ||
``` | ||
|
||
## License | ||
This source code is released only for academic use. Please do not use it for commercial purposes without authorization of the author. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
import os | ||
curr_path = os.path.dirname(os.path.abspath(__file__)) | ||
|
||
import argparse | ||
|
||
from omegaconf import OmegaConf | ||
|
||
|
||
def get_args(): | ||
parser = argparse.ArgumentParser() | ||
parser.add_argument('--config', type=str, default="cfg/config.yaml") | ||
parser.add_argument('--ckp', type=str, default=None, | ||
help="Path to the model to be tested") | ||
parser.add_argument('--no-cuda', action='store_true', | ||
help='Cuda will be enabled by default') | ||
parser.add_argument('--device', type=int, default=0, | ||
help='Which GPU will be called') | ||
parser.add_argument('--test-episode', type=int, default=1000, | ||
help='Number of episodes for evaluation') | ||
parser.add_argument('--render', action='store_true', | ||
help='Render the environment while testing') | ||
|
||
args = parser.parse_args() | ||
|
||
try: | ||
args.config = os.path.join(curr_path, args.config) | ||
cfg = OmegaConf.load(args.config) | ||
except FileNotFoundError: | ||
print("No configuration file found") | ||
|
||
box_small = int(max(cfg.env.container_size) / 10) | ||
box_big = int(max(cfg.env.container_size) / 2) | ||
# box_range = (5, 5, 5, 25, 25, 25) | ||
box_range = (box_small, box_small, box_small, box_big, box_big, box_big) | ||
|
||
if cfg.get("env.step") is not None: | ||
step = cfg.env.step | ||
else: | ||
step = box_small | ||
|
||
box_size_set = [] | ||
for i in range(box_range[0], box_range[3] + 1, step): | ||
for j in range(box_range[1], box_range[4] + 1, step): | ||
for k in range(box_range[2], box_range[5] + 1, step): | ||
box_size_set.append((i, j, k)) | ||
|
||
cfg.env.box_small = box_small | ||
cfg.env.box_big = box_big | ||
cfg.env.box_size_set = box_size_set | ||
cfg.cuda = not args.no_cuda | ||
|
||
cfg = OmegaConf.merge(cfg, vars(args)) | ||
|
||
return cfg | ||
|
||
|
||
if __name__ == "__main__": | ||
args = get_args() | ||
print(args.train.reward_type) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
# configuration file for training | ||
|
||
seed: 5 | ||
cuda_deterministic: True | ||
log_interval: 10 # How often to print training logs | ||
|
||
env: | ||
id: OnlinePack-v1 # env name OnlinePack-v1, PCT-v0 | ||
scheme: EMS # the scheme of generating candidate map: heightmap, EP, FC | ||
rot: True | ||
box_type: random # random, cut | ||
container_size: [10, 10, 10] | ||
step: | ||
k_placement: 80 # number of candidate placements | ||
|
||
|
||
train: | ||
algo: PPO | ||
clip_param: 0.3 | ||
num_processes: 2 # the number of subprogresses, if debug, set to 1 | ||
num_steps: 5 | ||
epoch: 1000 | ||
last_epoch: 200 | ||
batch_size: 128 | ||
step_per_epoch: 40000 # 2**15 | ||
repeat_per_collect: 1 | ||
gae_lambda: 0.96 | ||
reward_type: # optional: "terminal", None | ||
gamma: 1 # discount factor for rewards (default: 1) | ||
|
||
opt: # optimizer | ||
optimizer: Adam # optimizer: Adam, RMSprop | ||
lr: 7e-5 # learning rate (RMSprop7e-4, 1e-6, Adam7e-5) | ||
lr_decay: True # use a linear schedule on the learning rate | ||
eps: 1e-5 # epsilon (default: 1e-5) | ||
alpha: 0.99 # RMSprop alpha (default: 0.99) | ||
|
||
loss: | ||
entropy: 0.001 # entropy term coefficient (default: 0.01) | ||
value: 0.5 # value loss coefficient (default: 0.5) | ||
|
||
model: | ||
padding_mask: False # padding mask | ||
embed_dim: 128 | ||
heads: 1 | ||
num_layers: 3 | ||
forward_expansion: 2 | ||
dropout: 0 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
# configuration file for training | ||
|
||
seed: 5 | ||
cuda_deterministic: True | ||
log_interval: 10 # How often to print training logs | ||
|
||
env: | ||
id: OnlinePack-v1 # env name | ||
scheme: EMS # the scheme of generating candidate map: heightmap, EP, FC | ||
rot: True | ||
box_type: random | ||
container_size: [10, 10, 10] | ||
k_placement: 100 # number of candidate placements | ||
|
||
|
||
train: | ||
algo: PPO | ||
clip_param: 0.3 | ||
num_processes: 128 | ||
num_steps: 6 | ||
epoch: 500 | ||
batch_size: 128 | ||
step_per_epoch: 32768 # 2**15 | ||
repeat_per_collect: 1 | ||
gae_lambda: 0.96 | ||
reward_type: # optional: "terminal", None | ||
gamma: 1 # discount factor for rewards (default: 1) | ||
|
||
opt: # optimizer | ||
optimizer: Adam # optimizer: Adam, RMSprop | ||
lr: 7e-5 # learning rate (RMSprop7e-4, 1e-6, Adam7e-5) | ||
lr_decay: False # use a linear schedule on the learning rate | ||
eps: 1e-5 # epsilon (default: 1e-5) | ||
alpha: 0.99 # RMSprop alpha (default: 0.99) | ||
|
||
loss: | ||
entropy: 0.001 # entropy term coefficient (default: 0.01) | ||
value: 0.5 # value loss coefficient (default: 0.5) | ||
|
||
model: | ||
embed_dim: 128 | ||
heads: 1 | ||
num_layers: 4 | ||
forward_expansion: 2 | ||
dropout: 0 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
# -*- coding: utf-8 -*- | ||
""" | ||
------------------------------------------------- | ||
Project Name: Packing-RL | ||
File Name: __init__.py.py | ||
Author: XEH1SGH | ||
Create Date: 4/14/2022 | ||
------------------------------------------------- | ||
""" | ||
# from gym.envs.registration import register | ||
# from packing_env import PackingGame | ||
# | ||
# register( | ||
# id='Pack-v0', | ||
# entry_point='problems.OnlinePacking:PackingGame', | ||
# ) | ||
from .env import PackingEnv | ||
|
||
__version__ = "0.0.1" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
import numpy as np | ||
import copy | ||
import torch | ||
|
||
|
||
class BoxCreator(object): | ||
def __init__(self): | ||
self.box_list = [] # generated box list | ||
|
||
def reset(self): | ||
self.box_list.clear() | ||
|
||
def generate_box_size(self, **kwargs): | ||
pass | ||
|
||
def preview(self, length): | ||
""" | ||
:param length: | ||
:return: list | ||
""" | ||
while len(self.box_list) < length: | ||
self.generate_box_size() | ||
return copy.deepcopy(self.box_list[:length]) | ||
|
||
def drop_box(self): | ||
assert len(self.box_list) >= 0 | ||
self.box_list.pop(0) | ||
|
||
|
||
class RandomBoxCreator(BoxCreator): | ||
default_box_set = [] | ||
for i in range(4): | ||
for j in range(4): | ||
for k in range(4): | ||
default_box_set.append((2 + i, 2 + j, 2 + k)) | ||
|
||
def __init__(self, box_size_set=None): | ||
super().__init__() | ||
self.box_set = box_size_set | ||
if self.box_set is None: | ||
self.box_set = RandomBoxCreator.default_box_set | ||
# print(self.box_set) | ||
|
||
def generate_box_size(self, **kwargs): | ||
idx = np.random.randint(0, len(self.box_set)) | ||
self.box_list.append(self.box_set[idx]) | ||
|
||
|
||
# load data | ||
class LoadBoxCreator(BoxCreator): | ||
def __init__(self, data_name=None): # data url | ||
super().__init__() | ||
self.data_name = data_name | ||
self.index = 0 | ||
self.box_index = 0 | ||
self.traj_nums = len(torch.load(self.data_name)) | ||
print("load data set successfully, data name: ", self.data_name) | ||
|
||
def reset(self, index=None): | ||
self.box_list.clear() | ||
box_trajs = torch.load(self.data_name) | ||
self.recorder = [] | ||
if index is None: | ||
self.index += 1 | ||
else: | ||
self.index = index | ||
self.boxes = box_trajs[self.index] | ||
self.box_index = 0 | ||
self.box_set = self.boxes | ||
self.box_set.append([10, 10, 10]) | ||
|
||
def generate_box_size(self, **kwargs): | ||
if self.box_index < len(self.box_set): | ||
self.box_list.append(self.box_set[self.box_index]) | ||
self.recorder.append(self.box_set[self.box_index]) | ||
self.box_index += 1 | ||
else: | ||
self.box_list.append((10, 10, 10)) | ||
self.recorder.append((10, 10, 10)) | ||
self.box_index += 1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
|
||
class Box(object): | ||
def __init__(self, length, width, height, x, y, z): | ||
# dimension(x, y, z) + position(lx, ly, lz) | ||
self.size_x = length | ||
self.size_y = width | ||
self.size_z = height | ||
self.pos_x = x | ||
self.pos_y = y | ||
self.pos_z = z | ||
|
||
def standardize(self): | ||
""" | ||
Returns: | ||
tuple(size + position) | ||
""" | ||
return tuple([self.size_x, self.size_y, self.size_z, self.pos_x, self.pos_y, self.pos_z]) |
Oops, something went wrong.