{ "cells": [ { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "from nuscenes.can_bus.can_bus_api import NuScenesCanBus\n", "nusc_can = NuScenesCanBus(dataroot='can_bus')" ] }, { "cell_type": "markdown", "metadata": { "tags": [] }, "source": [ "The CAN bus is a vehicle bus over which information such as position, velocity, acceleration, steering, lights, battery and many more are submitted. We recommend you start by reading the [README](https://github.com/nutonomy/nuscenes-devkit/tree/master/python-sdk/nuscenes/can_bus/README.md)\n", "In BEVFormer, we only use the `pose` fields." ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "scene_name = 'scene-0001'\n", "pose_list = nusc_can.get_messages(scene_name, 'pose')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Each value of `pose_list` contains: \n", "- `orientation`: a Quaternion representation of orientation\n", "- `pos`: a global postion of ego-car\n", "- `vel`: the velocity of ego-car\n", "- `rotation_rate`: rotation rate" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'accel': [0.05252802768009661, 0.9291747528573647, 9.513756543139106],\n", " 'orientation': [0.7479305678167669, 0.0, 0.0, 0.6637769698666026],\n", " 'pos': [1010.1436201720262, 610.8882352282457, 0.0],\n", " 'rotation_rate': [0.040320225059986115,\n", " -0.002563952235504985,\n", " 0.28492140769958496],\n", " 'utime': 1531883530467511,\n", " 'vel': [4.1688763951334185, 0.0, 0.0]}" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pose_list[0] # one example" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "dict_keys(['accel', 'orientation', 'pos', 'rotation_rate', 'utime', 'vel'])" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pose_list[0].keys()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In [data_converter](https://github.com/zhiqi-li/BEVFormer/blob/master/tools/data_converter/nuscenes_converter.py), we use the following function to obatain the can bus information for each sample." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def _get_can_bus_info(nusc, nusc_can_bus, sample):\n", " scene_name = nusc.get('scene', sample['scene_token'])['name']\n", " sample_timestamp = sample['timestamp']\n", " try:\n", " pose_list = nusc_can_bus.get_messages(scene_name, 'pose')\n", " except:\n", " return np.zeros(18) # serveral scenes do not have can bus information.\n", " can_bus = []\n", " # during each scene, the first timestamp of can_bus may be large than the first sample's timestamp\n", " last_pose = pose_list[0]\n", " for i, pose in enumerate(pose_list):\n", " if pose['utime'] > sample_timestamp:\n", " break\n", " last_pose = pose # we obtain the can_bus information which is recorded before the sample recorded.\n", " \n", " _ = last_pose.pop('utime') # useless\n", " pos = last_pose.pop('pos') \n", " rotation = last_pose.pop('orientation')\n", " \n", " # one can_bus record contains 18 numbers\n", " can_bus.extend(pos) # [0:3] is the position\n", " can_bus.extend(rotation) # [3:7] is the orientation\n", " \n", " for key in last_pose.keys():\n", " can_bus.extend(pose[key]) # accel: [7, 10], rotation_rate: [10: 13], velocity: [13: 16]\n", " \n", " # the last two numbers are reserved for later calculation of rotation angle.\n", " can_bus.extend([0., 0.])\n", " \n", " \n", " return np.array(can_bus)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In [dataset](https://github.com/zhiqi-li/BEVFormer/blob/master/projects/mmdet3d_plugin/datasets/nuscenes_dataset.py#L174), we reorganize the can_bus." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ " # actually, the nuScenes provides the rotation and translation of each sample, which is more accurate than we obtained from can bus. \n", " rotation = Quaternion(input_dict['ego2global_rotation'])\n", " translation = input_dict['ego2global_translation']\n", " \n", " can_bus = input_dict['can_bus']\n", " can_bus[:3] = translation # We use the provided translation and rotation to repalce the original translation and rotation in can bus\n", " can_bus[3:7] = rotation\n", " \n", " patch_angle = quaternion_yaw(rotation) / np.pi * 180 # we get the yaw angle of ego car\n", " can_bus[-2] = patch_angle / 180 * np.pi # this angle is kept unchanged.\n", " can_bus[-1] = patch_angle # this angle is used to compute the detal of adjacent timestamps." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In [dataset](https://github.com/zhiqi-li/BEVFormer/blob/master/projects/mmdet3d_plugin/datasets/nuscenes_dataset.py#L93), we compute the delta orientation and position of adjacent timestamps" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ " prev_pos = None\n", " prev_angle = None\n", " for i, each in enumerate(queue):\n", " metas_map[i] = each['img_metas'].data\n", " if i == 0:\n", " metas_map[i]['prev_bev'] = False\n", " prev_pos = copy.deepcopy(metas_map[i]['can_bus'][:3])\n", " prev_angle = copy.deepcopy(metas_map[i]['can_bus'][-1])\n", " metas_map[i]['can_bus'][:3] = 0\n", " metas_map[i]['can_bus'][-1] = 0\n", " else:\n", " metas_map[i]['prev_bev'] = True\n", " tmp_pos = copy.deepcopy(metas_map[i]['can_bus'][:3])\n", " tmp_angle = copy.deepcopy(metas_map[i]['can_bus'][-1])\n", " metas_map[i]['can_bus'][:3] -= prev_pos\n", " metas_map[i]['can_bus'][-1] -= prev_angle\n", " prev_pos = copy.deepcopy(tmp_pos)\n", " prev_angle = copy.deepcopy(tmp_angle)" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "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.8.13" } }, "nbformat": 4, "nbformat_minor": 4 }