DJI Motion Controller

The DJI motion controller 1 was provided by DJI when I bought the drone pack.

This device is very cool and allows to pilot the drone even though you have never flown a drone... It's sooo simple !

I wanted to reuse this device to try to pilot RC planes connected to my TX16s buddy box.

It's easy to connect to motion controller to a PC or a smartphone and see it as a joystick.

But its outputs are quite misleading... So I decided to spend some time on this tricky challenge !

And you know what ? It works :-)

with a complex setup:

It's more or less like flying with an egg plant !

And works also with a much simpler setup :


Decoding the Motion Controller

I mounted the device on a tripod and connected it to my phone with a USB cable and entered the data into my phone using gamepad Tester App


It told me that this device has 4 buttons and 5 axis

If I align the motion controller to the north values are

from this "zero" postion if I rotate one axis to point to top I get

if I continue rotation on the same axis, pointing to north and down, I get:

if I rotate around the vertical axis from "zero" postion to point to "east" I get:

if I go on to point to south I get

now if I start from "zero" position and twist on the "roll" axis 90° I get

x=0
y= 0.5
Rx = 0


Preliminary conclusions 


The yaw axis is directly given by Rx value. It's an angle in the fixed reference frame of earth (values -1 to +1 for -PI to PI)
X and Y axis are given also in the earth reference frame (so they move together when you rotate around the vertical axis).
If we want them in motion controller ref frame (as any joystick or RC controller) then we have to apply rotation transformations from this fixed frame to the moving one (your hand)


Finally Rx gives an absolute angle. We want an angular velocity to control the rudder of our plane. So we need to evaluate the variation of Rx angle during time...


fixed frame to hand frame

Heading angle

heading =   Rx * pi  (expressed in radians, absolute value 0 = North)

Pitch angle

Pitch= -( Y*cos(heading) - X*sin(heading))

Roll angle

{Roll= - ( X*cos(heading) + Y*sin(heading))


With these formulae we have pitch and roll expressed into your "hand" ref frame. But heading is still espressed as an absolute value relative to north... To convert heading into yaw motion we need "a trick"

I used the "gimbal rotation" axis to latch the current heading (position of your hand relative to north) and then to compute variation of heading from this position.

If I release the gimbal switch then yaw is reset to zero until you press again this button.

I did try other solutions (introducing a "dead band" closed to yaw = 0 and detecting motion only if at a certain speed. It worked but was prone to some confusion.... So this simple "press and yaw" solution seemed to be better !


Test application

I wrote a small Basic for Android Application, starting from a working gamepad decoder, and implementing the formulae above.

result can be seen into this video


Current status is that it is quite easy to decode this motion controller and to compute "classical" Yaw/Pitch/Roll values that we could into into our RC radio Rudder/Elevator/Ailerons.


Testing with over engineered solution

To test this system "in flight" I wanted first to port the equations into an ESP32-S3 using ESP32Beans  USB host library. But it crashed... Details into this log

So I tried a different "over engineered approach"... go on with the APP and try to expose a Bluettoth Low Energy  joystick from the Android App... But I didn't succeed... So i decided to add an ESP32 in the middle; Android and ESP exchanging UDP messages and ESP32 exposing the BLE joystick...

Well quite long chain but it works and it even works with no perceptible latency !

here is the flowchart :

And here is the result

and it works. As you can see motion is smooth and learning curve is rather fast (at least on a simulator).

So next step will be to try to embed this code into a ESP32-C3 MCU  and to connect all this to my Buddy box

in order to fly a real RC plane

But before that here is a much simpler approach: a plugin for UCR


DJI MotionController plugin for Universal Control Remapper

UCR (Universal Control Remapper)  is a nice open source solution to create virtual Joysticks. I already used it to allow Phoenix RC simulator to run with Bluetooth joysticks (see here end of page).

UCR alllows to use "plugins" to remap the axies, buttons and so on to other virtual joystick.

However a plugin for a DJI motionController didn't exist yet... So I coded it !

you can find here on my gitub project : DJI motion controller UCR plugin

How to use it ?

Before installing UCR you need first to install the ViGem driver for emulation of DS4 and XBox360 controllers

ViGemBus driver

ViGem Currently supports emulation of the following USB Gamepads:

It can be found on this site : ViGEmBus driver – Virtual Gamepad Emulation Framework (ViGEm)

Download it and install it

UCR configuration

Configuring UCR is finally not complex at all !

download it, Install it.

Then locate the installation folder and copy my UCRplugins.dll into the plugins folder of UCR

Then create a new "profile"

then you will name it as you want (DJI_USB on my side !) and you will have to select the DJImotionController  joystick into the list of existing joysticks and remap it to a "virtual" DS4 joystick

Now you will have to remap your DJI motion controller axis to the virtual one.

Double click on the profile name (DJI_USB) it will open a new window

There you can click on "DJI MotionController" plugin to add a new "mixer" that you will have to fill (use the 3 dots menu on the right to bind each axis of the BLE joystick to the one of the DS4 controller

select the input axis one by one, then map the Yaw/Pitch/roll axis of the output to the virtual joystick ones

And you are good to go: your motion controller is now a regular joystick !


Running the virtual joystick

Once remmaping is done, using UCR virtual joystick is fairly simple :

select the profile and click the "play" button !

Now yo should see a new "Wireless Controller" under windows "game controllers" 

You can select it and see that you DJI MotionController is now seenas a joystick with "normal behavior"

Bear however in mind that the yaw axis has to be triggered when your hand is in "stable" position. To do this, simply pull up the "gimbal" slider. To desactivate : pull it down !


See it working here :

Enjoy

If you don't like UCR, another handy method does exist :JoystickGremlin

A DJI Motion Controller plugin for JoystickGremlin

JoystickGremlin installation

You will need to install Vjoy, select thelatest install from this site. This will install Vjoy and the needed driver.

Now install JoystickGremlin from the download tab. 

Copy the DjiMotionController plugin into the plugin folder of JoystickGremlin

You are ready to configure joystickGremlin with your DJI controller.

The idea is to remap the DJI into a viratual Vjoy joystick using the plugin to perform all the "maths"

Start to select your HID Joystick (the DJI one) from the main screen of Gremlin.

You should see 5 axis and a lot of buttons.

The axis MUST NOT be directly remapped to Vjoy as we want to use the plugin for this. So you will have to add a "NoOp" remapper (something which does nothing). Do this for the 5 axis.

You can (if you want ) remap the 4 first button to Vjoy ones directly as they are not handled by the plugin.

Now go the plugin tab and 

  1. add the DJI motion Controller plugin file.
  2. click the gear button
  3. assign each axis in the order of the picture

click on the gamecontroller icon and it will become Green (activated)

go to the "tools/Input Viewer" menu and select both the HID joystick and the Vjoy one.

You will see the "magic" the DJI axis (on top) are mapped to Yaw / pitch /roll joystick. Its sensitivity is perfect for a wrist rotation, south gap is no longer present on Yaw.

Your Vjoy DJI controller works !

Do Not forget to save this configuration for next time (menu Files/save Profile). And do not forget to click on the green gamecontroller to launch the virtual joystick.

Most of the flight simulators will accept Vjoy joystick to run. But not Phoenix... So if you want to use it a next step is required (simple one)

Xoutput virtual Xbox gamecontroller

Phoenix requires Xbox like game controller to be launced with the "SimEmu.exe" launcher.

Downlod Xoutput from this site. Install it as well as VigemBus driver

Launch it and select your Vjoy joystick (it must be "green" in joystickGremlin) and clcik on Add controller

now clcik edit and remap the 5 axis to your vJoy  joystick in this exact order

And you are good to go.

Check in Windows game controller (joy.cpl) that you see a  XBOX 360 controller. click on "advanced" and selct it as prefered joystick (to be in the first row!)

Launch Phoenix SimEmu.exe and select the first joystick proposed calibrate and fly !