3d maps of your drone images with ODM and DJI

Background

I noticed I have not posted anything about drones. There are plenty of Youtube videos showing all settings and functions of drones. I use a DJI Mini 4 Pro that produces extraordinary videos and images. I have mostly used way points. I stumbled upon some sites that helps you plan your flights and also creates a 3d map of the ground. What may be called photogrammetry. We will use two services to make this. We will also use free open source programs. This will not cost you any cloud tokens or monthly subscriptions. You will just use your on- prem hardware for processing. There are many different sites and programs. This is just one way. DJI also have enterprise services like Terra that might do a far better job. This post is for hobby users. We will use tthe two services below.

Opendronemap

Opendronemap is an open source project with some tools to make 3d maps of images. It does not really have to be drone images. It consists of several services all called ODM something. It might be a little bit complicated to setup. however there is also a payed app version. We will deploy it with Docker.

DJI Mapper

DJI Mapper is a tool developed by Yaros. There are other tools but I found this easy. I suppose you could do this in the DJI Fly app to but it would be quite hard.

Other tools

WSL – Windows subsystem for Windows. Becasue we want to run the application on our Windows computer.

Docker – To make the application run. With Docker Compose

Portainer – To monitor our containers

Installation

In my case I will be using WSL as my computer is Windows. Running Docker on Windows is not a good idea. I could just as well use a dedicated Linux server. I have som Intel NUC servers running but in my case the mail laptop has better CPU and GPU. The image processing takes time and we need the speed of good hardware. Another option would be to setup the WebODM on a NUC and the worker node on another machine. I might do that in the future.

WSL

The easy way of installing WSL is by typing:

wsl --install

This will install Ubuntu. There are more settings and you can find the docs here. As WSL is Linux the path of your files will be:

\\wsl$\Ubuntu

You might need this path later on. Now when you open up a terminal you will have the option of opening WSL.

Docker and Docker Compose (and the Opendronemap containers)

Docker is a way of running applications in containers. I won’t go into detail but just explain how to make it work. First read the docs here. Things might change compared to below. Open your WSL terminal first.

Set up Docker’s apt repository.

# Add Docker's official GPG key:
sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc

# Add the repository to Apt sources:
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update

Install the Docker packages.

sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

Now Docker is installed. In general I suppose it could be a good idea to follow the official docs but in my case I wanted to get more control of what was happening and also be able to auto start the containers.

The script they are using is ./webodm.sh start and this more or less do the same thing optimizing the containers. So it is up to you. Use the script in the docs or do it like I do. Both will work. It might be easier using webodm.sh as you are able to parse arguments. Check out ./webodm.sh –help. However my way gives me more control.

I execute this:

git clone https://github.com/OpenDroneMap/WebODM
cd WebODM

Now you have everyhing in this folder. Now run “sudo nano docker-compose.yml”. Add it like this.

# This configuration does not include a processing node
# Which makes for faster setup times
#version: '2.1'
volumes:
  dbdata:
  appmedia:
services:
  db:
    image: opendronemap/webodm_db
    container_name: db
    expose:
      - "5432"
    volumes:
      - ${WO_DB_DIR}:/var/lib/postgresql/data:Z
    restart: unless-stopped
    oom_score_adj: -100
  webapp:
    image: opendronemap/webodm_webapp
    container_name: webapp
    entrypoint: /bin/bash -c "chmod +x /webodm/*.sh && /bin/bash -c \"/webodm/wait-for-postgres.sh db /webodm/wait-for-it.sh -t 0 broker:6379 -- /webodm/start.sh\""
    volumes:
      - ${WO_MEDIA_DIR}:/webodm/app/media:z
    ports:
      - "${WO_PORT}:8000"
    depends_on:
      - db
      - broker
      - worker
    environment:
      - WO_PORT
      - WO_HOST
      - WO_DEBUG
      - WO_BROKER
      - WO_DEV
      - WO_DEV_WATCH_PLUGINS
      - WO_SECRET_KEY
    restart: unless-stopped
    oom_score_adj: 0
	worker:
    image: opendronemap/webodm_webapp
    container_name: worker
    entrypoint: /bin/bash -c "/webodm/wait-for-postgres.sh db /webodm/wait-for-it.sh -t 0 broker:6379 -- /webodm/wait-for-it.sh -t 0 webapp:8000 -- /webodm/worker.sh start"
    volumes:
      - ${WO_MEDIA_DIR}:/webodm/app/media:z
    depends_on:
      - db
      - broker
    environment:
      - WO_BROKER
      - WO_DEBUG
      - WO_SECRET_KEY
    restart: unless-stopped
    oom_score_adj: 250
  node-odm:
    image: opendronemap/nodeodm
    expose:
      - "3000"
    restart: unless-stopped
    oom_score_adj: 500

  portainer:
    image: portainer/portainer-ce:latest
    container_name: portainer
    restart: always
    ports:
      - "9000:9000"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - /portainer_data:/data

We use the original compose file but with some minor differences. We add the processing node on the same machine. We disable the obsolete version row and we add portainer. Now run:

sudo docker compose up -d

This will download the containers and start them. They will be running until your computer restarts. You could just as well run Docker on a server and in this case the containers would be up and running all the time. Now you can open up http://localhost:9000. As you can see below all containers are up and running. You can restart them here. Also note the ip address of the node container. This is the docker ip address and not the local host ip. You will need this.

Opendronemap

I suppose we have already installed opendronemap components in the docker file above. It is up and running. There are many other settings like using Nvidia GPU or Micmac. You could add this in the docker file.

You can not go to http://localhost:8000/dashboard/. Create a user and password. Add a node and start testing. It could be a good idea to get back to the docs again so you can optimize the map generation.

I imported some sample images like these bananas. I just wanted to make sure it worked. Note that when you edit the node you should use the ip address of the container node. You can see this in Portainer. In my case it was 172.18.0.5. It may change! If so you can set it static.

Mapping my house

So I was ready to do a real test. First I used DJI Mapper to plan my waypoints. There are some good docs at the site so I won´t go into any details here. But some tips are.

  • Make sure you use correct camera settings
  • Do not modify the route after you added into Dji fly on your controller
  • Use wait when taking photos in order to avoid blur as the drone is moving

There is a new version coming soon that will be able to:

Split the mission into multiple submissions
Use distance-based triggers to reduce drastically the amount of waypoints needed

Below are the settings I used. Note the delay

And the Mini 4 Pro camera settings

So the drone went up above my house and tool 39 photos. Most likely I should have been taken more and also tried with another camera angle. The photos looked like this one.

Now it was time to open up http://localhost:8000/dashboard. I created a new project and imported my images. There are some options here that will affect the output. I did use the original size of the images. I also used default, 3d model and architecture. It made some differences. However my main insight was that next time I would need more images and from more angles. There is a hole in the house.

Below are the 3d map after the process in odm was finished. I did try with other settings as well but it more or less looked the same

Conclusion

Setting up ODM on WSL is quite simple. And the program runs quite fast even on my poor hardware. The main issue was my poor images. I also did a test with Reality Capture from Epic. It is also free and can be used with Unreal.

Some Links

Reddit UAVmapping

Overview | DroneDB

Reddit photogrammetry

Potree Viewer – Docker image

https://point.love