Adjust THETA Z1 Settings Without a Mobile Phone

2021 February 8 Updated with Developer Information including the GitHub repo for the code used in this project.

This plug-in adjusts the THETA Z1 settings in the field without a mobile phone.

With this THETA plug-in, you can change the shooting settings by combining THETA’s position (tilt) and button operations.
Most shooting settings can be done without a smartphone.

The settings that can be operated with this plug-in are as follows.

  • Change shooting mode (still image/video)
  • Change the exposure mode (Auto/Av/Tv/Iso/Manual)
  • Change shooting settings for each exposure mode
    (Aperture, shutter speed, ISO sensitivity, white balance, Option setting in still image auto mode [NR/DR Comp/HDR/ Hh HDR]
  • Change the white balance specification method (preset/color temperature)
  • Change file format (JPEG / RAW +) when shooting still images
  • Change self-timer on/off
  • Change continuous shooting mode (Off/Time Shift/Interval/Interval Composite)

When you close the plug-in, the setting change made with the plug-in is saved and will be adopted when the plug-in is restarted.

This plug-in is compatible with remote controllers (HID devices that send out the “Vol +” key code).

Also see the video below.

File Organization

Since various shooting settings are made using the RICOH THETA API, I created them based on the source code of this article (in Japanese), which already covered most shooting and OLED display settings.

Newly created or newly modified files are as follows.

theta-plugin-switchbot-link\app\src\main
├assets       // Contains OLED display images. There are some new icons, but they look good, so I won't explain them.
└java\com\theta360
 ├pluginapplication
 │ ├model   // THETA Plug-in SDK as-is
 │ ├network // Added a method to HttpConnector.java like before 
 │ ├oled    // Oled.java (basically an OLED drawing library) only
 │ └task    // ChangeFilterTask.java and ChangeFormatTask.java are new
 │          // Fixed GetCameraStatusTask.java, ShutterButtonTask.java, ChangeShutterSpeedTask.java, ChangeWbTask.java
 └tiltui    // Attitude.java is the same as before. It is a convenient class.
            // MainActivity.java and DisplayInfo.java contain the unique items of this plug-in

How to Asses Tilt

Please refer to the links below for information on the following three basic items. All three links are in Japanese.

About getOrientation

Posture class Attitude.java

How to use posture class

Basic Structure of the Program

A thread that operates periodically is created in MainActivity.java, and the following processing is performed. Since the status of the shooting task is acquired periodically by WebAPI, it is operated while taking a rest of 200 milliseconds, so that the internal communication load does not become too high.

   public void drawOledThread() {
        new Thread(new Runnable() {
            @Override
            public void run() {

                //If there is something to do before the loop ...

                //Drawing loop
                while (mFinished == false) {
                    //Status check and drawing
                    try {
                        //Orientation information acquisition & orientation related information update
                        displayInfo.setTiltStatus(attitude.getDegAzimath(), attitude.getDegPitch(), attitude.getDegRoll());

                        //Internal state acquisition
                        new GetCameraStatusTask(mGetCameraStatusCallback).execute();

                        // OLED display
                        displayInfo.displayTiltUI();

                        // Upside down && WB changeable -> Preset <-> CT switching
             ~abbreviation~

                        //Processing when twisting operation is detected
             ~abbreviation~

                        //Execution of button operations
             ~abbreviation~

                        //Sleep so that internal communications load does not get too high
                        Thread.sleep(200);

                    } catch (InterruptedException e) {
                        // Deal with error.
                        e.printStackTrace();
                    } finally {
                        //
                    }

                }
            }
        }).start();
    }

Judging the Orientation

Judging the orientation of the THETA is done by the setTiltStatus method of the Displayinfo class, which is called at the beginning of the above periodic operation thread.

The processing contents are as follows.

   void setTiltStatus(double inYaw, double inPitch, double inRoll) {
        beforDegAzimath = degAzimath;
        degAzimath = inYaw;
        degPitch = inPitch;
        degRoll = inRoll;

        beforTilt = curTilt;
        if ( (-45 <= degPitch) && (degPitch<45) ) {
            if ( (-45<=degRoll) && (degRoll<=45) ) {
                curTilt = TILT_BASE;
            } else if ( (45<=degRoll) && (degRoll<=135) ) {
                curTilt = TILT_RIGHT;
            } else if ( (-135<=degRoll) && (degRoll<=-45) ) {
                curTilt = TILT_LEFT;
            } else if ( ((135<=degRoll) && (degRoll<=180)) ||
                    ( (-180<=degRoll) && (degRoll<=-135) ) ) {
                curTilt = TILT_UPSIDE_DOWN;
                occurUpsideDown=true;
            } else {
                curTilt = TILT_ERROR;
            }
        } else if ( (45 <= degPitch) && (degPitch<=90) ) {
            curTilt = TILT_FRONT;
        } else if ( (-90 <= degPitch) && (degPitch<=-45) ) {
            curTilt = TILT_BACK;
        } else {
            curTilt = TILT_ERROR;
        }

        //Twist event check
        if ( curTilt == TILT_BASE ) {
            double diffAzimath = beforDegAzimath-degAzimath;
            if ( diffAzimath >= TWIST_THRESH ) {
                lastEvent = EVENT_TWIST_L;
            } else if ( diffAzimath <= -1.0*TWIST_THRESH) {
                lastEvent = EVENT_TWIST_R;
            } else {
                //No twist event
            }
        }

        //Tilt event check
        boolean occurChangeEvent = false;
        if ( (curTilt==TILT_BASE)&&(beforTilt!=TILT_BASE) ) {
            occurChangeEvent = true;

            if (occurUpsideDown) {
                occurUpsideDown=false;
                lastEvent =EVENT_UPSIDE_DOWN;
            } else {
                switch (beforTilt) {
                    case TILT_FRONT :
                        lastEvent =EVENT_FRONT;
                        break;
                    case TILT_BACK :
                        lastEvent =EVENT_BACK;
                        break;
                    case TILT_RIGHT :
                        lastEvent =EVENT_RIGHT;
                        break;
                    case TILT_LEFT :
                        lastEvent =EVENT_LEFT;
                        break;
                    default:
                        //No processing: It shouldn't happen but just in case
                        break;
                }
            }

            // Changeable parameter transition
            ~abbreviation~

        }

    }

First, after determining the current orientation, the event is set according to the change from the previous orientation in the periodic motion. The process that follows this process only behaves in response to the event.

It’s a hassle to write, but it’s not difficult.

Common Structure of Tasks for Setting Shooting

With this plug-in, you can set various shooting settings, and 11 types of tasks are prepared for each setting item. I wanted to have a common Callback process after each task was processed, so I am using a mechanism called Consumer on Android. It is not full of callbacks and can be described clearly.

Conclusion

Partially because of the almost stick shape of a RICOH THETA, I think we were able to expand functions very well.

I think there are quite a lot of RICOH THETA Z1 users who want to make shooting settings without a smartphone. Remember, it is available in the THETA Plug-in Store. It’s called the Change via Tilt plug-in. Please give it a tilt!