├── .gitignore ├── Dockerfile ├── README.md ├── README_FILES └── header.png ├── create.sh ├── examples ├── amd64_stella_vslam │ ├── Lunarsim_stereo.yaml │ └── lunarsim_traj_points.png ├── jetson_nx_od_yolo │ └── lunarsim_od_jestson_result.png ├── raspberry_pico_smaf │ ├── lunarsim_smf_rpi_z.png │ └── pico_micro_ros_example.c └── versal_vck190_segment │ └── lunarsim_seg_fpga_result.png ├── run.sh └── run_once.sh /.gitignore: -------------------------------------------------------------------------------- 1 | *.zip 2 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:22.04 2 | 3 | ARG DEBIAN_FRONTEND=noninteractive 4 | 5 | # set time zone 6 | ENV TZ=Europe/Warsaw 7 | ENV LANG=en_US.UTF-8 8 | ENV XDG_RUNTIME_DIR=/tmp 9 | 10 | RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone 11 | 12 | # nvidia-container-runtime 13 | ENV NVIDIA_VISIBLE_DEVICES \ 14 | ${NVIDIA_VISIBLE_DEVICES:-all} 15 | ENV NVIDIA_DRIVER_CAPABILITIES \ 16 | ${NVIDIA_DRIVER_CAPABILITIES:+$NVIDIA_DRIVER_CAPABILITIES,}graphics 17 | 18 | # INSTALL SYSTEM DEPENDENCIES 19 | 20 | RUN apt clean 21 | RUN apt update && apt install -y --no-install-recommends \ 22 | ca-certificates \ 23 | devilspie \ 24 | gnupg2 \ 25 | mesa-utils \ 26 | sudo \ 27 | unzip \ 28 | wget \ 29 | xfce4-terminal \ 30 | unzip \ 31 | curl \ 32 | wget \ 33 | libssl-dev \ 34 | zlib1g-dev \ 35 | libreadline-dev 36 | 37 | # INSTALL GPU DEPENDENCIES 38 | RUN apt install nvidia-driver-525 -y 39 | RUN apt-get install -y libglu1 xvfb libxcursor1 libvulkan1 mesa-vulkan-drivers vulkan-tools -y 40 | 41 | # INSTALL ROS2-HUMBLE 42 | RUN curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg 43 | RUN echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu $(. /etc/os-release && echo $UBUNTU_CODENAME) main" | sudo tee /etc/apt/sources.list.d/ros2.list > /dev/null 44 | 45 | RUN apt update -y && apt install -y ros-humble-desktop 46 | 47 | RUN touch /root/.bashrc \ 48 | && echo "echo '|======================================================|'" >> /root/.bashrc \ 49 | && echo "echo '| DO NOT SOURCE ROS IN TERMINAL WHERE YOU RUN LUNARSIM |'" >> /root/.bashrc \ 50 | && echo "echo '|======================================================|'" >> /root/.bashrc 51 | 52 | # CONFIGURE APPLICATION 53 | RUN mkdir -p /root/lunarsim 54 | 55 | RUN wget "https://github.com/PUTvision/LunarSim/releases/latest/download/LunarSim.tar.xz" \ 56 | && cd /root/lunarsim \ 57 | && tar xf /LunarSim.tar.xz \ 58 | && rm -f /LunarSim.tar.xz \ 59 | && chmod +x /root/lunarsim/LunarSim.x86_64 60 | 61 | WORKDIR /root/lunarsim 62 | 63 | # TODO: ADD ENTRYPOINT SCRIPT TO RUN SIMULATION 64 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LunarSim - ROS 2-Connected Lunar Rover Simulation 2 | 3 | ![header](./README_FILES/header.png) 4 | 5 | ## About 6 | 7 | 8 | ## Installation 9 | 10 | ```bash 11 | # clone the repo 12 | git clone https://github.com/PUTvision/LunarSim 13 | 14 | # change the working directory to LunarSim 15 | cd ./LunarSim 16 | 17 | # build docker image 18 | docker build -t lunarsim:latest . 19 | ``` 20 | 21 | ## Run simulator 22 | 23 | ```bash 24 | # run docker container 25 | bash ./run.sh 26 | 27 | # run the simulator 28 | ./LunarSim.x86_64 29 | ``` 30 | 31 | > **Note:** DO NOT SOURCE ROS IN TERMINAL WHERE YOU RUN LUNARSIM 32 | 33 | ## Attach to container and activate ROS (in new terminal) 34 | 35 | ```bash 36 | # connect to container 37 | docker exec -it lunarsim bash 38 | 39 | # source ROS environment 40 | source /opt/ros/humble/setup.bash 41 | 42 | # then you can run sanity checks and display topics 43 | ros2 wtf 44 | ros2 topic list 45 | ``` 46 | 47 | ## Data generation mode 48 | 49 | You can find sample image sequences generated with the simulator [here](https://chmura.put.poznan.pl/s/9CQiMdU6O9Olyli). 50 | 51 | We also provide our real images recorded during analogue lunar missions ([link](https://chmura.put.poznan.pl/s/HAybyHz1rgpyy9r)). 52 | 53 | ## ROS 2 mode 54 | 55 | ### Topics 56 | 57 | #### Subscribed topics 58 | 59 | * `/cmd_vel` (geometry_msgs/Twist) 60 | 61 | The velocity command for the robot. 62 | 63 | #### Published topics 64 | 65 | * `/lunarsim/gt/pose` (geometry_msgs/PoseStamped) 66 | 67 | The ground truth pose of the robot. 68 | 69 | > For example, you can use terminal command `ros2 topic pub --once /cmd_vel geometry_msgs/msg/Twist "{linear: {x: 1.0, y: 0.0, z: 0.0}, angular: {x: 0.0, y: 0.0, z: 0.0}}"` 70 | 71 | * `/lunarsim/imu` (sensor_msgs/Imu) 72 | 73 | The IMU data. 74 | 75 | * `/lunarsim/camera_left/raw` (sensor_msgs/Image) 76 | 77 | or 78 | 79 | `/lunarsim/camera_left/compressed` (sensor_msgs/CompressedImage) 80 | 81 | The left camera image. 82 | 83 | * `/lunarsim/camera_right/raw` (sensor_msgs/Image) 84 | 85 | or 86 | 87 | `/lunarsim/camera_right/compressed` (sensor_msgs/CompressedImage) 88 | 89 | The right camera image. 90 | 91 | * `/lunarsim/camera_depth/depth` (sensor_msgs/Image) 92 | 93 | The depth image. 94 | 95 | 96 | ## Examples 97 | 98 | * Object detection – embedded device 99 | 100 | ``` 101 | ./examples/jetson_nx_od_yolo 102 | ``` 103 | 104 | ![object_detection](./examples/jetson_nx_od_yolo/lunarsim_od_jestson_result.png) 105 | 106 | * Visual odometry – x64-based mini-PC 107 | 108 | ``` 109 | ./examples/amd64_stella_vslam 110 | ``` 111 | 112 | ![visual_odometry](./examples/amd64_stella_vslam/lunarsim_traj_points.png) 113 | 114 | * Simple moving-average filter – microcontroller 115 | 116 | ``` 117 | ./examples/raspberry_pico_smaf 118 | ``` 119 | 120 | ![moving_average](./examples/raspberry_pico_smaf/lunarsim_smf_rpi_z.png) 121 | 122 | * image segmentation – FPGA 123 | 124 | ``` 125 | ./examples/versal_vck190_segment 126 | ``` 127 | 128 | ![image_segmentation](./examples/versal_vck190_segment/lunarsim_seg_fpga_result.png) 129 | 130 | ## Citation 131 | 132 | If you use this code for your research, please cite our paper: 133 | 134 | ``` 135 | 136 | @Article{app132212401, 137 | AUTHOR = {Pieczyński, Dominik and Ptak, Bartosz and Kraft, Marek and Drapikowski, Paweł}, 138 | TITLE = {LunarSim: Lunar Rover Simulator Focused on High Visual Fidelity and ROS 2 Integration for Advanced Computer Vision Algorithm Development}, 139 | JOURNAL = {Applied Sciences}, 140 | VOLUME = {13}, 141 | YEAR = {2023}, 142 | NUMBER = {22}, 143 | ARTICLE-NUMBER = {12401}, 144 | URL = {https://www.mdpi.com/2076-3417/13/22/12401}, 145 | ISSN = {2076-3417}, 146 | DOI = {10.3390/app132212401} 147 | } 148 | ``` 149 | -------------------------------------------------------------------------------- /README_FILES/header.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PUTvision/LunarSim/0f3b202624d398ecacbb1e4bab9aec02e394a2d2/README_FILES/header.png -------------------------------------------------------------------------------- /create.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | xhost local:root 3 | XSOCK=/tmp/.X11-unix 4 | 5 | docker build -t lunarsim . 6 | -------------------------------------------------------------------------------- /examples/amd64_stella_vslam/Lunarsim_stereo.yaml: -------------------------------------------------------------------------------- 1 | # TUM VI stereo rectify model 2 | # https://vision.in.tum.de/data/datasets/visual-inertial-dataset#geometric_calibration 3 | # pinhole (512x512) 4 | 5 | #==============# 6 | # Camera Model # 7 | #==============# 8 | 9 | Camera: 10 | name: "TUM VI stereo" 11 | setup: "stereo" 12 | model: "perspective" 13 | 14 | fx: 504.761904762 15 | fy: 502.105263158 16 | cx: 640.0 17 | cy: 360.0 18 | 19 | # there is no distortion after stereo rectification 20 | 21 | k1: 0.0 22 | k2: 0.0 23 | p1: 0.0 24 | p2: 0.0 25 | k3: 0.0 26 | 27 | # focal_x_baseline is -P2[0][3] which is calculated with cv::stereoRectify() 28 | 29 | fps: 10 30 | cols: 1280 31 | rows: 720 32 | focal_x_baseline: 60.5714285714 33 | 34 | color_order: "RGB" 35 | 36 | #======================# 37 | # Stereo Rectification # 38 | #======================# 39 | 40 | # original intrinsic parameters (K, D) and stereo-recitification parameters (R) 41 | # matrices (K, R) are written in row-major order 42 | # StereoRectifier.model is camera model before rectification 43 | 44 | #=====================# 45 | # Tracking Parameters # 46 | #=====================# 47 | 48 | Preprocessing: 49 | min_size: 800 50 | 51 | #================# 52 | # ORB Parameters # 53 | #================# 54 | 55 | Feature: 56 | name: "default ORB feature extraction setting" 57 | scale_factor: 1.2 58 | num_levels: 8 59 | ini_fast_threshold: 20 60 | min_fast_threshold: 7 61 | 62 | #====================# 63 | # Mapping Parameters # 64 | #====================# 65 | 66 | Mapping: 67 | baseline_dist_thr: 0.10108726432 68 | redundant_obs_ratio_thr: 0.9 69 | 70 | #========================# 71 | # Initializer Parameters # 72 | #========================# 73 | 74 | Initializer: 75 | num_min_triangulated_pts: 100 76 | -------------------------------------------------------------------------------- /examples/amd64_stella_vslam/lunarsim_traj_points.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PUTvision/LunarSim/0f3b202624d398ecacbb1e4bab9aec02e394a2d2/examples/amd64_stella_vslam/lunarsim_traj_points.png -------------------------------------------------------------------------------- /examples/jetson_nx_od_yolo/lunarsim_od_jestson_result.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PUTvision/LunarSim/0f3b202624d398ecacbb1e4bab9aec02e394a2d2/examples/jetson_nx_od_yolo/lunarsim_od_jestson_result.png -------------------------------------------------------------------------------- /examples/raspberry_pico_smaf/lunarsim_smf_rpi_z.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PUTvision/LunarSim/0f3b202624d398ecacbb1e4bab9aec02e394a2d2/examples/raspberry_pico_smaf/lunarsim_smf_rpi_z.png -------------------------------------------------------------------------------- /examples/raspberry_pico_smaf/pico_micro_ros_example.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "pico/stdlib.h" 12 | #include "pico_uart_transports.h" 13 | 14 | #define HISTORY_SIZE 5 15 | 16 | const uint LED_PIN = 25; 17 | 18 | struct IMU_flatten 19 | { 20 | float linear_acceleration_x; 21 | float linear_acceleration_y; 22 | float linear_acceleration_z; 23 | }; 24 | 25 | rcl_publisher_t publisher; 26 | rcl_publisher_t publisher_filtered; 27 | rcl_subscription_t subscriber; 28 | 29 | sensor_msgs__msg__Imu msg_in_type; 30 | geometry_msgs__msg__Vector3 msg_out; 31 | geometry_msgs__msg__Vector3 msg_out_filtered; 32 | 33 | struct IMU_flatten historyNumbers[HISTORY_SIZE] = {0}; 34 | int historyCounter = 0; 35 | 36 | void IMU_flatten_add(struct IMU_flatten *sum, struct IMU_flatten *add) 37 | { 38 | sum->linear_acceleration_x += add->linear_acceleration_x; 39 | sum->linear_acceleration_y += add->linear_acceleration_y; 40 | sum->linear_acceleration_z += add->linear_acceleration_z; 41 | } 42 | 43 | void IMU_Flatten_divide_by_value(struct IMU_flatten *sum, float divider) 44 | { 45 | sum->linear_acceleration_x /= divider; 46 | sum->linear_acceleration_y /= divider; 47 | sum->linear_acceleration_z /= divider; 48 | } 49 | 50 | void msg_callback(const void *msgin) 51 | { 52 | const sensor_msgs__msg__Imu *msg = (const sensor_msgs__msg__Imu *)msgin; 53 | 54 | if (historyCounter < HISTORY_SIZE) 55 | { 56 | 57 | struct IMU_flatten s = { 58 | msg->linear_acceleration.x, 59 | msg->linear_acceleration.y, 60 | msg->linear_acceleration.z}; 61 | 62 | historyNumbers[historyCounter] = s; 63 | historyCounter++; 64 | return; 65 | } 66 | 67 | struct IMU_flatten sum = {0.0, 0.0, 0.0}; 68 | 69 | for (int pos = 0; pos < HISTORY_SIZE - 1; pos++) 70 | { 71 | historyNumbers[pos] = historyNumbers[pos + 1]; 72 | IMU_flatten_add(&sum, &historyNumbers[pos]); 73 | } 74 | 75 | struct IMU_flatten s = { 76 | msg->linear_acceleration.x, 77 | msg->linear_acceleration.y, 78 | msg->linear_acceleration.z}; 79 | 80 | historyNumbers[HISTORY_SIZE - 1] = s; 81 | 82 | IMU_flatten_add(&sum, &historyNumbers[HISTORY_SIZE - 1]); 83 | IMU_Flatten_divide_by_value(&sum, (float)HISTORY_SIZE); 84 | 85 | msg_out.x = msg->linear_acceleration.x; 86 | msg_out.y = msg->linear_acceleration.y; 87 | msg_out.z = msg->linear_acceleration.z; 88 | 89 | msg_out_filtered.x = sum.linear_acceleration_x; 90 | msg_out_filtered.y = sum.linear_acceleration_y; 91 | msg_out_filtered.z = sum.linear_acceleration_z; 92 | 93 | rcl_publish(&publisher, (const void *)&msg_out, NULL); 94 | rcl_publish(&publisher_filtered, (const void *)&msg_out_filtered, NULL); 95 | } 96 | 97 | int main() 98 | { 99 | rmw_uros_set_custom_transport( 100 | true, 101 | NULL, 102 | pico_serial_transport_open, 103 | pico_serial_transport_close, 104 | pico_serial_transport_write, 105 | pico_serial_transport_read); 106 | 107 | gpio_init(LED_PIN); 108 | gpio_set_dir(LED_PIN, GPIO_OUT); 109 | 110 | rcl_timer_t timer; 111 | rcl_node_t node; 112 | rcl_allocator_t allocator; 113 | rclc_support_t support; 114 | rclc_executor_t executor; 115 | 116 | allocator = rcl_get_default_allocator(); 117 | 118 | // Wait for agent successful ping for 2 minutes. 119 | const int timeout_ms = 1000; 120 | const uint8_t attempts = 120; 121 | 122 | rcl_ret_t ret = rmw_uros_ping_agent(timeout_ms, attempts); 123 | 124 | if (ret != RCL_RET_OK) 125 | { 126 | // Unreachable agent, exiting program. 127 | return ret; 128 | } 129 | 130 | rclc_support_init(&support, 0, NULL, &allocator); 131 | 132 | rclc_node_init_default(&node, "pico_node", "", &support); 133 | 134 | rclc_publisher_init_default( 135 | &publisher, 136 | &node, 137 | ROSIDL_GET_MSG_TYPE_SUPPORT(geometry_msgs, msg, Vector3), 138 | "/microROS/acc"); 139 | 140 | rclc_publisher_init_default( 141 | &publisher_filtered, 142 | &node, 143 | ROSIDL_GET_MSG_TYPE_SUPPORT(geometry_msgs, msg, Vector3), 144 | "/microROS/acc_sma"); 145 | 146 | rclc_subscription_init_best_effort( 147 | &subscriber, 148 | &node, 149 | ROSIDL_GET_MSG_TYPE_SUPPORT(sensor_msgs, msg, Imu), 150 | "/lunarsim/imu"); 151 | 152 | rclc_executor_init(&executor, &support.context, 1, &allocator); 153 | rclc_executor_add_subscription( 154 | &executor, 155 | &subscriber, 156 | &msg_in_type, 157 | &msg_callback, 158 | ON_NEW_DATA); 159 | 160 | gpio_put(LED_PIN, 1); 161 | 162 | rclc_executor_spin(&executor); 163 | 164 | return 0; 165 | } 166 | -------------------------------------------------------------------------------- /examples/versal_vck190_segment/lunarsim_seg_fpga_result.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PUTvision/LunarSim/0f3b202624d398ecacbb1e4bab9aec02e394a2d2/examples/versal_vck190_segment/lunarsim_seg_fpga_result.png -------------------------------------------------------------------------------- /run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | xhost local:root 3 | XSOCK=/tmp/.X11-unix 4 | 5 | docker run -it \ 6 | --gpus all \ 7 | -e DISPLAY=$DISPLAY \ 8 | -v $XSOCK:$XSOCK \ 9 | -v $HOME/.Xauthority:/root/.Xauthority \ 10 | --privileged \ 11 | --net=host \ 12 | --name=lunarsim \ 13 | lunarsim:latest bash 14 | -------------------------------------------------------------------------------- /run_once.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | xhost local:root 3 | XSOCK=/tmp/.X11-unix 4 | 5 | docker run -it --rm \ 6 | --gpus all \ 7 | -e DISPLAY=$DISPLAY \ 8 | -v $XSOCK:$XSOCK \ 9 | -v $HOME/.Xauthority:/root/.Xauthority \ 10 | --privileged \ 11 | --net=host \ 12 | lunarsim:latest bash 13 | --------------------------------------------------------------------------------