diff --git a/.gitignore b/.gitignore index b7faf40..6c3fe86 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,9 @@ __pycache__/ *.py[codz] *$py.class +# env setup script +setup.sh + # C extensions *.so diff --git a/README.md b/README.md index f34ba2f..2c9066e 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,2 @@ # robotvision -Machine Learning @ Purdue - Robot Vision Team (2025-2026 +Machine Learning @ Purdue - Robot Vision Team (2025-2026) diff --git a/copy_lol.py b/copy_lol.py new file mode 100644 index 0000000..f0509ad --- /dev/null +++ b/copy_lol.py @@ -0,0 +1,13 @@ +import shutil +import time +import os +DATA_DIR = '/scratch/gilbreth/bnamikas/data/waymo_open_dataset_end_to_end_camera_v_1_0_0/training_202504031202_202504151040.tfrecord-00111-of-00263' +DEST = '/tmp/cache/' +if not os.path.exists(DEST): + os.mkdir(DEST) +start=time.time() +try: + shutil.copy(DATA_DIR, DEST) +except FileExistsError as e: + pass +print('Total time', time.time()-start) \ No newline at end of file diff --git a/dataloader.ipynb b/dataloader.ipynb new file mode 100644 index 0000000..47a78af --- /dev/null +++ b/dataloader.ipynb @@ -0,0 +1,331 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "fd8ca1e7", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + " 6%|▌ | 15/263 [02:22<39:09, 9.47s/it] \n" + ] + }, + { + "ename": "KeyboardInterrupt", + "evalue": "", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[10], line 24\u001b[0m\n\u001b[1;32m 22\u001b[0m \u001b[38;5;28;01mbreak\u001b[39;00m\n\u001b[1;32m 23\u001b[0m proto_len \u001b[38;5;241m=\u001b[39m struct\u001b[38;5;241m.\u001b[39munpack(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mq\u001b[39m\u001b[38;5;124m'\u001b[39m, blenth)[\u001b[38;5;241m0\u001b[39m]\n\u001b[0;32m---> 24\u001b[0m \u001b[43mfile\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mread\u001b[49m\u001b[43m(\u001b[49m\u001b[43mproto_len\u001b[49m\u001b[38;5;241;43m+\u001b[39;49m\u001b[38;5;241;43m8\u001b[39;49m\u001b[43m)\u001b[49m\n\u001b[1;32m 26\u001b[0m indexes\u001b[38;5;241m.\u001b[39mappend((fn, file\u001b[38;5;241m.\u001b[39mtell()))\n\u001b[1;32m 27\u001b[0m time\u001b[38;5;241m.\u001b[39msleep(\u001b[38;5;241m1\u001b[39m)\n", + "\u001b[0;31mKeyboardInterrupt\u001b[0m: " + ] + } + ], + "source": [ + "should_index = True\n", + "if should_index: # Takes approx. 9 mins to index\n", + " import os\n", + " import mmap\n", + " import struct\n", + " import time\n", + " import pickle\n", + " from tqdm import tqdm\n", + "\n", + " DATA_DIR = '/scratch/gilbreth/bnamikas/data/waymo_open_dataset_end_to_end_camera_v_1_0_0'\n", + "\n", + " indexes = []\n", + "\n", + " start = time.time()\n", + " for i, fn in enumerate(tqdm([file for file in os.listdir(DATA_DIR) if '.tfrecord' in file and file.startswith('train')])):\n", + " with open(os.path.join(DATA_DIR, fn), 'rb') as file:\n", + " indexes.append((fn, file.tell()))\n", + " while True:\n", + " blenth = file.read(8)\n", + " if len(blenth) == 0:\n", + " indexes.pop(-1)\n", + " break\n", + " proto_len = struct.unpack('q', blenth)[0]\n", + " file.read(proto_len+8)\n", + "\n", + " indexes.append((fn, file.tell()))\n", + "\n", + " with open('index.pkl', 'wb') as f:\n", + " pickle.dump(indexes, f)\n", + "\n", + " print(\"Done indexing\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4dbdf1d6", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0\n" + ] + }, + { + "data": { + "text/plain": [ + "{'PAST': array([[ 9.11132812e-01, -6.79931641e-02, 9.11132812e-01,\n", + " -8.95705402e-01, 2.10346878e-02, -2.93274820e-01,\n", + " -6.97642565e-04],\n", + " [ 7.26562500e-01, -5.49316406e-02, 7.26562500e-01,\n", + " -7.96713233e-01, 1.63470209e-02, 9.89921689e-02,\n", + " -4.68766689e-03],\n", + " [ 5.06835938e-01, -4.22363281e-02, 5.06835938e-01,\n", + " -5.84413052e-01, 1.66303962e-02, 2.12300181e-01,\n", + " 2.83375382e-04],\n", + " [ 3.31542969e-01, -3.21044922e-02, 3.31542969e-01,\n", + " -3.22308868e-01, 1.12319738e-02, 2.62104183e-01,\n", + " -5.39842248e-03],\n", + " [ 2.18261719e-01, -2.51464844e-02, 2.18261719e-01,\n", + " -7.06311315e-02, 3.87633406e-03, 2.51677752e-01,\n", + " -7.35563971e-03],\n", + " [ 1.70410156e-01, -2.19726562e-02, 1.70410156e-01,\n", + " -2.36727092e-02, 5.51053137e-03, 4.69584242e-02,\n", + " 1.63419731e-03],\n", + " [ 1.70410156e-01, -2.00195312e-02, 1.70410156e-01,\n", + " 2.31026905e-04, 5.53286169e-03, 2.39037368e-02,\n", + " 2.23303214e-05],\n", + " [ 1.67480469e-01, -1.85546875e-02, 1.67480469e-01,\n", + " 1.43995846e-03, 4.92360489e-03, 1.20893156e-03,\n", + " -6.09256793e-04],\n", + " [ 1.64062500e-01, -1.68457031e-02, 1.64062500e-01,\n", + " -9.62112099e-03, 3.93328862e-03, -1.10610798e-02,\n", + " -9.90316272e-04],\n", + " [ 1.63574219e-01, -1.51367188e-02, 1.63574219e-01,\n", + " -7.60746840e-03, 7.27008237e-03, 2.01365259e-03,\n", + " 3.33679374e-03],\n", + " [ 1.62109375e-01, -1.33056641e-02, 1.62109375e-01,\n", + " -7.03825131e-02, 7.32138939e-03, -6.27750456e-02,\n", + " 5.13070263e-05],\n", + " [ 1.53808594e-01, -1.14746094e-02, 1.53808594e-01,\n", + " -1.24832645e-01, 6.71608746e-03, -5.44501320e-02,\n", + " -6.05301932e-04],\n", + " [ 1.28417969e-01, -8.91113281e-03, 1.28417969e-01,\n", + " -1.57040447e-01, 5.12196869e-03, -3.22078019e-02,\n", + " -1.59411877e-03],\n", + " [ 9.47265625e-02, -6.10351562e-03, 9.47265625e-02,\n", + " -1.89198375e-01, 2.71172076e-03, -3.21579278e-02,\n", + " -2.41024792e-03],\n", + " [ 5.17578125e-02, -3.05175781e-03, 5.17578125e-02,\n", + " -2.35911697e-01, 4.65066731e-03, -4.67133224e-02,\n", + " 1.93894655e-03],\n", + " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " -2.35911697e-01, 4.65066731e-03, -4.67133224e-02,\n", + " 1.93894655e-03]]),\n", + " 'FUTURE': array([[-0.06787109, 0.00366211],\n", + " [-0.14990234, 0.0078125 ],\n", + " [-0.234375 , 0.01159668],\n", + " [-0.31347656, 0.01513672],\n", + " [-0.38134766, 0.01818848],\n", + " [-0.43945312, 0.02075195],\n", + " [-0.48681641, 0.02319336],\n", + " [-0.52197266, 0.02478027],\n", + " [-0.53955078, 0.02648926],\n", + " [-0.54589844, 0.02770996],\n", + " [-0.54931641, 0.02905273],\n", + " [-0.55712891, 0.03027344],\n", + " [-0.57177734, 0.03100586],\n", + " [-0.51367188, 0.03015137],\n", + " [-0.37353516, 0.02697754],\n", + " [-0.13964844, 0.01953125],\n", + " [ 0.19580078, 0.00671387],\n", + " [ 0.64501953, -0.01525879],\n", + " [ 1.20068359, -0.05432129],\n", + " [ 1.85644531, -0.1151123 ]])}" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# import protobuf\n", + "import protos.e2e_pb2 as e2e_pb2\n", + "import pickle\n", + "import struct\n", + "import os\n", + "import numpy as np\n", + "from PIL import Image\n", + "from io import BytesIO\n", + "\n", + "DATA_DIR = '/scratch/gilbreth/bnamikas/data/waymo_open_dataset_end_to_end_camera_v_1_0_0'\n", + "\n", + "\n", + "with open(\"index.pkl\", 'rb') as f:\n", + " indexes = pickle.load(f)\n", + "\n", + "def load_idx(idx):\n", + " frame = e2e_pb2.E2EDFrame()\n", + "\n", + " with open(os.path.join(DATA_DIR, indexes[idx][0]), 'rb') as f:\n", + " blenth = f.read(8)\n", + " proto_len = struct.unpack('q', blenth)[0]\n", + " f.read(4)\n", + " protobuff = f.read(proto_len)\n", + " server = frame.ParseFromString(protobuff)\n", + "\n", + " print(len(frame.past_states.pos_z))\n", + "\n", + " past = np.stack([frame.past_states.pos_x, frame.past_states.pos_y, frame.past_states.vel_x, frame.past_states.vel_y, frame.past_states.accel_x, frame.past_states.accel_y], axis=-1)\n", + " \n", + "\n", + " future = np.stack([frame.future_states.pos_x, frame.future_states.pos_y], axis=-1)\n", + "\n", + "\n", + " return {'PAST':past, 'FUTURE':future}#frame.intent#np.array(list(zip(frame.future_states.pos_x, frame.future_states.pos_y, frame.future_states.pos_z)))\n", + "\n", + "\n", + "\n", + "load_idx(99999)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "82bda809", + "metadata": {}, + "outputs": [], + "source": [ + "import torch\n", + "from torch.utils.data import Dataset\n", + "from protos import e2e_pb2\n", + "import pickle\n", + "import struct\n", + "import os\n", + "import numpy as np\n", + "from PIL import Image\n", + "from io import BytesIO \n", + "\n", + "class WaymoE2E(Dataset): \n", + " def __init__(self, indexFile = 'index.pkl', data_dir='./dataset'):\n", + " self.DATA_DIR = data_dir\n", + "\n", + " with open(indexFile, 'rb') as f:\n", + " self.indexes = pickle.load(f)\n", + "\n", + " def decode_img(self, img):\n", + " return np.array(Image.open(BytesIO(img)))\n", + " \n", + "\n", + " def __len__(self):\n", + " return len(self.indexes)\n", + "\n", + " def __getitem__(self, idx):\n", + " frame = e2e_pb2.E2EDFrame()\n", + "\n", + " with open(os.path.join(self.DATA_DIR, self.indexes[idx][0]), 'rb') as f:\n", + " # pass\n", + " f.seek(self.indexes[idx][1])\n", + " blenth = f.read(8)\n", + " proto_len = struct.unpack('q', blenth)[0]\n", + " f.read(4)\n", + " protobuff = f.read(proto_len)\n", + " frame.ParseFromString(protobuff)\n", + "\n", + " return np.vstack([self.decode_img(images.image) for images in frame.frame.images]), np.array(list(zip(frame.future_states.pos_x, frame.future_states.pos_y, frame.future_states.pos_z)))\n" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "22641550", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + " 0%| | 9/12990 [02:56<70:50:55, 19.65s/it] \n" + ] + }, + { + "ename": "RuntimeError", + "evalue": "DataLoader worker (pid(s) 1072405) exited unexpectedly", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mRuntimeError\u001b[0m Traceback (most recent call last)", + "File \u001b[0;32m~/.conda/envs/2025.06-py313/python3.10/lib/python3.10/site-packages/torch/utils/data/dataloader.py:1251\u001b[0m, in \u001b[0;36m_MultiProcessingDataLoaderIter._try_get_data\u001b[0;34m(self, timeout)\u001b[0m\n\u001b[1;32m 1250\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m-> 1251\u001b[0m data \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_data_queue\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mget\u001b[49m\u001b[43m(\u001b[49m\u001b[43mtimeout\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mtimeout\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 1252\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m (\u001b[38;5;28;01mTrue\u001b[39;00m, data)\n", + "File \u001b[0;32m~/.conda/envs/2025.06-py313/python3.10/lib/python3.10/multiprocessing/queues.py:113\u001b[0m, in \u001b[0;36mQueue.get\u001b[0;34m(self, block, timeout)\u001b[0m\n\u001b[1;32m 112\u001b[0m timeout \u001b[38;5;241m=\u001b[39m deadline \u001b[38;5;241m-\u001b[39m time\u001b[38;5;241m.\u001b[39mmonotonic()\n\u001b[0;32m--> 113\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_poll\u001b[49m\u001b[43m(\u001b[49m\u001b[43mtimeout\u001b[49m\u001b[43m)\u001b[49m:\n\u001b[1;32m 114\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m Empty\n", + "File \u001b[0;32m~/.conda/envs/2025.06-py313/python3.10/lib/python3.10/multiprocessing/connection.py:257\u001b[0m, in \u001b[0;36m_ConnectionBase.poll\u001b[0;34m(self, timeout)\u001b[0m\n\u001b[1;32m 256\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_check_readable()\n\u001b[0;32m--> 257\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_poll\u001b[49m\u001b[43m(\u001b[49m\u001b[43mtimeout\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m~/.conda/envs/2025.06-py313/python3.10/lib/python3.10/multiprocessing/connection.py:424\u001b[0m, in \u001b[0;36mConnection._poll\u001b[0;34m(self, timeout)\u001b[0m\n\u001b[1;32m 423\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21m_poll\u001b[39m(\u001b[38;5;28mself\u001b[39m, timeout):\n\u001b[0;32m--> 424\u001b[0m r \u001b[38;5;241m=\u001b[39m \u001b[43mwait\u001b[49m\u001b[43m(\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mtimeout\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 425\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mbool\u001b[39m(r)\n", + "File \u001b[0;32m~/.conda/envs/2025.06-py313/python3.10/lib/python3.10/multiprocessing/connection.py:931\u001b[0m, in \u001b[0;36mwait\u001b[0;34m(object_list, timeout)\u001b[0m\n\u001b[1;32m 930\u001b[0m \u001b[38;5;28;01mwhile\u001b[39;00m \u001b[38;5;28;01mTrue\u001b[39;00m:\n\u001b[0;32m--> 931\u001b[0m ready \u001b[38;5;241m=\u001b[39m \u001b[43mselector\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mselect\u001b[49m\u001b[43m(\u001b[49m\u001b[43mtimeout\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 932\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m ready:\n", + "File \u001b[0;32m~/.conda/envs/2025.06-py313/python3.10/lib/python3.10/selectors.py:416\u001b[0m, in \u001b[0;36m_PollLikeSelector.select\u001b[0;34m(self, timeout)\u001b[0m\n\u001b[1;32m 415\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m--> 416\u001b[0m fd_event_list \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_selector\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mpoll\u001b[49m\u001b[43m(\u001b[49m\u001b[43mtimeout\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 417\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mInterruptedError\u001b[39;00m:\n", + "File \u001b[0;32m~/.conda/envs/2025.06-py313/python3.10/lib/python3.10/site-packages/torch/utils/data/_utils/signal_handling.py:73\u001b[0m, in \u001b[0;36m_set_SIGCHLD_handler..handler\u001b[0;34m(signum, frame)\u001b[0m\n\u001b[1;32m 70\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21mhandler\u001b[39m(signum, frame):\n\u001b[1;32m 71\u001b[0m \u001b[38;5;66;03m# This following call uses `waitid` with WNOHANG from C side. Therefore,\u001b[39;00m\n\u001b[1;32m 72\u001b[0m \u001b[38;5;66;03m# Python can still get and update the process status successfully.\u001b[39;00m\n\u001b[0;32m---> 73\u001b[0m \u001b[43m_error_if_any_worker_fails\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 74\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m previous_handler \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n", + "\u001b[0;31mRuntimeError\u001b[0m: DataLoader worker (pid 1072405) is killed by signal: Killed. ", + "\nThe above exception was the direct cause of the following exception:\n", + "\u001b[0;31mRuntimeError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[2], line 16\u001b[0m\n\u001b[1;32m 8\u001b[0m loader \u001b[38;5;241m=\u001b[39m DataLoader(\n\u001b[1;32m 9\u001b[0m dataset, \n\u001b[1;32m 10\u001b[0m batch_size\u001b[38;5;241m=\u001b[39m\u001b[38;5;241m32\u001b[39m,\n\u001b[1;32m 11\u001b[0m num_workers\u001b[38;5;241m=\u001b[39m\u001b[38;5;241m4\u001b[39m,\n\u001b[1;32m 12\u001b[0m shuffle\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mFalse\u001b[39;00m\n\u001b[1;32m 13\u001b[0m )\n\u001b[1;32m 15\u001b[0m start \u001b[38;5;241m=\u001b[39m time\u001b[38;5;241m.\u001b[39mtime()\n\u001b[0;32m---> 16\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m batch_of_frames \u001b[38;5;129;01min\u001b[39;00m tqdm(loader):\n\u001b[1;32m 17\u001b[0m \u001b[38;5;28;01mpass\u001b[39;00m\n\u001b[1;32m 18\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mTotal Time:\u001b[39m\u001b[38;5;124m\"\u001b[39m, time\u001b[38;5;241m.\u001b[39mtime()\u001b[38;5;241m-\u001b[39mstart)\n", + "File \u001b[0;32m~/.conda/envs/2025.06-py313/python3.10/lib/python3.10/site-packages/tqdm/std.py:1181\u001b[0m, in \u001b[0;36mtqdm.__iter__\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 1178\u001b[0m time \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_time\n\u001b[1;32m 1180\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m-> 1181\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m obj \u001b[38;5;129;01min\u001b[39;00m iterable:\n\u001b[1;32m 1182\u001b[0m \u001b[38;5;28;01myield\u001b[39;00m obj\n\u001b[1;32m 1183\u001b[0m \u001b[38;5;66;03m# Update and possibly print the progressbar.\u001b[39;00m\n\u001b[1;32m 1184\u001b[0m \u001b[38;5;66;03m# Note: does not call self.update(1) for speed optimisation.\u001b[39;00m\n", + "File \u001b[0;32m~/.conda/envs/2025.06-py313/python3.10/lib/python3.10/site-packages/torch/utils/data/dataloader.py:708\u001b[0m, in \u001b[0;36m_BaseDataLoaderIter.__next__\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 705\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_sampler_iter \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[1;32m 706\u001b[0m \u001b[38;5;66;03m# TODO(https://github.com/pytorch/pytorch/issues/76750)\u001b[39;00m\n\u001b[1;32m 707\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_reset() \u001b[38;5;66;03m# type: ignore[call-arg]\u001b[39;00m\n\u001b[0;32m--> 708\u001b[0m data \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_next_data\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 709\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_num_yielded \u001b[38;5;241m+\u001b[39m\u001b[38;5;241m=\u001b[39m \u001b[38;5;241m1\u001b[39m\n\u001b[1;32m 710\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m (\n\u001b[1;32m 711\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_dataset_kind \u001b[38;5;241m==\u001b[39m _DatasetKind\u001b[38;5;241m.\u001b[39mIterable\n\u001b[1;32m 712\u001b[0m \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_IterableDataset_len_called \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[1;32m 713\u001b[0m \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_num_yielded \u001b[38;5;241m>\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_IterableDataset_len_called\n\u001b[1;32m 714\u001b[0m ):\n", + "File \u001b[0;32m~/.conda/envs/2025.06-py313/python3.10/lib/python3.10/site-packages/torch/utils/data/dataloader.py:1458\u001b[0m, in \u001b[0;36m_MultiProcessingDataLoaderIter._next_data\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 1455\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_process_data(data)\n\u001b[1;32m 1457\u001b[0m \u001b[38;5;28;01massert\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_shutdown \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_tasks_outstanding \u001b[38;5;241m>\u001b[39m \u001b[38;5;241m0\u001b[39m\n\u001b[0;32m-> 1458\u001b[0m idx, data \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_get_data\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 1459\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_tasks_outstanding \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m=\u001b[39m \u001b[38;5;241m1\u001b[39m\n\u001b[1;32m 1460\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_dataset_kind \u001b[38;5;241m==\u001b[39m _DatasetKind\u001b[38;5;241m.\u001b[39mIterable:\n\u001b[1;32m 1461\u001b[0m \u001b[38;5;66;03m# Check for _IterableDatasetStopIteration\u001b[39;00m\n", + "File \u001b[0;32m~/.conda/envs/2025.06-py313/python3.10/lib/python3.10/site-packages/torch/utils/data/dataloader.py:1420\u001b[0m, in \u001b[0;36m_MultiProcessingDataLoaderIter._get_data\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 1416\u001b[0m \u001b[38;5;66;03m# In this case, `self._data_queue` is a `queue.Queue`,. But we don't\u001b[39;00m\n\u001b[1;32m 1417\u001b[0m \u001b[38;5;66;03m# need to call `.task_done()` because we don't use `.join()`.\u001b[39;00m\n\u001b[1;32m 1418\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m 1419\u001b[0m \u001b[38;5;28;01mwhile\u001b[39;00m \u001b[38;5;28;01mTrue\u001b[39;00m:\n\u001b[0;32m-> 1420\u001b[0m success, data \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_try_get_data\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 1421\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m success:\n\u001b[1;32m 1422\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m data\n", + "File \u001b[0;32m~/.conda/envs/2025.06-py313/python3.10/lib/python3.10/site-packages/torch/utils/data/dataloader.py:1264\u001b[0m, in \u001b[0;36m_MultiProcessingDataLoaderIter._try_get_data\u001b[0;34m(self, timeout)\u001b[0m\n\u001b[1;32m 1262\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mlen\u001b[39m(failed_workers) \u001b[38;5;241m>\u001b[39m \u001b[38;5;241m0\u001b[39m:\n\u001b[1;32m 1263\u001b[0m pids_str \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m, \u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;241m.\u001b[39mjoin(\u001b[38;5;28mstr\u001b[39m(w\u001b[38;5;241m.\u001b[39mpid) \u001b[38;5;28;01mfor\u001b[39;00m w \u001b[38;5;129;01min\u001b[39;00m failed_workers)\n\u001b[0;32m-> 1264\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mRuntimeError\u001b[39;00m(\n\u001b[1;32m 1265\u001b[0m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mDataLoader worker (pid(s) \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mpids_str\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m) exited unexpectedly\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 1266\u001b[0m ) \u001b[38;5;28;01mfrom\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21;01me\u001b[39;00m\n\u001b[1;32m 1267\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(e, queue\u001b[38;5;241m.\u001b[39mEmpty):\n\u001b[1;32m 1268\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m (\u001b[38;5;28;01mFalse\u001b[39;00m, \u001b[38;5;28;01mNone\u001b[39;00m)\n", + "\u001b[0;31mRuntimeError\u001b[0m: DataLoader worker (pid(s) 1072405) exited unexpectedly" + ] + } + ], + "source": [ + "from torch.utils.data import DataLoader\n", + "import time\n", + "from tqdm import tqdm\n", + "DATA_DIR = '/scratch/gilbreth/bnamikas/data/waymo_open_dataset_end_to_end_camera_v_1_0_0'\n", + "\n", + "dataset = WaymoE2E(data_dir = DATA_DIR)\n", + "\n", + "loader = DataLoader(\n", + " dataset, \n", + " batch_size=32,\n", + " num_workers=4,\n", + " shuffle=False\n", + ")\n", + "\n", + "start = time.time()\n", + "for batch_of_frames in tqdm(loader):\n", + " pass\n", + "print(\"Total Time:\", time.time()-start)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a00dde80", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "python3.10", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.19" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/index.pkl b/index.pkl new file mode 100644 index 0000000..4d9f7af Binary files /dev/null and b/index.pkl differ diff --git a/indexer.py b/indexer.py new file mode 100644 index 0000000..c4d333f --- /dev/null +++ b/indexer.py @@ -0,0 +1,30 @@ +should_index = True +if should_index: # Takes approx. 9 mins to index + import os + import mmap + import struct + import time + import pickle + from tqdm import tqdm + + DATA_DIR = '/scratch/gilbreth/bnamikas/data/waymo_open_dataset_end_to_end_camera_v_1_0_0' + # DATA_DIR = './data' + + indexes = [] + + start = time.time() + for i, fn in enumerate(tqdm([file for file in os.listdir(DATA_DIR) if '.tfrecord' in file and file.startswith('train')])): + with open(os.path.join(DATA_DIR, fn), 'rb') as file: + while True: + blenth = file.read(8) + if len(blenth) == 0: + break + proto_len = struct.unpack('q', blenth)[0] + indexes.append((fn, file.tell()+4, proto_len)) #file.tell()+4 so that I can make sure we skip checksum + file.seek(file.tell() + proto_len+8) + + + with open('index.pkl', 'wb') as f: + pickle.dump(indexes, f) + + print("Done indexing") diff --git a/loader.py b/loader.py new file mode 100644 index 0000000..792ca13 --- /dev/null +++ b/loader.py @@ -0,0 +1,70 @@ +# HISTORICAL, loader1-3 have memory leaks and issues +import torch +from torch.utils.data import Dataset +from protos import e2e_pb2 +import pickle +import struct +import os +import numpy as np +from PIL import Image +from io import BytesIO +import cv2 + +class WaymoE2E(Dataset): + def __init__(self, indexFile = 'index_local.pkl', data_dir='./dataset'): + self.DATA_DIR = data_dir + + with open(indexFile, 'rb') as f: + self.indexes = pickle.load(f) + + def decode_img(self, img): + img_array = np.frombuffer(img, np.uint8) + return cv2.imdecode(img_array, cv2.IMREAD_COLOR) + + + def __len__(self): + return len(self.indexes) + + def __getitem__(self, idx): + filename, offset, size = self.indexes[idx] + full_filepath = os.path.join(self.DATA_DIR, filename) + + + with open(full_filepath, 'rb') as f: + # pass + f.seek(offset) + # blenth = f.read(8) + # proto_len = struct.unpack('q', blenth)[0] + # f.read(4) + protobuff = f.read(size) + + frame = e2e_pb2.E2EDFrame() + frame.ParseFromString(protobuff) + return np.vstack([self.decode_img(images.image) for images in frame.frame.images]), np.array(list(zip(frame.future_states.pos_x, frame.future_states.pos_y, frame.future_states.pos_z))) + +from torch.utils.data import DataLoader +import time +from tqdm import tqdm +# DATA_DIR = '/scratch/gilbreth/bnamikas/data/waymo_open_dataset_end_to_end_camera_v_1_0_0' +DATA_DIR = './data' +# DATA_DIR = '/tmp/' + + +def main(): + dataset = WaymoE2E(data_dir = DATA_DIR) + + loader = DataLoader( + dataset, + batch_size=32, + num_workers=16, + shuffle=False + ) + + start = time.time() + for batch_of_frames in tqdm(loader): + pass + print("Total Time:", time.time()-start) + +import cProfile +cProfile.run('main()') +# main() \ No newline at end of file diff --git a/loader1.py b/loader1.py new file mode 100644 index 0000000..fc3c099 --- /dev/null +++ b/loader1.py @@ -0,0 +1,61 @@ +# HISTORICAL, loader1-3 have memory leaks and issues +import torch +from torch.utils.data import Dataset +from protos import e2e_pb2 +import pickle +import struct +import os +import numpy as np +from PIL import Image +from io import BytesIO + +class WaymoE2E(Dataset): + def __init__(self, indexFile = 'index.pkl', data_dir='./dataset'): + self.DATA_DIR = data_dir + + with open(indexFile, 'rb') as f: + self.indexes = pickle.load(f) + + self.file = open(os.path.join(self.DATA_DIR, self.indexes[0][0]), 'rb') + self.filename=self.indexes[0][0] + + def decode_img(self, img): + return np.array(Image.open(BytesIO(img))) + + + def __len__(self): + return len(self.indexes) + + def __getitem__(self, idx): + frame = e2e_pb2.E2EDFrame() + + if self.filename != self.indexes[idx][0]: + self.file.close() + self.file = open(os.path.join(self.DATA_DIR, self.indexes[idx][0]), 'rb') + self.filename = self.indexes[idx][0] + + # pass + self.file.seek(self.indexes[idx][1]) + protobuff = self.file.read(self.indexes[idx][2]) + frame.ParseFromString(protobuff) + + return 1 # np.vstack([self.decode_img(images.image) for images in frame.frame.images]), np.array(list(zip(frame.future_states.pos_x, frame.future_states.pos_y, frame.future_states.pos_z))) + +from torch.utils.data import DataLoader +import time +from tqdm import tqdm +DATA_DIR = '/scratch/gilbreth/bnamikas/data/waymo_open_dataset_end_to_end_camera_v_1_0_0' + +dataset = WaymoE2E(data_dir = DATA_DIR) + +loader = DataLoader( + dataset, + batch_size=32, + num_workers=0, + shuffle=False +) + +start = time.time() +for batch_of_frames in tqdm(loader): + pass +print("Total Time:", time.time()-start) diff --git a/loader1m.py b/loader1m.py new file mode 100644 index 0000000..a17156c --- /dev/null +++ b/loader1m.py @@ -0,0 +1,56 @@ +# HISTORICAL, loader1-3 have memory leaks and issues +import torch +from torch.utils.data import Dataset +from protos import e2e_pb2 +import pickle +import struct +import os +import numpy as np +from PIL import Image +from io import BytesIO + +class WaymoE2E(Dataset): + def __init__(self, indexFile='index.pkl', data_dir='./dataset'): + self.DATA_DIR = data_dir + + with open(indexFile, 'rb') as f: + self.indexes = pickle.load(f) + + + def decode_img(self, img): + return np.array(Image.open(BytesIO(img))) + + def __len__(self): + return len(self.indexes) + + def __getitem__(self, idx): + filename, offset, size = self.indexes[idx] + full_filepath = os.path.join(self.DATA_DIR, filename) + + with open(full_filepath, 'rb') as f: + f.seek(offset) + protobuff = f.read(size) + + frame = e2e_pb2.E2EDFrame() + frame.ParseFromString(protobuff) + + return 1 # np.vstack([self.decode_img(images.image) for images in frame.frame.images]), np.array(list(zip(frame.future_states.pos_x, frame.future_states.pos_y, frame.future_states.pos_z))) + +from torch.utils.data import DataLoader +import time +from tqdm import tqdm +DATA_DIR = '/scratch/gilbreth/bnamikas/data/waymo_open_dataset_end_to_end_camera_v_1_0_0' + +dataset = WaymoE2E(data_dir = DATA_DIR) + +loader = DataLoader( + dataset, + batch_size=32, + num_workers=8, + shuffle=False +) + +start = time.time() +for batch_of_frames in tqdm(loader): + pass +print("Total Time:", time.time()-start) diff --git a/loader2.py b/loader2.py new file mode 100644 index 0000000..ceaddc0 --- /dev/null +++ b/loader2.py @@ -0,0 +1,72 @@ +# HISTORICAL, loader1-3 have memory leaks and issues +import torch +from torch.utils.data import Dataset +from protos import e2e_pb2 +import pickle +import struct +import os +import numpy as np +from PIL import Image +from io import BytesIO +import mmap +import cv2 + +class WaymoE2E(Dataset): + def __init__(self, indexFile = 'index.pkl', data_dir='./dataset'): + self.DATA_DIR = data_dir + + with open(indexFile, 'rb') as f: + self.indexes = pickle.load(f) + + all_paths = list(set([index[0] for index in self.indexes])) + self.fds = [(os.open(os.path.join(self.DATA_DIR, fp), os.O_RDONLY), fp) for fp in all_paths] + self.mmaps = {fd[1]: mmap.mmap(fd[0], length=0, access=mmap.ACCESS_READ) for fd in self.fds} + + def decode_img(self, img): + img_array = np.frombuffer(img, np.uint8) + return cv2.imdecode(img_array, cv2.IMREAD_COLOR) + + + def __len__(self): + return len(self.indexes) + + def __getitem__(self, idx): + frame = e2e_pb2.E2EDFrame() + + # self.mmaps[self.indexes[idx][0]].seek(self.indexes[idx][1]) + # frame.ParseFromString(self.mmaps[self.indexes[idx][0]].read(self.indexes[idx][2])) + frame.ParseFromString(self.mmaps[self.indexes[idx][0]][self.indexes[idx][1]:self.indexes[idx][1]+self.indexes[idx][2]]) + + return 1#np.vstack([self.decode_img(images.image) for images in frame.frame.images]), np.array(list(zip(frame.future_states.pos_x, frame.future_states.pos_y, frame.future_states.pos_z))) + +from torch.utils.data import DataLoader +import time +from tqdm import tqdm +DATA_DIR = '/scratch/gilbreth/bnamikas/data/waymo_open_dataset_end_to_end_camera_v_1_0_0' + + + +def main(): + try: + dataset = WaymoE2E(data_dir = DATA_DIR) + + loader = DataLoader( + dataset, + batch_size=32, + num_workers=8, + shuffle=True + ) + + start = time.time() + for batch_of_frames in tqdm(loader): + pass + print("Total Time:", time.time()-start) + except Exception as e: + print(e) + finally: + [mmap.close() for mmap in dataset.mmaps.values()] + [os.close(fd[0]) for fd in dataset.fds] + +import cProfile +# cProfile.run('main()') +main() \ No newline at end of file diff --git a/loader3.py b/loader3.py new file mode 100644 index 0000000..bf8badb --- /dev/null +++ b/loader3.py @@ -0,0 +1,118 @@ +# HISTORICAL, loader1-3 have memory leaks and issues +import torch +from torch.utils.data import IterableDataset +from protos import e2e_pb2 +import pickle +import struct +import os +import numpy as np +from PIL import Image +from io import BytesIO +import cv2 + +devices = ['cuda:0', 'cuda:1'] + +class WaymoE2E(IterableDataset): + def __init__(self, batch_size, indexFile = 'index.pkl', data_dir='./dataset'): + self.data_dir = data_dir + self.batch_size = batch_size + self.filename = "" + self.file = None + + + with open(indexFile, 'rb') as f: + self.indexes = pickle.load(f) + + def decode_img(self, img): + return img + img_array = np.frombuffer(img, np.uint8) + return cv2.imdecode(img_array, cv2.IMREAD_COLOR) + + def __len__(self): + return len(self.indexes) + + def __iter__(self): + worker = torch.utils.data.get_worker_info() + if worker is not None: + id, num_workers = worker.id, worker.num_workers + local_indexes = [] + batch_id = 0 + for i in range(0, len(self.indexes), self.batch_size): + if batch_id % num_workers == id: + local_indexes.extend(list(range(i, min(len(self.indexes), i + self.batch_size)))) + + batch_id += 1 + else: + local_indexes = list(range(len(self.indexes))) + + frame = e2e_pb2.E2EDFrame() + + for idx in local_indexes: + filename, start_byte, byte_length = self.indexes[idx] + if self.filename != filename: + if self.file: + self.file.close() + self.file = open(os.path.join(self.data_dir, filename), 'rb') + self.filename = filename + + self.file.seek(start_byte) # type: ignore + protobuf = self.file.read(byte_length) # type: ignore + frame.ParseFromString(protobuf) + + yield [self.decode_img(images.image) for images in frame.frame.images], np.stack((frame.future_states.pos_x, frame.future_states.pos_y, frame.future_states.pos_z), axis=-1) + +import torchvision + +def collat_fn(batch): + + all_states = [] + flat_img_bytes = [] + images_per_sample = len(batch[0][0]) + + for img_bytes_list, states in batch: + flat_img_bytes.extend(img_bytes_list) + all_states.append(states) + + # 2. Convert raw bytes to a list of CPU Tensors + cpu_tensors = [ + torch.from_numpy(np.frombuffer(img_bytes, dtype=np.uint8).copy()) + for img_bytes in flat_img_bytes + ] + + # 3. Batch Decode to GPU + # This returns a LIST of GPU tensors (e.g., [tensor1, tensor2, ...]) + # of *different* sizes. + # start = time.time() + gpu_tensors_list = torchvision.io.decode_jpeg( + cpu_tensors, + mode=torchvision.io.ImageReadMode.UNCHANGED, # Output is CHW + device= 'cuda' #['cuda:0', 'cuda:1'][torch.utils.data.get_worker_info().id%2] + ) + # print("Decode time: ", time.time()-start) + return gpu_tensors_list + +from torch.utils.data import DataLoader +import time +from tqdm import tqdm +# DATA_DIR = '/scratch/gilbreth/bnamikas/data/waymo_open_dataset_end_to_end_camera_v_1_0_0' +DATA_DIR = './data' +# DATA_DIR = '/tmp/' +BATCH_SIZE = 32 +dataset = WaymoE2E(BATCH_SIZE, data_dir = DATA_DIR) +loader = DataLoader( + dataset, + batch_size=BATCH_SIZE, + collate_fn = collat_fn, + num_workers=14, +) + +def main(): + + + # start = time.time() + for batch_of_frames in tqdm(loader): + pass + # print("Total Time:", time.time()-start) + +import cProfile +main() \ No newline at end of file diff --git a/loader4_gpudecode.py b/loader4_gpudecode.py new file mode 100644 index 0000000..86a837f --- /dev/null +++ b/loader4_gpudecode.py @@ -0,0 +1,94 @@ +import torch +from torch.utils.data import IterableDataset +from protos import e2e_pb2 +import torchvision +import pickle +import struct +import os +import numpy as np +from PIL import Image +from io import BytesIO +import cv2 + +devices = ['cuda:0', 'cuda:1'] + +class WaymoE2E(IterableDataset): + def __init__(self, batch_size, indexFile = 'index.pkl', data_dir='./dataset'): + self.data_dir = data_dir + self.batch_size = batch_size + + self.filename = "" + self.file = None + + with open(indexFile, 'rb') as f: + self.indexes = pickle.load(f) + + + def decode_img(self, img): + img_tensor = torch.from_numpy(np.frombuffer(img, dtype=np.uint8).copy()) + gpu_tensors_list = torchvision.io.decode_jpeg( + img_tensor, + mode=torchvision.io.ImageReadMode.UNCHANGED, + device= 'cuda' #['cuda:0', 'cuda:1'][torch.utils.data.get_worker_info().id%2] + ) + # img_array = np.frombuffer(img, np.uint8) + return gpu_tensors_list.cpu() + + def __len__(self): + return len(self.indexes) + + def __iter__(self): + worker = torch.utils.data.get_worker_info() + if worker is not None: + id, num_workers = worker.id, worker.num_workers + local_indexes = [] + batch_id = 0 + for i in range(0, len(self.indexes), self.batch_size): + if batch_id % num_workers == id: + local_indexes.extend(list(range(i, min(len(self.indexes), i + self.batch_size)))) + + batch_id += 1 + else: + local_indexes = list(range(len(self.indexes))) + + + for idx in local_indexes: + frame = e2e_pb2.E2EDFrame() # type: ignore + filename, start_byte, byte_length = self.indexes[idx] + if self.filename != filename: + if self.file: + self.file.close() + del self.file + self.file = open(os.path.join(self.data_dir, filename), 'rb') + self.filename = filename + + self.file.seek(start_byte) # type: ignore + protobuf = self.file.read(byte_length) # type: ignore + frame.ParseFromString(protobuf) + + yield [self.decode_img(images.image) for images in frame.frame.images], np.stack((frame.future_states.pos_x, frame.future_states.pos_y, frame.future_states.pos_z), axis=-1) + + + +from torch.utils.data import DataLoader +import time +from tqdm import tqdm +DATA_DIR = '/scratch/gilbreth/bnamikas/data/waymo_open_dataset_end_to_end_camera_v_1_0_0' +# DATA_DIR = './data' +# DATA_DIR = '/tmp/' +BATCH_SIZE = 32 +dataset = WaymoE2E(BATCH_SIZE, data_dir = DATA_DIR) +loader = DataLoader( + dataset, + batch_size=BATCH_SIZE, + num_workers=32, +) + +def main(): + # start = time.time() + for batch_of_frames in tqdm(loader): + pass + # print("Total Time:", time.time()-start) + +import cProfile +main() \ No newline at end of file diff --git a/loader5_copy.py b/loader5_copy.py new file mode 100644 index 0000000..d731b68 --- /dev/null +++ b/loader5_copy.py @@ -0,0 +1,148 @@ +import torch +from torch.utils.data import IterableDataset, DataLoader +from protos import e2e_pb2 +import torchvision +import pickle +import shutil +import os +import numpy as np +import threading +import fcntl +import time +from tqdm import tqdm + +devices = ['cuda:0', 'cuda:1'] + +class WaymoE2E(IterableDataset): + def __init__(self, batch_size, indexFile = 'index.pkl', data_dir='./dataset', temp_dir='/tmp/cache/', precopy_factor=1, decode_image=True): + self.precopy_factor=precopy_factor + self.decode_image = decode_image + self.data_dir = data_dir + self.batch_size = batch_size + self.temp_dir = temp_dir + + + with open(indexFile, 'rb') as f: + self.indexes = pickle.load(f)[:20000] + + self.filenames = [] + for index in self.indexes: + if index[0] not in self.filenames: + self.filenames.append(index[0]) + self.filename = self.filenames.pop(0) + os.makedirs(self.temp_dir, exist_ok=True) + + + def decode_img(self, img): + # return img + img_tensor = torch.from_numpy(np.frombuffer(img, dtype=np.uint8).copy()) + gpu_tensors_list = torchvision.io.decode_jpeg( + img_tensor, + mode=torchvision.io.ImageReadMode.UNCHANGED, + device= 'cuda' #['cuda:0', 'cuda:1'][torch.utils.data.get_worker_info().id%2] + ) + # img_array = np.frombuffer(img, np.uint8) + return gpu_tensors_list.cpu() + + def __len__(self): + return len(self.indexes) + + def _copy_file(self, filename): + source_path, dest_path = os.path.join(self.data_dir, filename), os.path.join(self.temp_dir, filename) + temp_dest_path = dest_path + f".tmp.{os.getpid()}" #prevents the file from being read before it is copied + lock_path = dest_path + ".lock" + + if os.path.exists(dest_path): + return + + lock_file = open(lock_path, 'w') + + try: + fcntl.flock(lock_file.fileno(), fcntl.LOCK_EX) + + if os.path.exists(dest_path): + return dest_path + + try: + start = time.time() + shutil.copy(source_path, temp_dest_path) + print(f"Copy took {time.time()-start} seconds") + os.rename(temp_dest_path, dest_path) + + finally: + if os.path.exists(temp_dest_path): + os.remove(temp_dest_path) + except Exception as e: + print("waiting") + finally: + fcntl.flock(lock_file.fileno(), fcntl.LOCK_UN) + lock_file.close() + + def __iter__(self): + worker = torch.utils.data.get_worker_info() + + self._copy_file(self.filename) + self.file = open(os.path.join(self.temp_dir, self.filename), 'rb') + + self.next_filename = self.filenames.pop(0) + + self.copy = threading.Thread(target=self._copy_file, name="copy file", args=(self.next_filename,)) + self.copy.daemon = True + self.copy.start() + + if worker is not None: + id, num_workers = worker.id, worker.num_workers + local_indexes = [] + batch_id = 0 + for i in range(0, len(self.indexes), self.batch_size): + if batch_id % num_workers == id: + local_indexes.extend(list(range(i, min(len(self.indexes), i + self.batch_size)))) + + batch_id += 1 + else: + local_indexes = list(range(len(self.indexes))) + + + for idx in local_indexes: + frame = e2e_pb2.E2EDFrame() # type: ignore + filename, start_byte, byte_length = self.indexes[idx] + if self.filename != filename: + if self.file: + self.file.close() + + self.copy.join() + self.file = open(os.path.join(self.temp_dir, self.next_filename), 'rb') + self.filename = self.next_filename + + if len(self.filenames): + self.next_filename = self.filenames.pop(0) + self.copy = threading.Thread(target=self._copy_file, name="copy file", args=(self.next_filename,)) + self.copy.daemon = True + self.copy.start() + + self.file.seek(start_byte) # type: ignore + protobuf = self.file.read(byte_length) # type: ignore + frame.ParseFromString(protobuf) + + yield [self.decode_img(images.image) for images in frame.frame.images], np.stack((frame.future_states.pos_x, frame.future_states.pos_y, frame.future_states.pos_z), axis=-1) + + +DATA_DIR = '/scratch/gilbreth/bnamikas/data/waymo_open_dataset_end_to_end_camera_v_1_0_0' +# DATA_DIR = './data' +# DATA_DIR = '/tmp/' +BATCH_SIZE = 32 +dataset = WaymoE2E(BATCH_SIZE, data_dir = DATA_DIR) +loader = DataLoader( + dataset, + batch_size=BATCH_SIZE, + num_workers=12, +) + +def main(): + # start = time.time() + for batch_of_frames in tqdm(loader): + pass + # print("Total Time:", time.time()-start) + +import cProfile +main() \ No newline at end of file diff --git a/loader6_precopy.py b/loader6_precopy.py new file mode 100644 index 0000000..8e167ad --- /dev/null +++ b/loader6_precopy.py @@ -0,0 +1,202 @@ +import torch +from torch.utils.data import IterableDataset, DataLoader +from protos import e2e_pb2 +import torchvision +import pickle +import shutil +import os +import numpy as np +import threading +import fcntl +import time +from tqdm import tqdm +from concurrent.futures import ThreadPoolExecutor + +devices = ['cuda:0', 'cuda:1'] + +class WaymoE2E(IterableDataset): + def __init__(self, batch_size, indexFile = 'index.pkl', data_dir='./dataset', temp_dir='/tmp/cache/', precopy_factor=1, decode_image=True): + self.precopy_factor = precopy_factor + self.decode_image = decode_image + self.data_dir = data_dir + self.batch_size = batch_size + self.temp_dir = temp_dir + + self.copy_executor = ThreadPoolExecutor(max_workers=precopy_factor) + + with open(indexFile, 'rb') as f: + self.indexes = pickle.load(f) + + self.all_filenames = [] + for index in self.indexes: + if index[0] not in self.all_filenames: + self.all_filenames.append(index[0]) + + self.current_filename_index = 0 + os.makedirs(self.temp_dir, exist_ok=True) + + self.copy_futures_map = {} + self.copy_lock = threading.Lock() + + def decode_img(self, img): + # return img + if not self.decode_image: + return np.array([]) + img_tensor = torch.from_numpy(np.frombuffer(img, dtype=np.uint8).copy()) + gpu_tensors_list = torchvision.io.decode_jpeg( + img_tensor, + mode=torchvision.io.ImageReadMode.UNCHANGED, + device= 'cuda' #['cuda:0', 'cuda:1'][torch.utils.data.get_worker_info().id%2] + ) + return gpu_tensors_list.cpu() + + def __len__(self): + return len(self.indexes) + + def _copy_files(self, filenames): + """Submits file copy tasks to the thread pool and stores the Futures in a map.""" + with self.copy_lock: + finished_keys = [k for k, v in self.copy_futures_map.items() if v.done()] + for k in finished_keys: + del self.copy_futures_map[k] + + active_futures = len(self.copy_futures_map) + + for filename in filenames: + if filename not in self.copy_futures_map: + if active_futures < self.precopy_factor: + future = self.copy_executor.submit(self._copy_file, filename) + self.copy_futures_map[filename] = future + active_futures += 1 + else: + break + + def _copy_file(self, filename): + source_path, dest_path = os.path.join(self.data_dir, filename), os.path.join(self.temp_dir, filename) + temp_dest_path = dest_path + f".tmp.{os.getpid()}" + lock_path = dest_path + ".lock" + + if os.path.exists(dest_path): + return dest_path + + lock_file = open(lock_path, 'w') + + try: + fcntl.flock(lock_file.fileno(), fcntl.LOCK_EX) + + if os.path.exists(dest_path): + return dest_path + + try: + start = time.time() + shutil.copy(source_path, temp_dest_path) + print(f"Copy took {time.time()-start} seconds for {filename}") + os.rename(temp_dest_path, dest_path) + return dest_path + + finally: + if os.path.exists(temp_dest_path): + os.remove(temp_dest_path) + except Exception as e: + print(f"Error during copy of {filename}: {e}") + finally: + fcntl.flock(lock_file.fileno(), fcntl.LOCK_UN) + lock_file.close() + + def __iter__(self): + worker = torch.utils.data.get_worker_info() + + worker_file_set = set() + if worker is not None: + id, num_workers = worker.id, worker.num_workers + local_indexes = [] + batch_id = 0 + for i in range(0, len(self.indexes), self.batch_size): + if batch_id % num_workers == id: + local_indexes.extend(list(range(i, min(len(self.indexes), i + self.batch_size)))) + batch_id += 1 + else: + local_indexes = list(range(len(self.indexes))) + + for idx in local_indexes: + worker_file_set.add(self.indexes[idx][0]) + + worker_files = sorted(list(worker_file_set), key=lambda f: self.all_filenames.index(f)) + + if not worker_files: + return iter([]) + + self.file = None + self.filename = None + + current_file_idx_in_all = self.all_filenames.index(worker_files[0]) + + initial_copy_list = self.all_filenames[current_file_idx_in_all : current_file_idx_in_all + self.precopy_factor] + self._copy_files(initial_copy_list) + + + for idx in local_indexes: + frame = e2e_pb2.E2EDFrame() # type: ignore + + filename, start_byte, byte_length = self.indexes[idx] + + if self.filename != filename: + if self.file: + self.file.close() + + try: + future_to_wait_on = None + with self.copy_lock: + future_to_wait_on = self.copy_futures_map.get(filename) + + if future_to_wait_on: + future_to_wait_on.result() + else: + self._copy_file(filename) + + except Exception as e: + print(f"Error waiting for or copying file {filename}: {e}") + continue + + self.file = open(os.path.join(self.temp_dir, filename), 'rb') + self.filename = filename + + current_file_global_idx = self.all_filenames.index(self.filename) + next_file_global_idx = current_file_global_idx + 1 + + if next_file_global_idx < len(self.all_filenames): + files_to_precopy = self.all_filenames[next_file_global_idx : next_file_global_idx + self.precopy_factor] + self._copy_files(files_to_precopy) + + self.file.seek(start_byte) # type: ignore + protobuf = self.file.read(byte_length) # type: ignore + frame.ParseFromString(protobuf) + + yield [self.decode_img(images.image) for images in frame.frame.images], np.stack((frame.future_states.pos_x, frame.future_states.pos_y, frame.future_states.pos_z), axis=-1) + + if self.file: + self.file.close() + + +DATA_DIR = '/scratch/gilbreth/bnamikas/data/waymo_open_dataset_end_to_end_camera_v_1_0_0' +# DATA_DIR = './data' +BATCH_SIZE = 32 +PRECOPY_FACTOR = 4 +NUM_WORKERS = 8 + +dataset = WaymoE2E(BATCH_SIZE, data_dir = DATA_DIR, precopy_factor=PRECOPY_FACTOR, decode_image=False) +loader = DataLoader( + dataset, + batch_size=BATCH_SIZE, + num_workers=NUM_WORKERS, +) + +def main(): + # start = time.time() + for batch_of_frames in tqdm(loader): + pass + # print("Total Time:", time.time()-start) + +import cProfile +cProfile.run('main()') +# main() \ No newline at end of file diff --git a/loader8_nocopy_dataloader.py b/loader8_nocopy_dataloader.py new file mode 100644 index 0000000..3217f86 --- /dev/null +++ b/loader8_nocopy_dataloader.py @@ -0,0 +1,104 @@ +import torch +from torch.utils.data import IterableDataset +from protos import e2e_pb2 +import torchvision +import pickle +import struct +import os +import numpy as np +from PIL import Image +from io import BytesIO +import cv2 + +devices = ['cuda:0', 'cuda:1'] + +class WaymoE2E(IterableDataset): + def __init__(self, batch_size, indexFile = 'index.pkl', data_dir='./dataset', images = True): + self.images = images + self.data_dir = data_dir + self.batch_size = batch_size + + self.filename = "" + self.file = None + + with open(indexFile, 'rb') as f: + self.indexes = pickle.load(f) + + + def decode_img(self, img): + if not self.images: + return np.array([]) + + img_tensor = torch.from_numpy(np.frombuffer(img, dtype=np.uint8).copy()) + gpu_tensors_list = torchvision.io.decode_jpeg( + img_tensor, + mode=torchvision.io.ImageReadMode.UNCHANGED, + device= 'cuda' #['cuda:0', 'cuda:1'][torch.utils.data.get_worker_info().id%2] + ) + # img_array = np.frombuffer(img, np.uint8) + return gpu_tensors_list.cpu() + + def __len__(self): + return len(self.indexes) + + def __iter__(self): + worker = torch.utils.data.get_worker_info() + if worker is not None: + id, num_workers = worker.id, worker.num_workers + local_indexes = [] + batch_id = 0 + for i in range(0, len(self.indexes), self.batch_size): + if batch_id % num_workers == id: + local_indexes.extend(list(range(i, min(len(self.indexes), i + self.batch_size)))) + + batch_id += 1 + else: + local_indexes = list(range(len(self.indexes))) + + + for idx in local_indexes: + frame = e2e_pb2.E2EDFrame() # type: ignore + filename, start_byte, byte_length = self.indexes[idx] + if self.filename != filename: + if self.file: + self.file.close() + del self.file + self.file = open(os.path.join(self.data_dir, filename), 'rb') + self.filename = filename + + self.file.seek(start_byte) # type: ignore + protobuf = self.file.read(byte_length) # type: ignore + frame.ParseFromString(protobuf) + + past = np.stack([frame.past_states.pos_x, frame.past_states.pos_y, frame.past_states.vel_x, frame.past_states.vel_y, frame.past_states.accel_x, frame.past_states.accel_y], axis=-1) + + + future = np.stack([frame.future_states.pos_x, frame.future_states.pos_y], axis=-1) + + + yield {'PAST': past, 'FUTURE': future, 'IMAGES': [self.decode_img(images.image) for images in frame.frame.images], 'INTENT': frame.intent} + + + +from torch.utils.data import DataLoader +import time +from tqdm import tqdm +DATA_DIR = '/scratch/gilbreth/bnamikas/data/waymo_open_dataset_end_to_end_camera_v_1_0_0' +# DATA_DIR = './data' +# DATA_DIR = '/tmp/' +BATCH_SIZE = 32 +dataset = WaymoE2E(BATCH_SIZE, data_dir = DATA_DIR, images=False) +loader = DataLoader( + dataset, + batch_size=BATCH_SIZE, + num_workers=16, +) + +def main(): + # start = time.time() + for batch_of_frames in tqdm(loader): + pass + # print("Total Time:", time.time()-start) + +import cProfile +main() \ No newline at end of file diff --git a/protos/dataset.proto b/protos/dataset.proto new file mode 100644 index 0000000..0615466 --- /dev/null +++ b/protos/dataset.proto @@ -0,0 +1,440 @@ +/* Copyright 2019 The Waymo Open Dataset Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +syntax = "proto2"; + +package waymo.open_dataset; + +import "label.proto"; +import "map.proto"; +import "vector.proto"; + +message MatrixShape { + // Dimensions for the Matrix messages defined below. Must not be empty. + // + // The order of entries in 'dims' matters, as it indicates the layout of the + // values in the tensor in-memory representation. + // + // The first entry in 'dims' is the outermost dimension used to lay out the + // values; the last entry is the innermost dimension. This matches the + // in-memory layout of row-major matrices. + repeated int32 dims = 1; +} + +// Row-major matrix. +// Requires: data.size() = product(shape.dims()). +message MatrixFloat { + repeated float data = 1 [packed = true]; + optional MatrixShape shape = 2; +} + +// Row-major matrix. +// Requires: data.size() = product(shape.dims()). +message MatrixInt32 { + repeated int32 data = 1 [packed = true]; + optional MatrixShape shape = 2; +} + +message CameraName { + enum Name { + UNKNOWN = 0; + FRONT = 1; + FRONT_LEFT = 2; + FRONT_RIGHT = 3; + SIDE_LEFT = 4; + SIDE_RIGHT = 5; + REAR_LEFT = 6; + REAR = 7; + REAR_RIGHT = 8; + + } +} + +// 'Laser' is used interchangeably with 'Lidar' in this file. +message LaserName { + enum Name { + UNKNOWN = 0; + TOP = 1; + FRONT = 2; + SIDE_LEFT = 3; + SIDE_RIGHT = 4; + REAR = 5; + + } +} + +// 4x4 row major transform matrix that tranforms 3d points from one frame to +// another. +message Transform { + repeated double transform = 1; +} + +message Velocity { + // Velocity in m/s. + optional float v_x = 1; + optional float v_y = 2; + optional float v_z = 3; + + // Angular velocity in rad/s. + optional double w_x = 4; + optional double w_y = 5; + optional double w_z = 6; +} + +message CameraCalibration { + optional CameraName.Name name = 1; + // 1d Array of [f_u, f_v, c_u, c_v, k{1, 2}, p{1, 2}, k{3}]. + // Note that this intrinsic corresponds to the images after scaling. + // Camera model: pinhole camera. + // Lens distortion: + // Radial distortion coefficients: k1, k2, k3. + // Tangential distortion coefficients: p1, p2. + // k_{1, 2, 3}, p_{1, 2} follows the same definition as OpenCV. + // https://en.wikipedia.org/wiki/Distortion_(optics) + // https://docs.opencv.org/2.4/doc/tutorials/calib3d/camera_calibration/camera_calibration.html + repeated double intrinsic = 2; + // Camera frame to vehicle frame. + optional Transform extrinsic = 3; + // Camera image size. + optional int32 width = 4; + optional int32 height = 5; + + enum RollingShutterReadOutDirection { + UNKNOWN = 0; + TOP_TO_BOTTOM = 1; + LEFT_TO_RIGHT = 2; + BOTTOM_TO_TOP = 3; + RIGHT_TO_LEFT = 4; + GLOBAL_SHUTTER = 5; + } + optional RollingShutterReadOutDirection rolling_shutter_direction = 6; + + +} + +message LaserCalibration { + optional LaserName.Name name = 1; + // If non-empty, the beam pitch (in radians) is non-uniform. When constructing + // a range image, this mapping is used to map from beam pitch to range image + // row. If this is empty, we assume a uniform distribution. + repeated double beam_inclinations = 2; + // beam_inclination_{min,max} (in radians) are used to determine the mapping. + optional double beam_inclination_min = 3; + optional double beam_inclination_max = 4; + // Lidar frame to vehicle frame. + optional Transform extrinsic = 5; + + +} + +message Context { + // A unique name that identifies the frame sequence. + optional string name = 1; + repeated CameraCalibration camera_calibrations = 2; + repeated LaserCalibration laser_calibrations = 3; + // Some stats for the run segment used. + message Stats { + message ObjectCount { + optional Label.Type type = 1; + // The number of unique objects with the type in the segment. + optional int32 count = 2; + } + repeated ObjectCount laser_object_counts = 1; + repeated ObjectCount camera_object_counts = 5; + // Day, Dawn/Dusk, or Night, determined from sun elevation. + optional string time_of_day = 2; + // Human readable location (e.g. CHD, SF) of the run segment. + optional string location = 3; + // Currently either Sunny or Rain. + optional string weather = 4; + } + optional Stats stats = 4; +} + +// Range image is a 2d tensor. The first dim (row) represents pitch. The second +// dim represents yaw. +// There are two types of range images: +// 1. Raw range image: Raw range image with a non-empty +// 'range_image_pose_compressed' which tells the vehicle pose of each +// range image cell. +// 2. Virtual range image: Range image with an empty +// 'range_image_pose_compressed'. This range image is constructed by +// transforming all lidar points into a fixed vehicle frame (usually the +// vehicle frame of the middle scan). +// NOTE: 'range_image_pose_compressed' is only populated for the first range +// image return. The second return has the exact the same range image pose as +// the first one. +message RangeImage { + // Zlib compressed [H, W, 4] serialized version of MatrixFloat. + // To decompress: + // string val = ZlibDecompress(range_image_compressed); + // MatrixFloat range_image; + // range_image.ParseFromString(val); + // Inner dimensions are: + // * channel 0: range + // * channel 1: intensity + // * channel 2: elongation + // * channel 3: is in any no label zone. + optional bytes range_image_compressed = 2; + + // Lidar point to camera image projections. A point can be projected to + // multiple camera images. We pick the first two at the following order: + // [FRONT, FRONT_LEFT, FRONT_RIGHT, SIDE_LEFT, SIDE_RIGHT]. + // + // Zlib compressed [H, W, 6] serialized version of MatrixInt32. + // To decompress: + // string val = ZlibDecompress(camera_projection_compressed); + // MatrixInt32 camera_projection; + // camera_projection.ParseFromString(val); + // Inner dimensions are: + // * channel 0: CameraName.Name of 1st projection. Set to UNKNOWN if no + // projection. + // * channel 1: x (axis along image width) + // * channel 2: y (axis along image height) + // * channel 3: CameraName.Name of 2nd projection. Set to UNKNOWN if no + // projection. + // * channel 4: x (axis along image width) + // * channel 5: y (axis along image height) + // Note: pixel 0 corresponds to the left edge of the first pixel in the image. + optional bytes camera_projection_compressed = 3; + + // Zlib compressed [H, W, 6] serialized version of MatrixFloat. + // To decompress: + // string val = ZlibDecompress(range_image_pose_compressed); + // MatrixFloat range_image_pose; + // range_image_pose.ParseFromString(val); + // Inner dimensions are [roll, pitch, yaw, x, y, z] represents a transform + // from vehicle frame to global frame for every range image pixel. + // This is ONLY populated for the first return. The second return is assumed + // to have exactly the same range_image_pose_compressed. + // + // The roll, pitch and yaw are specified as 3-2-1 Euler angle rotations, + // meaning that rotating from the navigation to vehicle frame consists of a + // yaw, then pitch and finally roll rotation about the z, y and x axes + // respectively. All rotations use the right hand rule and are positive + // in the counter clockwise direction. + optional bytes range_image_pose_compressed = 4; + + // Zlib compressed [H, W, 5] serialized version of MatrixFloat. + // To decompress: + // string val = ZlibDecompress(range_image_flow_compressed); + // MatrixFloat range_image_flow; + // range_image_flow.ParseFromString(val); + // Inner dimensions are [vx, vy, vz, pointwise class]. + // + // If the point is not annotated with scene flow information, class is set + // to -1. A point is not annotated if it is in a no-label zone or if its label + // bounding box does not have a corresponding match in the previous frame, + // making it infeasible to estimate the motion of the point. + // Otherwise, (vx, vy, vz) are velocity along (x, y, z)-axis for this point + // and class is set to one of the following values: + // -1: no-flow-label, the point has no flow information. + // 0: unlabeled or "background,", i.e., the point is not contained in a + // bounding box. + // 1: vehicle, i.e., the point corresponds to a vehicle label box. + // 2: pedestrian, i.e., the point corresponds to a pedestrian label box. + // 3: sign, i.e., the point corresponds to a sign label box. + // 4: cyclist, i.e., the point corresponds to a cyclist label box. + optional bytes range_image_flow_compressed = 5; + + // Zlib compressed [H, W, 2] serialized version of MatrixInt32. + // To decompress: + // string val = ZlibDecompress(segmentation_label_compressed); + // MatrixInt32 segmentation_label. + // segmentation_label.ParseFromString(val); + // Inner dimensions are [instance_id, semantic_class]. + // + // NOTE: + // 1. Only TOP LiDAR has segmentation labels. + // 2. Not every frame has segmentation labels. This field is not set if a + // frame is not labeled. + // 3. There can be points missing segmentation labels within a labeled frame. + // Their label are set to TYPE_NOT_LABELED when that happens. + optional bytes segmentation_label_compressed = 6; + + // Deprecated, do not use. + optional MatrixFloat range_image = 1 [deprecated = true]; +} + +// Panoptic (instance + semantic) segmentation labels for a given camera image. +// Associations can also be provided between each instance ID and a globally +// unique ID across all frames. +message CameraSegmentationLabel { + // The value used to separate instance_ids from different semantic classes. + // See the panoptic_label field for how this is used. Must be set to be + // greater than the maximum instance_id. + optional int32 panoptic_label_divisor = 1; + // A uint16 png encoded image, with the same resolution as the corresponding + // camera image. Each pixel contains a panoptic segmentation label, which is + // computed as: + // semantic_class_id * panoptic_label_divisor + instance_id. + // We set instance_id = 0 for pixels for which there is no instance_id. + // NOTE: Instance IDs in this label are only consistent within this camera + // image. Use instance_id_to_global_id_mapping to get cross-camera consistent + // instance IDs. + optional bytes panoptic_label = 2; + // A mapping between each panoptic label with an instance_id and a globally + // unique ID across all frames within the same sequence. This can be used to + // match instances across cameras and over time. i.e. instances belonging to + // the same object will map to the same global ID across all frames in the + // same sequence. + // NOTE: These unique IDs are not consistent with other IDs in the dataset, + // e.g. the bounding box IDs. + message InstanceIDToGlobalIDMapping { + optional int32 local_instance_id = 1; + optional int32 global_instance_id = 2; + // If false, the corresponding instance will not have consistent global ids + // between frames. + optional bool is_tracked = 3; + } + repeated InstanceIDToGlobalIDMapping instance_id_to_global_id_mapping = 3; + // The sequence id for this label. The above instance_id_to_global_id_mapping + // is only valid with other labels with the same sequence id. + optional string sequence_id = 4; + + // A uint8 png encoded image, with the same resolution as the corresponding + // camera image. The value on each pixel indicates the number of cameras that + // overlap with this pixel. Used for the weighted Segmentation and Tracking + // Quality (wSTQ) metric. + optional bytes num_cameras_covered = 5; +} + +// All timestamps in this proto are represented as seconds since Unix epoch. +message CameraImage { + optional CameraName.Name name = 1; + // JPEG image. + optional bytes image = 2; + // SDC pose. + optional Transform pose = 3; + // SDC velocity at 'pose_timestamp' below. The velocity value is represented + // at *global* frame. + // With this velocity, the pose can be extrapolated. + // r(t+dt) = r(t) + dr/dt * dt where dr/dt = v_{x,y,z}. + // dR(t)/dt = W*R(t) where W = SkewSymmetric(w_{x,y,z}) + // This differential equation solves to: R(t) = exp(Wt)*R(0) if W is constant. + // When dt is small: R(t+dt) = (I+W*dt)R(t) + // r(t) = (x(t), y(t), z(t)) is vehicle location at t in the global frame. + // R(t) = Rotation Matrix (3x3) from the body frame to the global frame at t. + // SkewSymmetric(x,y,z) is defined as the cross-product matrix in the + // following: + // https://en.wikipedia.org/wiki/Cross_product#Conversion_to_matrix_multiplication + optional Velocity velocity = 4; + // Timestamp of the `pose` above. + optional double pose_timestamp = 5; + + // Rolling shutter params. + // The following explanation assumes left->right rolling shutter. + // + // Rolling shutter cameras expose and read the image column by column, offset + // by the read out time for each column. The desired timestamp for each column + // is the middle of the exposure of that column as outlined below for an image + // with 3 columns: + // ------time------> + // |---- exposure col 1----| read | + // -------|---- exposure col 2----| read | + // --------------|---- exposure col 3----| read | + // ^trigger time ^readout end time + // ^time for row 1 (= middle of exposure of row 1) + // ^time image center (= middle of exposure of middle row) + // Shutter duration in seconds. Exposure time per column. + optional double shutter = 6; + // Time when the sensor was triggered and when last readout finished. + // The difference between trigger time and readout done time includes + // the exposure time and the actual sensor readout time. + optional double camera_trigger_time = 7; + optional double camera_readout_done_time = 8; + + // Panoptic segmentation labels for this camera image. + // NOTE: Not every image has panoptic segmentation labels. + optional CameraSegmentationLabel camera_segmentation_label = 10; + + +} + +// The camera labels associated with a given camera image. This message +// indicates the ground truth information for the camera image +// recorded by the given camera. If there are no labeled objects in the image, +// then the labels field is empty. +message CameraLabels { + optional CameraName.Name name = 1; + repeated Label labels = 2; +} + +message Laser { + optional LaserName.Name name = 1; + optional RangeImage ri_return1 = 2; + optional RangeImage ri_return2 = 3; +} + +message Frame { + // The following field numbers are reserved for third-party extensions. Users + // may declare new fields in that range in their own .proto files without + // having to edit the original file. + extensions 1000 to max; + + // This context is the same for all frames belong to the same driving run + // segment. Use context.name to identify frames belong to the same driving + // segment. We do not store all frames from one driving segment in one proto + // to avoid huge protos. + optional Context context = 1; + + // Frame start time, which is the timestamp of the first top LiDAR scan + // within this frame. Note that this timestamp does not correspond to the + // provided vehicle pose (pose). + optional int64 timestamp_micros = 2; + + // Frame vehicle pose. Note that unlike in CameraImage, the Frame pose does + // not correspond to the provided timestamp (timestamp_micros). Instead, it + // roughly (but not exactly) corresponds to the vehicle pose in the middle of + // the given frame. The frame vehicle pose defines the coordinate system which + // the 3D laser labels are defined in. + optional Transform pose = 3; + + // The camera images. + repeated CameraImage images = 4; + + // The LiDAR sensor data. + repeated Laser lasers = 5; + + // Native 3D labels that correspond to the LiDAR sensor data. The 3D labels + // are defined w.r.t. the frame vehicle pose coordinate system (pose). + repeated Label laser_labels = 6; + + // The native 3D LiDAR labels (laser_labels) projected to camera images. A + // projected label is the smallest image axis aligned rectangle that can cover + // all projected points from the 3d LiDAR label. The projected label is + // ignored if the projection is fully outside a camera image. The projected + // label is clamped to the camera image if it is partially outside. + repeated CameraLabels projected_lidar_labels = 9; + + // Native 2D camera labels. Note that if a camera identified by + // CameraLabels.name has an entry in this field, then it has been labeled, + // even though it is possible that there are no labeled objects in the + // corresponding image, which is identified by a zero sized + // CameraLabels.labels. + repeated CameraLabels camera_labels = 8; + + // No label zones in the *global* frame. + repeated Polygon2dProto no_label_zones = 7; + + // Map features. Only the first frame in a segment will contain map data. This + // field will be empty for other frames as the map is identical for all + // frames. + repeated MapFeature map_features = 10; + + // Map pose offset. This offset must be added to lidar points from this frame + // to compensate for pose drift and align with the map features. + optional Vector3d map_pose_offset = 11; +} \ No newline at end of file diff --git a/protos/dataset_pb2.py b/protos/dataset_pb2.py new file mode 100644 index 0000000..ce1c6a6 --- /dev/null +++ b/protos/dataset_pb2.py @@ -0,0 +1,87 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE +# source: dataset.proto +# Protobuf Python Version: 6.30.2 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 6, + 30, + 2, + '', + 'dataset.proto' +) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +import protos.label_pb2 as label__pb2 +import protos.map_pb2 as map__pb2 +import protos.vector_pb2 as vector__pb2 + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\rdataset.proto\x12\x12waymo.open_dataset\x1a\x0blabel.proto\x1a\tmap.proto\x1a\x0cvector.proto\"\x1b\n\x0bMatrixShape\x12\x0c\n\x04\x64ims\x18\x01 \x03(\x05\"O\n\x0bMatrixFloat\x12\x10\n\x04\x64\x61ta\x18\x01 \x03(\x02\x42\x02\x10\x01\x12.\n\x05shape\x18\x02 \x01(\x0b\x32\x1f.waymo.open_dataset.MatrixShape\"O\n\x0bMatrixInt32\x12\x10\n\x04\x64\x61ta\x18\x01 \x03(\x05\x42\x02\x10\x01\x12.\n\x05shape\x18\x02 \x01(\x0b\x32\x1f.waymo.open_dataset.MatrixShape\"\x96\x01\n\nCameraName\"\x87\x01\n\x04Name\x12\x0b\n\x07UNKNOWN\x10\x00\x12\t\n\x05\x46RONT\x10\x01\x12\x0e\n\nFRONT_LEFT\x10\x02\x12\x0f\n\x0b\x46RONT_RIGHT\x10\x03\x12\r\n\tSIDE_LEFT\x10\x04\x12\x0e\n\nSIDE_RIGHT\x10\x05\x12\r\n\tREAR_LEFT\x10\x06\x12\x08\n\x04REAR\x10\x07\x12\x0e\n\nREAR_RIGHT\x10\x08\"]\n\tLaserName\"P\n\x04Name\x12\x0b\n\x07UNKNOWN\x10\x00\x12\x07\n\x03TOP\x10\x01\x12\t\n\x05\x46RONT\x10\x02\x12\r\n\tSIDE_LEFT\x10\x03\x12\x0e\n\nSIDE_RIGHT\x10\x04\x12\x08\n\x04REAR\x10\x05\"\x1e\n\tTransform\x12\x11\n\ttransform\x18\x01 \x03(\x01\"X\n\x08Velocity\x12\x0b\n\x03v_x\x18\x01 \x01(\x02\x12\x0b\n\x03v_y\x18\x02 \x01(\x02\x12\x0b\n\x03v_z\x18\x03 \x01(\x02\x12\x0b\n\x03w_x\x18\x04 \x01(\x01\x12\x0b\n\x03w_y\x18\x05 \x01(\x01\x12\x0b\n\x03w_z\x18\x06 \x01(\x01\"\xa3\x03\n\x11\x43\x61meraCalibration\x12\x31\n\x04name\x18\x01 \x01(\x0e\x32#.waymo.open_dataset.CameraName.Name\x12\x11\n\tintrinsic\x18\x02 \x03(\x01\x12\x30\n\textrinsic\x18\x03 \x01(\x0b\x32\x1d.waymo.open_dataset.Transform\x12\r\n\x05width\x18\x04 \x01(\x05\x12\x0e\n\x06height\x18\x05 \x01(\x05\x12g\n\x19rolling_shutter_direction\x18\x06 \x01(\x0e\x32\x44.waymo.open_dataset.CameraCalibration.RollingShutterReadOutDirection\"\x8d\x01\n\x1eRollingShutterReadOutDirection\x12\x0b\n\x07UNKNOWN\x10\x00\x12\x11\n\rTOP_TO_BOTTOM\x10\x01\x12\x11\n\rLEFT_TO_RIGHT\x10\x02\x12\x11\n\rBOTTOM_TO_TOP\x10\x03\x12\x11\n\rRIGHT_TO_LEFT\x10\x04\x12\x12\n\x0eGLOBAL_SHUTTER\x10\x05\"\xcd\x01\n\x10LaserCalibration\x12\x30\n\x04name\x18\x01 \x01(\x0e\x32\".waymo.open_dataset.LaserName.Name\x12\x19\n\x11\x62\x65\x61m_inclinations\x18\x02 \x03(\x01\x12\x1c\n\x14\x62\x65\x61m_inclination_min\x18\x03 \x01(\x01\x12\x1c\n\x14\x62\x65\x61m_inclination_max\x18\x04 \x01(\x01\x12\x30\n\textrinsic\x18\x05 \x01(\x0b\x32\x1d.waymo.open_dataset.Transform\"\xf6\x03\n\x07\x43ontext\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x42\n\x13\x63\x61mera_calibrations\x18\x02 \x03(\x0b\x32%.waymo.open_dataset.CameraCalibration\x12@\n\x12laser_calibrations\x18\x03 \x03(\x0b\x32$.waymo.open_dataset.LaserCalibration\x12\x30\n\x05stats\x18\x04 \x01(\x0b\x32!.waymo.open_dataset.Context.Stats\x1a\xa4\x02\n\x05Stats\x12J\n\x13laser_object_counts\x18\x01 \x03(\x0b\x32-.waymo.open_dataset.Context.Stats.ObjectCount\x12K\n\x14\x63\x61mera_object_counts\x18\x05 \x03(\x0b\x32-.waymo.open_dataset.Context.Stats.ObjectCount\x12\x13\n\x0btime_of_day\x18\x02 \x01(\t\x12\x10\n\x08location\x18\x03 \x01(\t\x12\x0f\n\x07weather\x18\x04 \x01(\t\x1aJ\n\x0bObjectCount\x12,\n\x04type\x18\x01 \x01(\x0e\x32\x1e.waymo.open_dataset.Label.Type\x12\r\n\x05\x63ount\x18\x02 \x01(\x05\"\xfd\x01\n\nRangeImage\x12\x1e\n\x16range_image_compressed\x18\x02 \x01(\x0c\x12$\n\x1c\x63\x61mera_projection_compressed\x18\x03 \x01(\x0c\x12#\n\x1brange_image_pose_compressed\x18\x04 \x01(\x0c\x12#\n\x1brange_image_flow_compressed\x18\x05 \x01(\x0c\x12%\n\x1dsegmentation_label_compressed\x18\x06 \x01(\x0c\x12\x38\n\x0brange_image\x18\x01 \x01(\x0b\x32\x1f.waymo.open_dataset.MatrixFloatB\x02\x18\x01\"\xe0\x02\n\x17\x43\x61meraSegmentationLabel\x12\x1e\n\x16panoptic_label_divisor\x18\x01 \x01(\x05\x12\x16\n\x0epanoptic_label\x18\x02 \x01(\x0c\x12q\n instance_id_to_global_id_mapping\x18\x03 \x03(\x0b\x32G.waymo.open_dataset.CameraSegmentationLabel.InstanceIDToGlobalIDMapping\x12\x13\n\x0bsequence_id\x18\x04 \x01(\t\x12\x1b\n\x13num_cameras_covered\x18\x05 \x01(\x0c\x1ah\n\x1bInstanceIDToGlobalIDMapping\x12\x19\n\x11local_instance_id\x18\x01 \x01(\x05\x12\x1a\n\x12global_instance_id\x18\x02 \x01(\x05\x12\x12\n\nis_tracked\x18\x03 \x01(\x08\"\xe4\x02\n\x0b\x43\x61meraImage\x12\x31\n\x04name\x18\x01 \x01(\x0e\x32#.waymo.open_dataset.CameraName.Name\x12\r\n\x05image\x18\x02 \x01(\x0c\x12+\n\x04pose\x18\x03 \x01(\x0b\x32\x1d.waymo.open_dataset.Transform\x12.\n\x08velocity\x18\x04 \x01(\x0b\x32\x1c.waymo.open_dataset.Velocity\x12\x16\n\x0epose_timestamp\x18\x05 \x01(\x01\x12\x0f\n\x07shutter\x18\x06 \x01(\x01\x12\x1b\n\x13\x63\x61mera_trigger_time\x18\x07 \x01(\x01\x12 \n\x18\x63\x61mera_readout_done_time\x18\x08 \x01(\x01\x12N\n\x19\x63\x61mera_segmentation_label\x18\n \x01(\x0b\x32+.waymo.open_dataset.CameraSegmentationLabel\"l\n\x0c\x43\x61meraLabels\x12\x31\n\x04name\x18\x01 \x01(\x0e\x32#.waymo.open_dataset.CameraName.Name\x12)\n\x06labels\x18\x02 \x03(\x0b\x32\x19.waymo.open_dataset.Label\"\xa1\x01\n\x05Laser\x12\x30\n\x04name\x18\x01 \x01(\x0e\x32\".waymo.open_dataset.LaserName.Name\x12\x32\n\nri_return1\x18\x02 \x01(\x0b\x32\x1e.waymo.open_dataset.RangeImage\x12\x32\n\nri_return2\x18\x03 \x01(\x0b\x32\x1e.waymo.open_dataset.RangeImage\"\xb8\x04\n\x05\x46rame\x12,\n\x07\x63ontext\x18\x01 \x01(\x0b\x32\x1b.waymo.open_dataset.Context\x12\x18\n\x10timestamp_micros\x18\x02 \x01(\x03\x12+\n\x04pose\x18\x03 \x01(\x0b\x32\x1d.waymo.open_dataset.Transform\x12/\n\x06images\x18\x04 \x03(\x0b\x32\x1f.waymo.open_dataset.CameraImage\x12)\n\x06lasers\x18\x05 \x03(\x0b\x32\x19.waymo.open_dataset.Laser\x12/\n\x0claser_labels\x18\x06 \x03(\x0b\x32\x19.waymo.open_dataset.Label\x12@\n\x16projected_lidar_labels\x18\t \x03(\x0b\x32 .waymo.open_dataset.CameraLabels\x12\x37\n\rcamera_labels\x18\x08 \x03(\x0b\x32 .waymo.open_dataset.CameraLabels\x12:\n\x0eno_label_zones\x18\x07 \x03(\x0b\x32\".waymo.open_dataset.Polygon2dProto\x12\x34\n\x0cmap_features\x18\n \x03(\x0b\x32\x1e.waymo.open_dataset.MapFeature\x12\x35\n\x0fmap_pose_offset\x18\x0b \x01(\x0b\x32\x1c.waymo.open_dataset.Vector3d*\t\x08\xe8\x07\x10\x80\x80\x80\x80\x02') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'dataset_pb2', _globals) +if not _descriptor._USE_C_DESCRIPTORS: + DESCRIPTOR._loaded_options = None + _globals['_MATRIXFLOAT'].fields_by_name['data']._loaded_options = None + _globals['_MATRIXFLOAT'].fields_by_name['data']._serialized_options = b'\020\001' + _globals['_MATRIXINT32'].fields_by_name['data']._loaded_options = None + _globals['_MATRIXINT32'].fields_by_name['data']._serialized_options = b'\020\001' + _globals['_RANGEIMAGE'].fields_by_name['range_image']._loaded_options = None + _globals['_RANGEIMAGE'].fields_by_name['range_image']._serialized_options = b'\030\001' + _globals['_MATRIXSHAPE']._serialized_start=75 + _globals['_MATRIXSHAPE']._serialized_end=102 + _globals['_MATRIXFLOAT']._serialized_start=104 + _globals['_MATRIXFLOAT']._serialized_end=183 + _globals['_MATRIXINT32']._serialized_start=185 + _globals['_MATRIXINT32']._serialized_end=264 + _globals['_CAMERANAME']._serialized_start=267 + _globals['_CAMERANAME']._serialized_end=417 + _globals['_CAMERANAME_NAME']._serialized_start=282 + _globals['_CAMERANAME_NAME']._serialized_end=417 + _globals['_LASERNAME']._serialized_start=419 + _globals['_LASERNAME']._serialized_end=512 + _globals['_LASERNAME_NAME']._serialized_start=432 + _globals['_LASERNAME_NAME']._serialized_end=512 + _globals['_TRANSFORM']._serialized_start=514 + _globals['_TRANSFORM']._serialized_end=544 + _globals['_VELOCITY']._serialized_start=546 + _globals['_VELOCITY']._serialized_end=634 + _globals['_CAMERACALIBRATION']._serialized_start=637 + _globals['_CAMERACALIBRATION']._serialized_end=1056 + _globals['_CAMERACALIBRATION_ROLLINGSHUTTERREADOUTDIRECTION']._serialized_start=915 + _globals['_CAMERACALIBRATION_ROLLINGSHUTTERREADOUTDIRECTION']._serialized_end=1056 + _globals['_LASERCALIBRATION']._serialized_start=1059 + _globals['_LASERCALIBRATION']._serialized_end=1264 + _globals['_CONTEXT']._serialized_start=1267 + _globals['_CONTEXT']._serialized_end=1769 + _globals['_CONTEXT_STATS']._serialized_start=1477 + _globals['_CONTEXT_STATS']._serialized_end=1769 + _globals['_CONTEXT_STATS_OBJECTCOUNT']._serialized_start=1695 + _globals['_CONTEXT_STATS_OBJECTCOUNT']._serialized_end=1769 + _globals['_RANGEIMAGE']._serialized_start=1772 + _globals['_RANGEIMAGE']._serialized_end=2025 + _globals['_CAMERASEGMENTATIONLABEL']._serialized_start=2028 + _globals['_CAMERASEGMENTATIONLABEL']._serialized_end=2380 + _globals['_CAMERASEGMENTATIONLABEL_INSTANCEIDTOGLOBALIDMAPPING']._serialized_start=2276 + _globals['_CAMERASEGMENTATIONLABEL_INSTANCEIDTOGLOBALIDMAPPING']._serialized_end=2380 + _globals['_CAMERAIMAGE']._serialized_start=2383 + _globals['_CAMERAIMAGE']._serialized_end=2739 + _globals['_CAMERALABELS']._serialized_start=2741 + _globals['_CAMERALABELS']._serialized_end=2849 + _globals['_LASER']._serialized_start=2852 + _globals['_LASER']._serialized_end=3013 + _globals['_FRAME']._serialized_start=3016 + _globals['_FRAME']._serialized_end=3584 +# @@protoc_insertion_point(module_scope) diff --git a/protos/e2e.proto b/protos/e2e.proto new file mode 100644 index 0000000..0550d65 --- /dev/null +++ b/protos/e2e.proto @@ -0,0 +1,90 @@ +/* Copyright 2025 The Waymo Open Dataset Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +// This proto contains the Waymo Open Dataset End-to-End Driving (E2ED) data +// format. + +syntax = "proto2"; + +package waymo.open_dataset; + +import "dataset.proto"; + +message E2EDFrame { + // This proto contains the Waymo Open Dataset End-to-End Driving (E2ED) data + // format. + + // WOD frame object populated with camera image, calibration, and metadata. + // Populated fields: + // frame.context + // .name = unique identifier for this frame. + // .camera_calibrations = calibration metadata for all cameras. + // All other fields in `frame.context` are unused. + // frame.timestamp_micros = current frame timestamp. + // frame.images = camera images. + // All other fields in `frame` are unused. + // For details about frame.context.camera_calibrations and frame.images, see + // the CameraCalibration and CameraImage protos. + optional waymo.open_dataset.Frame frame = 1; + + // t = (0, 5s] future log states at 4Hz. Only position fields are populated. + // Future position x,y coords are used as prediction targets. z coords are + // included for visualization, but are not used as prediction targets. + optional EgoTrajectoryStates future_states = 5; + // t = (-4s, 0] past history states at 4Hz. + optional EgoTrajectoryStates past_states = 6; + // Driving intent of the ego-vehicle at this timestep. + optional EgoIntent.Intent intent = 7; + + // Future trajectories with human-labeled rater scores. Only x,y position + // fields are populated, along with the rated score. This field is valid + // for only a subset of frames. For these frames, there are up to 3 rated + // trajectories. In all other frames, this field is marked as invalid with + // assigned rater scores of -1 or left empty. Valid scores range from [0, 10]. + repeated EgoTrajectoryStates preference_trajectories = 8; + + +} + +message EgoTrajectoryStates { + // Position in meters. Right-handed coordinate system. + // +x = forward, +y = left, +z = up. + // The origin (0, 0, 0) is at the middle of the ego vehicle's rear axle. + repeated float pos_x = 1 [packed = true]; + repeated float pos_y = 2 [packed = true]; + repeated float pos_z = 3 [packed = true]; + + // Velocity in m/s. + repeated float vel_x = 4 [packed = true]; + repeated float vel_y = 5 [packed = true]; + + // Acceleration in m/s^2. + repeated float accel_x = 6 [packed = true]; + repeated float accel_y = 7 [packed = true]; + + // Only populated for trajectories with human-labeled scores. + // Valid scores range from [0, 10], inclusive. + optional float preference_score = 8; +} + +message EgoIntent { + // Driving intent of the ego-vehicle at a given timestep. + enum Intent { + UNKNOWN = 0; + GO_STRAIGHT = 1; + GO_LEFT = 2; + GO_RIGHT = 3; + } +} \ No newline at end of file diff --git a/protos/e2e_pb2.py b/protos/e2e_pb2.py new file mode 100644 index 0000000..b72617f --- /dev/null +++ b/protos/e2e_pb2.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE +# source: e2e.proto +# Protobuf Python Version: 6.30.2 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 6, + 30, + 2, + '', + 'e2e.proto' +) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +import protos.dataset_pb2 as dataset__pb2 + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\te2e.proto\x12\x12waymo.open_dataset\x1a\rdataset.proto\"\xb3\x02\n\tE2EDFrame\x12(\n\x05\x66rame\x18\x01 \x01(\x0b\x32\x19.waymo.open_dataset.Frame\x12>\n\rfuture_states\x18\x05 \x01(\x0b\x32\'.waymo.open_dataset.EgoTrajectoryStates\x12<\n\x0bpast_states\x18\x06 \x01(\x0b\x32\'.waymo.open_dataset.EgoTrajectoryStates\x12\x34\n\x06intent\x18\x07 \x01(\x0e\x32$.waymo.open_dataset.EgoIntent.Intent\x12H\n\x17preference_trajectories\x18\x08 \x03(\x0b\x32\'.waymo.open_dataset.EgoTrajectoryStates\"\xb8\x01\n\x13\x45goTrajectoryStates\x12\x11\n\x05pos_x\x18\x01 \x03(\x02\x42\x02\x10\x01\x12\x11\n\x05pos_y\x18\x02 \x03(\x02\x42\x02\x10\x01\x12\x11\n\x05pos_z\x18\x03 \x03(\x02\x42\x02\x10\x01\x12\x11\n\x05vel_x\x18\x04 \x03(\x02\x42\x02\x10\x01\x12\x11\n\x05vel_y\x18\x05 \x03(\x02\x42\x02\x10\x01\x12\x13\n\x07\x61\x63\x63\x65l_x\x18\x06 \x03(\x02\x42\x02\x10\x01\x12\x13\n\x07\x61\x63\x63\x65l_y\x18\x07 \x03(\x02\x42\x02\x10\x01\x12\x18\n\x10preference_score\x18\x08 \x01(\x02\"N\n\tEgoIntent\"A\n\x06Intent\x12\x0b\n\x07UNKNOWN\x10\x00\x12\x0f\n\x0bGO_STRAIGHT\x10\x01\x12\x0b\n\x07GO_LEFT\x10\x02\x12\x0c\n\x08GO_RIGHT\x10\x03') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'e2e_pb2', _globals) +if not _descriptor._USE_C_DESCRIPTORS: + DESCRIPTOR._loaded_options = None + _globals['_EGOTRAJECTORYSTATES'].fields_by_name['pos_x']._loaded_options = None + _globals['_EGOTRAJECTORYSTATES'].fields_by_name['pos_x']._serialized_options = b'\020\001' + _globals['_EGOTRAJECTORYSTATES'].fields_by_name['pos_y']._loaded_options = None + _globals['_EGOTRAJECTORYSTATES'].fields_by_name['pos_y']._serialized_options = b'\020\001' + _globals['_EGOTRAJECTORYSTATES'].fields_by_name['pos_z']._loaded_options = None + _globals['_EGOTRAJECTORYSTATES'].fields_by_name['pos_z']._serialized_options = b'\020\001' + _globals['_EGOTRAJECTORYSTATES'].fields_by_name['vel_x']._loaded_options = None + _globals['_EGOTRAJECTORYSTATES'].fields_by_name['vel_x']._serialized_options = b'\020\001' + _globals['_EGOTRAJECTORYSTATES'].fields_by_name['vel_y']._loaded_options = None + _globals['_EGOTRAJECTORYSTATES'].fields_by_name['vel_y']._serialized_options = b'\020\001' + _globals['_EGOTRAJECTORYSTATES'].fields_by_name['accel_x']._loaded_options = None + _globals['_EGOTRAJECTORYSTATES'].fields_by_name['accel_x']._serialized_options = b'\020\001' + _globals['_EGOTRAJECTORYSTATES'].fields_by_name['accel_y']._loaded_options = None + _globals['_EGOTRAJECTORYSTATES'].fields_by_name['accel_y']._serialized_options = b'\020\001' + _globals['_E2EDFRAME']._serialized_start=49 + _globals['_E2EDFRAME']._serialized_end=356 + _globals['_EGOTRAJECTORYSTATES']._serialized_start=359 + _globals['_EGOTRAJECTORYSTATES']._serialized_end=543 + _globals['_EGOINTENT']._serialized_start=545 + _globals['_EGOINTENT']._serialized_end=623 + _globals['_EGOINTENT_INTENT']._serialized_start=558 + _globals['_EGOINTENT_INTENT']._serialized_end=623 +# @@protoc_insertion_point(module_scope) diff --git a/protos/keypoint.proto b/protos/keypoint.proto new file mode 100644 index 0000000..8a7042e --- /dev/null +++ b/protos/keypoint.proto @@ -0,0 +1,111 @@ +/* Copyright 2021 The Waymo Open Dataset Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +syntax = "proto2"; + +package waymo.open_dataset.keypoints; + +import "vector.proto"; + +// Attributes related to the keypoint's visibility. +message KeypointVisibility { + // Is true, if the keypoint is occluded by any object, a body part or its + // location can be determined only with large uncertainty. + // Is false if the keypoint is clearly visible. + optional bool is_occluded = 1; +} + +// Keypoint relative to a specific camera image. +message Keypoint2d { + // The following field numbers are reserved for third-party extensions. Users + // may declare new fields in that range in their own .proto files without + // having to edit the original file. + extensions 1000 to max; + + // Camera image coordinates (in pixels, x=0, y=0 is top-left pixel). + optional Vector2d location_px = 1; + // Visibility attributes determined based on camera image only. + optional KeypointVisibility visibility = 2; +} + +message Keypoint3d { + // The following field numbers are reserved for third-party extensions. Users + // may declare new fields in that range in their own .proto files without + // having to edit the original file. + extensions 1000 to max; + + // A 3D coordinate in vehicle or camera frame (depending which message it is + // part of - LaserKeypoint or CameraKeypoint). + optional Vector3d location_m = 1; + // Visibility attributes determined based on all available data (camera image + // and or lidar). + optional KeypointVisibility visibility = 2; +} + +// All types of keypoints except (NOSE and HEAD_CENTER) are defined as the 3D +// location where corresponing bones meet - inside the body. +// We use person-centric coordinates in this task. For example, the person’s +// right shoulder will be located on the left side of the image for frontal +// views and on the right side of the image for back views. Similarly for the +// other body joints. +enum KeypointType { + KEYPOINT_TYPE_UNSPECIFIED = 0; + // Tip of nose. + KEYPOINT_TYPE_NOSE = 1; + KEYPOINT_TYPE_LEFT_SHOULDER = 5; + KEYPOINT_TYPE_LEFT_ELBOW = 6; + KEYPOINT_TYPE_LEFT_WRIST = 7; + KEYPOINT_TYPE_LEFT_HIP = 8; + KEYPOINT_TYPE_LEFT_KNEE = 9; + KEYPOINT_TYPE_LEFT_ANKLE = 10; + KEYPOINT_TYPE_RIGHT_SHOULDER = 13; + KEYPOINT_TYPE_RIGHT_ELBOW = 14; + KEYPOINT_TYPE_RIGHT_WRIST = 15; + KEYPOINT_TYPE_RIGHT_HIP = 16; + KEYPOINT_TYPE_RIGHT_KNEE = 17; + KEYPOINT_TYPE_RIGHT_ANKLE = 18; + // Center of the forehead area. + KEYPOINT_TYPE_FOREHEAD = 19; + // A point in the center of head - a point in the middle between two ears. + // The nose and head center together create an imaginary line in the direction + // that the person is looking (i.e. head orientation). + KEYPOINT_TYPE_HEAD_CENTER = 20; +} + +// A 2D keypoint on a specific camera. +message CameraKeypoint { + optional KeypointType type = 1; + // Camera coordinates. + optional Keypoint2d keypoint_2d = 2; + // 3D keypoint in camera coordinate frame. + optional Keypoint3d keypoint_3d = 3; +} + +// All 2D keypoints for a camera label (object). +message CameraKeypoints { + repeated CameraKeypoint keypoint = 1; +} + +// A 3D keypoint. +message LaserKeypoint { + optional KeypointType type = 1; + // 3D keypoint in vehicle coordinate frame. + optional Keypoint3d keypoint_3d = 2; +} + +// All 3D keypoints for a laser label (object). +message LaserKeypoints { + repeated LaserKeypoint keypoint = 1; +} \ No newline at end of file diff --git a/protos/keypoint_pb2.py b/protos/keypoint_pb2.py new file mode 100644 index 0000000..fd05f96 --- /dev/null +++ b/protos/keypoint_pb2.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE +# source: keypoint.proto +# Protobuf Python Version: 6.30.2 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 6, + 30, + 2, + '', + 'keypoint.proto' +) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +import protos.vector_pb2 as vector__pb2 + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0ekeypoint.proto\x12\x1cwaymo.open_dataset.keypoints\x1a\x0cvector.proto\")\n\x12KeypointVisibility\x12\x13\n\x0bis_occluded\x18\x01 \x01(\x08\"\x90\x01\n\nKeypoint2d\x12\x31\n\x0blocation_px\x18\x01 \x01(\x0b\x32\x1c.waymo.open_dataset.Vector2d\x12\x44\n\nvisibility\x18\x02 \x01(\x0b\x32\x30.waymo.open_dataset.keypoints.KeypointVisibility*\t\x08\xe8\x07\x10\x80\x80\x80\x80\x02\"\x8f\x01\n\nKeypoint3d\x12\x30\n\nlocation_m\x18\x01 \x01(\x0b\x32\x1c.waymo.open_dataset.Vector3d\x12\x44\n\nvisibility\x18\x02 \x01(\x0b\x32\x30.waymo.open_dataset.keypoints.KeypointVisibility*\t\x08\xe8\x07\x10\x80\x80\x80\x80\x02\"\xc8\x01\n\x0e\x43\x61meraKeypoint\x12\x38\n\x04type\x18\x01 \x01(\x0e\x32*.waymo.open_dataset.keypoints.KeypointType\x12=\n\x0bkeypoint_2d\x18\x02 \x01(\x0b\x32(.waymo.open_dataset.keypoints.Keypoint2d\x12=\n\x0bkeypoint_3d\x18\x03 \x01(\x0b\x32(.waymo.open_dataset.keypoints.Keypoint3d\"Q\n\x0f\x43\x61meraKeypoints\x12>\n\x08keypoint\x18\x01 \x03(\x0b\x32,.waymo.open_dataset.keypoints.CameraKeypoint\"\x88\x01\n\rLaserKeypoint\x12\x38\n\x04type\x18\x01 \x01(\x0e\x32*.waymo.open_dataset.keypoints.KeypointType\x12=\n\x0bkeypoint_3d\x18\x02 \x01(\x0b\x32(.waymo.open_dataset.keypoints.Keypoint3d\"O\n\x0eLaserKeypoints\x12=\n\x08keypoint\x18\x01 \x03(\x0b\x32+.waymo.open_dataset.keypoints.LaserKeypoint*\xee\x03\n\x0cKeypointType\x12\x1d\n\x19KEYPOINT_TYPE_UNSPECIFIED\x10\x00\x12\x16\n\x12KEYPOINT_TYPE_NOSE\x10\x01\x12\x1f\n\x1bKEYPOINT_TYPE_LEFT_SHOULDER\x10\x05\x12\x1c\n\x18KEYPOINT_TYPE_LEFT_ELBOW\x10\x06\x12\x1c\n\x18KEYPOINT_TYPE_LEFT_WRIST\x10\x07\x12\x1a\n\x16KEYPOINT_TYPE_LEFT_HIP\x10\x08\x12\x1b\n\x17KEYPOINT_TYPE_LEFT_KNEE\x10\t\x12\x1c\n\x18KEYPOINT_TYPE_LEFT_ANKLE\x10\n\x12 \n\x1cKEYPOINT_TYPE_RIGHT_SHOULDER\x10\r\x12\x1d\n\x19KEYPOINT_TYPE_RIGHT_ELBOW\x10\x0e\x12\x1d\n\x19KEYPOINT_TYPE_RIGHT_WRIST\x10\x0f\x12\x1b\n\x17KEYPOINT_TYPE_RIGHT_HIP\x10\x10\x12\x1c\n\x18KEYPOINT_TYPE_RIGHT_KNEE\x10\x11\x12\x1d\n\x19KEYPOINT_TYPE_RIGHT_ANKLE\x10\x12\x12\x1a\n\x16KEYPOINT_TYPE_FOREHEAD\x10\x13\x12\x1d\n\x19KEYPOINT_TYPE_HEAD_CENTER\x10\x14') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'keypoint_pb2', _globals) +if not _descriptor._USE_C_DESCRIPTORS: + DESCRIPTOR._loaded_options = None + _globals['_KEYPOINTTYPE']._serialized_start=905 + _globals['_KEYPOINTTYPE']._serialized_end=1399 + _globals['_KEYPOINTVISIBILITY']._serialized_start=62 + _globals['_KEYPOINTVISIBILITY']._serialized_end=103 + _globals['_KEYPOINT2D']._serialized_start=106 + _globals['_KEYPOINT2D']._serialized_end=250 + _globals['_KEYPOINT3D']._serialized_start=253 + _globals['_KEYPOINT3D']._serialized_end=396 + _globals['_CAMERAKEYPOINT']._serialized_start=399 + _globals['_CAMERAKEYPOINT']._serialized_end=599 + _globals['_CAMERAKEYPOINTS']._serialized_start=601 + _globals['_CAMERAKEYPOINTS']._serialized_end=682 + _globals['_LASERKEYPOINT']._serialized_start=685 + _globals['_LASERKEYPOINT']._serialized_end=821 + _globals['_LASERKEYPOINTS']._serialized_start=823 + _globals['_LASERKEYPOINTS']._serialized_end=902 +# @@protoc_insertion_point(module_scope) diff --git a/protos/label.proto b/protos/label.proto new file mode 100644 index 0000000..da1b611 --- /dev/null +++ b/protos/label.proto @@ -0,0 +1,145 @@ +/* Copyright 2019 The Waymo Open Dataset Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +syntax = "proto2"; + +package waymo.open_dataset; + +import "keypoint.proto"; + +message Label { + // Upright box, zero pitch and roll. + message Box { + // Box coordinates in vehicle frame. + optional double center_x = 1; + optional double center_y = 2; + optional double center_z = 3; + + // Dimensions of the box. length: dim x. width: dim y. height: dim z. + optional double length = 5; + optional double width = 4; + optional double height = 6; + + // The heading of the bounding box (in radians). The heading is the angle + // required to rotate +x to the surface normal of the box front face. It is + // normalized to [-pi, pi). + optional double heading = 7; + + enum Type { + TYPE_UNKNOWN = 0; + // 7-DOF 3D (a.k.a upright 3D box). + TYPE_3D = 1; + // 5-DOF 2D. Mostly used for laser top down representation. + TYPE_2D = 2; + // Axis aligned 2D. Mostly used for image. + TYPE_AA_2D = 3; + } + } + + optional Box box = 1; + + message Metadata { + optional double speed_x = 1; + optional double speed_y = 2; + optional double speed_z = 5; + optional double accel_x = 3; + optional double accel_y = 4; + optional double accel_z = 6; + } + optional Metadata metadata = 2; + + enum Type { + TYPE_UNKNOWN = 0; + TYPE_VEHICLE = 1; + TYPE_PEDESTRIAN = 2; + TYPE_SIGN = 3; + TYPE_CYCLIST = 4; + } + optional Type type = 3; + // Object ID. + optional string id = 4; + + // The difficulty level of this label. The higher the level, the harder it is. + enum DifficultyLevel { + UNKNOWN = 0; + LEVEL_1 = 1; + LEVEL_2 = 2; + } + + // Difficulty level for detection problem. + optional DifficultyLevel detection_difficulty_level = 5; + // Difficulty level for tracking problem. + optional DifficultyLevel tracking_difficulty_level = 6; + + // The total number of lidar points in this box. + optional int32 num_lidar_points_in_box = 7; + // The total number of top lidar points in this box. + optional int32 num_top_lidar_points_in_box = 13; + + oneof keypoints_oneof { + // Used if the Label is a part of `Frame.laser_labels`. + keypoints.LaserKeypoints laser_keypoints = 8; + // Used if the Label is a part of `Frame.camera_labels`. + keypoints.CameraKeypoints camera_keypoints = 9; + } + + // Information to cross reference between labels for different modalities. + message Association { + // Currently only CameraLabels with class `TYPE_PEDESTRIAN` store + // information about associated lidar objects. + optional string laser_object_id = 1; + } + optional Association association = 10; + + // Used by Lidar labels to store in which camera it is mostly visible. + optional string most_visible_camera_name = 11; + // Used by Lidar labels to store a camera-synchronized box corresponding to + // the camera indicated by `most_visible_camera_name`. Currently, the boxes + // are shifted to the time when the most visible camera captures the center of + // the box, taking into account the rolling shutter of that camera. + // Specifically, given the object box living at the start of the Open Dataset + // frame (t_frame) with center position (c) and velocity (v), we aim to find + // the camera capture time (t_capture), when the camera indicated by + // `most_visible_camera_name` captures the center of the object. To this end, + // we solve the rolling shutter optimization considering both ego and object + // motion: + // t_capture = image_column_to_time( + // camera_projection(c + v * (t_capture - t_frame), + // transform_vehicle(t_capture - t_ref), + // cam_params)), + // where transform_vehicle(t_capture - t_frame) is the vehicle transform from + // a pose reference time t_ref to t_capture considering the ego motion, and + // cam_params is the camera extrinsic and intrinsic parameters. + // We then move the label box to t_capture by updating the center of the box + // as follows: + // c_camra_synced = c + v * (t_capture - t_frame), + // while keeping the box dimensions and heading direction. + // We use the camera_synced_box as the ground truth box for the 3D Camera-Only + // Detection Challenge. This makes the assumption that the users provide the + // detection at the same time as the most visible camera captures the object + // center. + optional Box camera_synced_box = 12; + + +} + +// Non-self-intersecting 2d polygons. This polygon is not necessarily convex. +message Polygon2dProto { + repeated double x = 1; + repeated double y = 2; + + // A globally unique ID. + optional string id = 3; +} \ No newline at end of file diff --git a/protos/label_pb2.py b/protos/label_pb2.py new file mode 100644 index 0000000..8d33f83 --- /dev/null +++ b/protos/label_pb2.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE +# source: label.proto +# Protobuf Python Version: 6.30.2 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 6, + 30, + 2, + '', + 'label.proto' +) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +import protos.keypoint_pb2 as keypoint__pb2 + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0blabel.proto\x12\x12waymo.open_dataset\x1a\x0ekeypoint.proto\"\xbd\t\n\x05Label\x12*\n\x03\x62ox\x18\x01 \x01(\x0b\x32\x1d.waymo.open_dataset.Label.Box\x12\x34\n\x08metadata\x18\x02 \x01(\x0b\x32\".waymo.open_dataset.Label.Metadata\x12,\n\x04type\x18\x03 \x01(\x0e\x32\x1e.waymo.open_dataset.Label.Type\x12\n\n\x02id\x18\x04 \x01(\t\x12M\n\x1a\x64\x65tection_difficulty_level\x18\x05 \x01(\x0e\x32).waymo.open_dataset.Label.DifficultyLevel\x12L\n\x19tracking_difficulty_level\x18\x06 \x01(\x0e\x32).waymo.open_dataset.Label.DifficultyLevel\x12\x1f\n\x17num_lidar_points_in_box\x18\x07 \x01(\x05\x12#\n\x1bnum_top_lidar_points_in_box\x18\r \x01(\x05\x12G\n\x0flaser_keypoints\x18\x08 \x01(\x0b\x32,.waymo.open_dataset.keypoints.LaserKeypointsH\x00\x12I\n\x10\x63\x61mera_keypoints\x18\t \x01(\x0b\x32-.waymo.open_dataset.keypoints.CameraKeypointsH\x00\x12:\n\x0b\x61ssociation\x18\n \x01(\x0b\x32%.waymo.open_dataset.Label.Association\x12 \n\x18most_visible_camera_name\x18\x0b \x01(\t\x12\x38\n\x11\x63\x61mera_synced_box\x18\x0c \x01(\x0b\x32\x1d.waymo.open_dataset.Label.Box\x1a\xbf\x01\n\x03\x42ox\x12\x10\n\x08\x63\x65nter_x\x18\x01 \x01(\x01\x12\x10\n\x08\x63\x65nter_y\x18\x02 \x01(\x01\x12\x10\n\x08\x63\x65nter_z\x18\x03 \x01(\x01\x12\x0e\n\x06length\x18\x05 \x01(\x01\x12\r\n\x05width\x18\x04 \x01(\x01\x12\x0e\n\x06height\x18\x06 \x01(\x01\x12\x0f\n\x07heading\x18\x07 \x01(\x01\"B\n\x04Type\x12\x10\n\x0cTYPE_UNKNOWN\x10\x00\x12\x0b\n\x07TYPE_3D\x10\x01\x12\x0b\n\x07TYPE_2D\x10\x02\x12\x0e\n\nTYPE_AA_2D\x10\x03\x1ap\n\x08Metadata\x12\x0f\n\x07speed_x\x18\x01 \x01(\x01\x12\x0f\n\x07speed_y\x18\x02 \x01(\x01\x12\x0f\n\x07speed_z\x18\x05 \x01(\x01\x12\x0f\n\x07\x61\x63\x63\x65l_x\x18\x03 \x01(\x01\x12\x0f\n\x07\x61\x63\x63\x65l_y\x18\x04 \x01(\x01\x12\x0f\n\x07\x61\x63\x63\x65l_z\x18\x06 \x01(\x01\x1a&\n\x0b\x41ssociation\x12\x17\n\x0flaser_object_id\x18\x01 \x01(\t\"`\n\x04Type\x12\x10\n\x0cTYPE_UNKNOWN\x10\x00\x12\x10\n\x0cTYPE_VEHICLE\x10\x01\x12\x13\n\x0fTYPE_PEDESTRIAN\x10\x02\x12\r\n\tTYPE_SIGN\x10\x03\x12\x10\n\x0cTYPE_CYCLIST\x10\x04\"8\n\x0f\x44ifficultyLevel\x12\x0b\n\x07UNKNOWN\x10\x00\x12\x0b\n\x07LEVEL_1\x10\x01\x12\x0b\n\x07LEVEL_2\x10\x02\x42\x11\n\x0fkeypoints_oneof\"2\n\x0ePolygon2dProto\x12\t\n\x01x\x18\x01 \x03(\x01\x12\t\n\x01y\x18\x02 \x03(\x01\x12\n\n\x02id\x18\x03 \x01(\t') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'label_pb2', _globals) +if not _descriptor._USE_C_DESCRIPTORS: + DESCRIPTOR._loaded_options = None + _globals['_LABEL']._serialized_start=52 + _globals['_LABEL']._serialized_end=1265 + _globals['_LABEL_BOX']._serialized_start=745 + _globals['_LABEL_BOX']._serialized_end=936 + _globals['_LABEL_BOX_TYPE']._serialized_start=870 + _globals['_LABEL_BOX_TYPE']._serialized_end=936 + _globals['_LABEL_METADATA']._serialized_start=938 + _globals['_LABEL_METADATA']._serialized_end=1050 + _globals['_LABEL_ASSOCIATION']._serialized_start=1052 + _globals['_LABEL_ASSOCIATION']._serialized_end=1090 + _globals['_LABEL_TYPE']._serialized_start=1092 + _globals['_LABEL_TYPE']._serialized_end=1188 + _globals['_LABEL_DIFFICULTYLEVEL']._serialized_start=1190 + _globals['_LABEL_DIFFICULTYLEVEL']._serialized_end=1246 + _globals['_POLYGON2DPROTO']._serialized_start=1267 + _globals['_POLYGON2DPROTO']._serialized_end=1317 +# @@protoc_insertion_point(module_scope) diff --git a/protos/map.proto b/protos/map.proto new file mode 100644 index 0000000..ced15f5 --- /dev/null +++ b/protos/map.proto @@ -0,0 +1,255 @@ +/* Copyright 2021 The Waymo Open Dataset Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +syntax = "proto2"; + +package waymo.open_dataset; + +message Map { + // The full set of map features. + repeated MapFeature map_features = 1; + + // A set of dynamic states per time step. These are ordered in consecutive + // time steps. + repeated DynamicState dynamic_states = 2; + + +} + +message DynamicState { + // The timestamp associated with the dynamic feature data. + optional double timestamp_seconds = 1; + + // The set of traffic signal states for the associated time step. + repeated TrafficSignalLaneState lane_states = 2; +} + +message TrafficSignalLaneState { + // The ID for the MapFeature corresponding to the lane controlled by this + // traffic signal state. + optional int64 lane = 1; + + enum State { + LANE_STATE_UNKNOWN = 0; + + // States for traffic signals with arrows. + LANE_STATE_ARROW_STOP = 1; + LANE_STATE_ARROW_CAUTION = 2; + LANE_STATE_ARROW_GO = 3; + + // Standard round traffic signals. + LANE_STATE_STOP = 4; + LANE_STATE_CAUTION = 5; + LANE_STATE_GO = 6; + + // Flashing light signals. + LANE_STATE_FLASHING_STOP = 7; + LANE_STATE_FLASHING_CAUTION = 8; + } + + // The state of the traffic signal. + optional State state = 2; + + // The stopping point along the lane controlled by the traffic signal. + // This is the point where dynamic objects must stop when the signal is in a + // stop state. + optional MapPoint stop_point = 3; +} + +message MapFeature { + // A unique ID to identify this feature. + optional int64 id = 1; + + // Type specific data. + oneof feature_data { + LaneCenter lane = 3; + RoadLine road_line = 4; + RoadEdge road_edge = 5; + StopSign stop_sign = 7; + Crosswalk crosswalk = 8; + SpeedBump speed_bump = 9; + Driveway driveway = 10; + } +} + +message MapPoint { + // Position in meters. The origin is an arbitrary location. + optional double x = 1; + optional double y = 2; + optional double z = 3; +} + +// A segment of a lane with a given adjacent boundary. +message BoundarySegment { + // The index into the lane's polyline where this lane boundary starts. + optional int32 lane_start_index = 1; + + // The index into the lane's polyline where this lane boundary ends. + optional int32 lane_end_index = 2; + + // The adjacent boundary feature ID of the MapFeature for the boundary. This + // can either be a RoadLine feature or a RoadEdge feature. + optional int64 boundary_feature_id = 3; + + // The adjacent boundary type. If the boundary is a road edge instead of a + // road line, this will be set to TYPE_UNKNOWN. + optional RoadLine.RoadLineType boundary_type = 4; +} + +message LaneNeighbor { + // The feature ID of the neighbor lane. + optional int64 feature_id = 1; + + // The self adjacency segment. + // The other lane may only be a neighbor for only part of this lane. These + // indices define the points within this lane's polyline for which feature_id + // is a neighbor. If the lanes are neighbors at disjoint places (e.g., a + // median between them appears and then goes away) multiple neighbors will be + // listed. A lane change can only happen from this segment of this lane into + // the segment of the neighbor lane defined by neighbor_start_index and + // neighbor_end_index. + optional int32 self_start_index = 2; + optional int32 self_end_index = 3; + + // The neighbor adjacency segment. + // These indices define the valid portion of the neighbor lane's polyline + // where that lane is a neighbor to this lane. A lane change can only happen + // into this segment of the neighbor lane from the segment of this lane + // defined by self_start_index and self_end_index. + optional int32 neighbor_start_index = 4; + optional int32 neighbor_end_index = 5; + + // A list of segments within the self adjacency segment that have different + // boundaries between this lane and the neighbor lane. Each entry in this + // field contains the boundary type between this lane and the neighbor lane + // along with the indices into this lane's polyline where the boundary type + // begins and ends. + repeated BoundarySegment boundaries = 6; +} + +message LaneCenter { + // The speed limit for this lane. + optional double speed_limit_mph = 1; + + // Type of this lane. + enum LaneType { + TYPE_UNDEFINED = 0; + TYPE_FREEWAY = 1; + TYPE_SURFACE_STREET = 2; + TYPE_BIKE_LANE = 3; + } + optional LaneType type = 2; + + // True if the lane interpolates between two other lanes. + optional bool interpolating = 3; + + // The polyline data for the lane. A polyline is a list of points with + // segments defined between consecutive points. + repeated MapPoint polyline = 8; + + // A list of IDs for lanes that this lane may be entered from. + repeated int64 entry_lanes = 9 [packed = true]; + + // A list of IDs for lanes that this lane may exit to. + repeated int64 exit_lanes = 10 [packed = true]; + + // The boundaries to the left of this lane. There may be different boundary + // types along this lane. Each BoundarySegment defines a section of the lane + // with a given boundary feature to the left. Note that some lanes do not have + // any boundaries (i.e. lane centers in intersections). + repeated BoundarySegment left_boundaries = 13; + + // The boundaries to the right of this lane. See left_boundaries for details. + repeated BoundarySegment right_boundaries = 14; + + // A list of neighbors to the left of this lane. Neighbor lanes + // include only adjacent lanes going the same direction. + repeated LaneNeighbor left_neighbors = 11; + + // A list of neighbors to the right of this lane. Neighbor lanes + // include only adjacent lanes going the same direction. + repeated LaneNeighbor right_neighbors = 12; +} + +message RoadEdge { + // Type of this road edge. + enum RoadEdgeType { + TYPE_UNKNOWN = 0; + // Physical road boundary that doesn't have traffic on the other side (e.g., + // a curb or the k-rail on the right side of a freeway). + TYPE_ROAD_EDGE_BOUNDARY = 1; + // Physical road boundary that separates the car from other traffic + // (e.g. a k-rail or an island). + TYPE_ROAD_EDGE_MEDIAN = 2; + } + + // The type of road edge. + optional RoadEdgeType type = 1; + + // The polyline defining the road edge. A polyline is a list of points with + // segments defined between consecutive points. + repeated MapPoint polyline = 2; +} + +message RoadLine { + // Type of this road line. + enum RoadLineType { + TYPE_UNKNOWN = 0; + TYPE_BROKEN_SINGLE_WHITE = 1; + TYPE_SOLID_SINGLE_WHITE = 2; + TYPE_SOLID_DOUBLE_WHITE = 3; + TYPE_BROKEN_SINGLE_YELLOW = 4; + TYPE_BROKEN_DOUBLE_YELLOW = 5; + TYPE_SOLID_SINGLE_YELLOW = 6; + TYPE_SOLID_DOUBLE_YELLOW = 7; + TYPE_PASSING_DOUBLE_YELLOW = 8; + } + + // The type of the lane boundary. + optional RoadLineType type = 1; + + // The polyline defining the road edge. A polyline is a list of points with + // segments defined between consecutive points. + repeated MapPoint polyline = 2; +} + +message StopSign { + // The IDs of lane features controlled by this stop sign. + repeated int64 lane = 1; + + // The position of the stop sign. + optional MapPoint position = 2; +} + +message Crosswalk { + // The polygon defining the outline of the crosswalk. The polygon is assumed + // to be closed (i.e. a segment exists between the last point and the first + // point). + repeated MapPoint polygon = 1; +} + +message SpeedBump { + // The polygon defining the outline of the speed bump. The polygon is assumed + // to be closed (i.e. a segment exists between the last point and the first + // point). + repeated MapPoint polygon = 1; +} + +message Driveway { + // The polygon defining the outline of the driveway region. The polygon is + // assumed to be closed (i.e. a segment exists between the last point and the + // first point). + repeated MapPoint polygon = 1; +} \ No newline at end of file diff --git a/protos/map_pb2.py b/protos/map_pb2.py new file mode 100644 index 0000000..9541e0e --- /dev/null +++ b/protos/map_pb2.py @@ -0,0 +1,74 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE +# source: map.proto +# Protobuf Python Version: 6.30.2 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 6, + 30, + 2, + '', + 'map.proto' +) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\tmap.proto\x12\x12waymo.open_dataset\"u\n\x03Map\x12\x34\n\x0cmap_features\x18\x01 \x03(\x0b\x32\x1e.waymo.open_dataset.MapFeature\x12\x38\n\x0e\x64ynamic_states\x18\x02 \x03(\x0b\x32 .waymo.open_dataset.DynamicState\"j\n\x0c\x44ynamicState\x12\x19\n\x11timestamp_seconds\x18\x01 \x01(\x01\x12?\n\x0blane_states\x18\x02 \x03(\x0b\x32*.waymo.open_dataset.TrafficSignalLaneState\"\x8c\x03\n\x16TrafficSignalLaneState\x12\x0c\n\x04lane\x18\x01 \x01(\x03\x12?\n\x05state\x18\x02 \x01(\x0e\x32\x30.waymo.open_dataset.TrafficSignalLaneState.State\x12\x30\n\nstop_point\x18\x03 \x01(\x0b\x32\x1c.waymo.open_dataset.MapPoint\"\xf0\x01\n\x05State\x12\x16\n\x12LANE_STATE_UNKNOWN\x10\x00\x12\x19\n\x15LANE_STATE_ARROW_STOP\x10\x01\x12\x1c\n\x18LANE_STATE_ARROW_CAUTION\x10\x02\x12\x17\n\x13LANE_STATE_ARROW_GO\x10\x03\x12\x13\n\x0fLANE_STATE_STOP\x10\x04\x12\x16\n\x12LANE_STATE_CAUTION\x10\x05\x12\x11\n\rLANE_STATE_GO\x10\x06\x12\x1c\n\x18LANE_STATE_FLASHING_STOP\x10\x07\x12\x1f\n\x1bLANE_STATE_FLASHING_CAUTION\x10\x08\"\x8c\x03\n\nMapFeature\x12\n\n\x02id\x18\x01 \x01(\x03\x12.\n\x04lane\x18\x03 \x01(\x0b\x32\x1e.waymo.open_dataset.LaneCenterH\x00\x12\x31\n\troad_line\x18\x04 \x01(\x0b\x32\x1c.waymo.open_dataset.RoadLineH\x00\x12\x31\n\troad_edge\x18\x05 \x01(\x0b\x32\x1c.waymo.open_dataset.RoadEdgeH\x00\x12\x31\n\tstop_sign\x18\x07 \x01(\x0b\x32\x1c.waymo.open_dataset.StopSignH\x00\x12\x32\n\tcrosswalk\x18\x08 \x01(\x0b\x32\x1d.waymo.open_dataset.CrosswalkH\x00\x12\x33\n\nspeed_bump\x18\t \x01(\x0b\x32\x1d.waymo.open_dataset.SpeedBumpH\x00\x12\x30\n\x08\x64riveway\x18\n \x01(\x0b\x32\x1c.waymo.open_dataset.DrivewayH\x00\x42\x0e\n\x0c\x66\x65\x61ture_data\"+\n\x08MapPoint\x12\t\n\x01x\x18\x01 \x01(\x01\x12\t\n\x01y\x18\x02 \x01(\x01\x12\t\n\x01z\x18\x03 \x01(\x01\"\xa2\x01\n\x0f\x42oundarySegment\x12\x18\n\x10lane_start_index\x18\x01 \x01(\x05\x12\x16\n\x0elane_end_index\x18\x02 \x01(\x05\x12\x1b\n\x13\x62oundary_feature_id\x18\x03 \x01(\x03\x12@\n\rboundary_type\x18\x04 \x01(\x0e\x32).waymo.open_dataset.RoadLine.RoadLineType\"\xc7\x01\n\x0cLaneNeighbor\x12\x12\n\nfeature_id\x18\x01 \x01(\x03\x12\x18\n\x10self_start_index\x18\x02 \x01(\x05\x12\x16\n\x0eself_end_index\x18\x03 \x01(\x05\x12\x1c\n\x14neighbor_start_index\x18\x04 \x01(\x05\x12\x1a\n\x12neighbor_end_index\x18\x05 \x01(\x05\x12\x37\n\nboundaries\x18\x06 \x03(\x0b\x32#.waymo.open_dataset.BoundarySegment\"\xa5\x04\n\nLaneCenter\x12\x17\n\x0fspeed_limit_mph\x18\x01 \x01(\x01\x12\x35\n\x04type\x18\x02 \x01(\x0e\x32\'.waymo.open_dataset.LaneCenter.LaneType\x12\x15\n\rinterpolating\x18\x03 \x01(\x08\x12.\n\x08polyline\x18\x08 \x03(\x0b\x32\x1c.waymo.open_dataset.MapPoint\x12\x17\n\x0b\x65ntry_lanes\x18\t \x03(\x03\x42\x02\x10\x01\x12\x16\n\nexit_lanes\x18\n \x03(\x03\x42\x02\x10\x01\x12<\n\x0fleft_boundaries\x18\r \x03(\x0b\x32#.waymo.open_dataset.BoundarySegment\x12=\n\x10right_boundaries\x18\x0e \x03(\x0b\x32#.waymo.open_dataset.BoundarySegment\x12\x38\n\x0eleft_neighbors\x18\x0b \x03(\x0b\x32 .waymo.open_dataset.LaneNeighbor\x12\x39\n\x0fright_neighbors\x18\x0c \x03(\x0b\x32 .waymo.open_dataset.LaneNeighbor\"]\n\x08LaneType\x12\x12\n\x0eTYPE_UNDEFINED\x10\x00\x12\x10\n\x0cTYPE_FREEWAY\x10\x01\x12\x17\n\x13TYPE_SURFACE_STREET\x10\x02\x12\x12\n\x0eTYPE_BIKE_LANE\x10\x03\"\xcd\x01\n\x08RoadEdge\x12\x37\n\x04type\x18\x01 \x01(\x0e\x32).waymo.open_dataset.RoadEdge.RoadEdgeType\x12.\n\x08polyline\x18\x02 \x03(\x0b\x32\x1c.waymo.open_dataset.MapPoint\"X\n\x0cRoadEdgeType\x12\x10\n\x0cTYPE_UNKNOWN\x10\x00\x12\x1b\n\x17TYPE_ROAD_EDGE_BOUNDARY\x10\x01\x12\x19\n\x15TYPE_ROAD_EDGE_MEDIAN\x10\x02\"\x88\x03\n\x08RoadLine\x12\x37\n\x04type\x18\x01 \x01(\x0e\x32).waymo.open_dataset.RoadLine.RoadLineType\x12.\n\x08polyline\x18\x02 \x03(\x0b\x32\x1c.waymo.open_dataset.MapPoint\"\x92\x02\n\x0cRoadLineType\x12\x10\n\x0cTYPE_UNKNOWN\x10\x00\x12\x1c\n\x18TYPE_BROKEN_SINGLE_WHITE\x10\x01\x12\x1b\n\x17TYPE_SOLID_SINGLE_WHITE\x10\x02\x12\x1b\n\x17TYPE_SOLID_DOUBLE_WHITE\x10\x03\x12\x1d\n\x19TYPE_BROKEN_SINGLE_YELLOW\x10\x04\x12\x1d\n\x19TYPE_BROKEN_DOUBLE_YELLOW\x10\x05\x12\x1c\n\x18TYPE_SOLID_SINGLE_YELLOW\x10\x06\x12\x1c\n\x18TYPE_SOLID_DOUBLE_YELLOW\x10\x07\x12\x1e\n\x1aTYPE_PASSING_DOUBLE_YELLOW\x10\x08\"H\n\x08StopSign\x12\x0c\n\x04lane\x18\x01 \x03(\x03\x12.\n\x08position\x18\x02 \x01(\x0b\x32\x1c.waymo.open_dataset.MapPoint\":\n\tCrosswalk\x12-\n\x07polygon\x18\x01 \x03(\x0b\x32\x1c.waymo.open_dataset.MapPoint\":\n\tSpeedBump\x12-\n\x07polygon\x18\x01 \x03(\x0b\x32\x1c.waymo.open_dataset.MapPoint\"9\n\x08\x44riveway\x12-\n\x07polygon\x18\x01 \x03(\x0b\x32\x1c.waymo.open_dataset.MapPoint') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'map_pb2', _globals) +if not _descriptor._USE_C_DESCRIPTORS: + DESCRIPTOR._loaded_options = None + _globals['_LANECENTER'].fields_by_name['entry_lanes']._loaded_options = None + _globals['_LANECENTER'].fields_by_name['entry_lanes']._serialized_options = b'\020\001' + _globals['_LANECENTER'].fields_by_name['exit_lanes']._loaded_options = None + _globals['_LANECENTER'].fields_by_name['exit_lanes']._serialized_options = b'\020\001' + _globals['_MAP']._serialized_start=33 + _globals['_MAP']._serialized_end=150 + _globals['_DYNAMICSTATE']._serialized_start=152 + _globals['_DYNAMICSTATE']._serialized_end=258 + _globals['_TRAFFICSIGNALLANESTATE']._serialized_start=261 + _globals['_TRAFFICSIGNALLANESTATE']._serialized_end=657 + _globals['_TRAFFICSIGNALLANESTATE_STATE']._serialized_start=417 + _globals['_TRAFFICSIGNALLANESTATE_STATE']._serialized_end=657 + _globals['_MAPFEATURE']._serialized_start=660 + _globals['_MAPFEATURE']._serialized_end=1056 + _globals['_MAPPOINT']._serialized_start=1058 + _globals['_MAPPOINT']._serialized_end=1101 + _globals['_BOUNDARYSEGMENT']._serialized_start=1104 + _globals['_BOUNDARYSEGMENT']._serialized_end=1266 + _globals['_LANENEIGHBOR']._serialized_start=1269 + _globals['_LANENEIGHBOR']._serialized_end=1468 + _globals['_LANECENTER']._serialized_start=1471 + _globals['_LANECENTER']._serialized_end=2020 + _globals['_LANECENTER_LANETYPE']._serialized_start=1927 + _globals['_LANECENTER_LANETYPE']._serialized_end=2020 + _globals['_ROADEDGE']._serialized_start=2023 + _globals['_ROADEDGE']._serialized_end=2228 + _globals['_ROADEDGE_ROADEDGETYPE']._serialized_start=2140 + _globals['_ROADEDGE_ROADEDGETYPE']._serialized_end=2228 + _globals['_ROADLINE']._serialized_start=2231 + _globals['_ROADLINE']._serialized_end=2623 + _globals['_ROADLINE_ROADLINETYPE']._serialized_start=2349 + _globals['_ROADLINE_ROADLINETYPE']._serialized_end=2623 + _globals['_STOPSIGN']._serialized_start=2625 + _globals['_STOPSIGN']._serialized_end=2697 + _globals['_CROSSWALK']._serialized_start=2699 + _globals['_CROSSWALK']._serialized_end=2757 + _globals['_SPEEDBUMP']._serialized_start=2759 + _globals['_SPEEDBUMP']._serialized_end=2817 + _globals['_DRIVEWAY']._serialized_start=2819 + _globals['_DRIVEWAY']._serialized_end=2876 +# @@protoc_insertion_point(module_scope) diff --git a/protos/vector.proto b/protos/vector.proto new file mode 100644 index 0000000..c0df18f --- /dev/null +++ b/protos/vector.proto @@ -0,0 +1,28 @@ +/* Copyright 2023 The Waymo Open Dataset Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +syntax = "proto2"; + +package waymo.open_dataset; + +message Vector2d { + optional double x = 1; + optional double y = 2; +} + +message Vector3d { + optional double x = 1; + optional double y = 2; + optional double z = 3; +} \ No newline at end of file diff --git a/protos/vector_pb2.py b/protos/vector_pb2.py new file mode 100644 index 0000000..bb956d5 --- /dev/null +++ b/protos/vector_pb2.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE +# source: vector.proto +# Protobuf Python Version: 6.30.2 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 6, + 30, + 2, + '', + 'vector.proto' +) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0cvector.proto\x12\x12waymo.open_dataset\" \n\x08Vector2d\x12\t\n\x01x\x18\x01 \x01(\x01\x12\t\n\x01y\x18\x02 \x01(\x01\"+\n\x08Vector3d\x12\t\n\x01x\x18\x01 \x01(\x01\x12\t\n\x01y\x18\x02 \x01(\x01\x12\t\n\x01z\x18\x03 \x01(\x01') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'vector_pb2', _globals) +if not _descriptor._USE_C_DESCRIPTORS: + DESCRIPTOR._loaded_options = None + _globals['_VECTOR2D']._serialized_start=36 + _globals['_VECTOR2D']._serialized_end=68 + _globals['_VECTOR3D']._serialized_start=70 + _globals['_VECTOR3D']._serialized_end=113 +# @@protoc_insertion_point(module_scope)