BT-45C/45CS Support Tools
This section describes required procedure for the application development of the Moverio controller.
The description explains how to install Android SDK using Windows 10 PC as an example.
Android Studio will be downloaded from following Android developer's site.
https://developer.android.com/studio/
Follow an installer instruction and install Android Studio on your PC.
The later explanation is based on the SDK is installed in the following folder
C:\Users\<user name>\AppData\Local\Android\Sdk
When developing an application in a network environment that requires proxy settings, set the Android Studio proxy settings. Please check the detailed procedure on the site below.
https://developer.android.com/studio/intro/studio-config#gradle-plugin
If you do not know the proxy settings, ask your network administrator how to connect to the external network using the proxy.
Use the Android SDK Manager for the tools required for application development. Please check the detailed procedure on the site below.
https://developer.android.com/studio/intro/update#sdk-manager
Use the ADB connection confirmation command to check if the computer and host device are connected.
Start a command prompt and run;
"cd C:\Users\<user name>\AppData\Local\Android\sdk\platform-tools"
*It is convenient to set the above path as an environment variable.
If you execute "adb devices" and the device name is displayed in the list, ADB connection is established.
If it is not displayed, reconnect the host device with USB and execute "adb devices" again.
Moverio Controller Function SDK has dedicated API for controlling the Moverio controller. Describe the method for using dedicated API.
Following description is based on using Android Studio.
Display the Project View of Android Studio and create a "libs" folder from [File]-[New]-[Directory].
After C:¥Users¥<user name>¥AndroidStudioProjects¥<application name>¥app¥libs is created.
Put MoverioControllerFunctionSDK_1.0.0.aar there.
Then define your application's minimum API level at 28 and add MoverioControllerFunctionSDK_1.0.0.aar to your application's dependencies.
apply plugin: 'com.android.application'
android {
:
// Add API level 28
minSdkVersion 28
:
}
dependencies {
:
// Add Moverio Controller Function SDK.aar
implementation files('libs/MoverioControllerFunctionSDK_1.0.0.aar')
:
:
}
Press the Sync Project with Gradle Files button at the top of Android Studio to reflect Gradle changes to the project.
When developing an application for a headset model (USB connection type Moverio headset), confirm the application behavior in the state of connecting Moverio headset and the Moverio controller via USB. However, the PC and the Moverio controller are not connected by USB, so wired debugging cannot be performed at this time.
This section describes how to develop and debug application software for headset models and the Moverio controller that are connected via USB by connecting to the Moverio controller via a network. Please check the following sites as well.
https://developer.android.com/studio/command-line/adb#wireless
# adb tcpip 5555
# adb connect ip_address (e.g. adb connect 192.168.1.10#5555)
Firstly, please import com.epson.moverio.btcontrol.BtCustomKey such as below.
import com.epson.moverio.btcontrol.BtCustomKey;
Next, please create an instance of BtCustomKey class and specify the key constants in the table below in the first argument of the setKeyEnable() method, and specify a boolean type lock (false) and unlock (true) in the second argument and call it.
Constants | Description |
---|---|
BtCustomKey.VOLUME_UP | Volume up key |
BtCustomKey.VOLUME_DOWN | Volume down key |
BtCustomKey.TRIGGER | Function key |
BtCustomKey.HOME | Home key |
BtCustomKey.BACK | Back key |
BtCustomKey.APP_SWITCH | History key |
BtCustomKey.POWER | Power button |
BtCustomKey.ALLKEY | Used to specify all physical keys |
public class UIControlActivity extends Activity {
private BtCustomKey mBtCustomKey = null;
private Button mButton_powerKeyLock = null;
@Override
public final void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mBtCustomKey = new BtCustomKey(this);
mButton_powerKeyLock = (Button) findViewById(R.id.button_powerKeyLock);
mButton_powerKeyLock.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mBtCustomKey.setKeyEnable(BtCustomKey.POWER, false); /* Disable power key. */
}
});
}
:
:
}
This API can change the key code assigned to the physical key of the Moverio controller. However, it is impossible to change the key code of the power button.
Firstly, please import com.epson.moverio.btcontrol.BtCustomKey such as below.
import com.epson.moverio.btcontrol.BtCustomKey;
Next, please create an instance of the BtCustomKey class and specify the target physical key in the table below as the first argument of the setKeyAssign() method, and specify the key code as the second argument.
Target Physical Key | Key Code |
---|---|
BtCustomKey.VOLUME_UP | KeyEvent.KEYCODE_VOLUME_UP |
BtCustomKey.VOLUME_DOWN | KeyEvent.KEYCODE_VOLUME_DOW |
BtCustomKey.TRIGGER | KeyEvent.KEYCODE_FUNCTION |
BtCustomKey.HOME | KeyEvent.KEYCODE_HOME |
BtCustomKey.BACK | KeyEvent.KEYCODE_BACK |
BtCustomKey.APP_SWITCH | KeyEvent.KEYCODE_APP_SWITCH KeyEvent.KEYCODE_F1 |
KeyEvent.KEYCODE_F2 | |
KeyEvent.KEYCODE_F3 | |
KeyEvent.KEYCODE_F4 |
public class UIControlActivity extends Activity {
private BtCustomKey mBtCustomKey = null;
private Button mButton_appSwitch2Home = null;
@Override public final void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mBtCustomKey = new BtCustomKey(this);
mButton_appSwitch2Home = (Button) findViewById(R.id.button_appSwitch2Home);
mButton_appSwitch2Home.setOnClickListener(new View.OnClickListener() {
@Override public void onClick(View view) {
mBtCustomKey.setKeyAssign(BtCustomKey.APP_SWITCH, KeyEvent.KEYCODE_HOME);
}
});
}
:
:
}
This API can control LED indicator of the Moverio controller (Lighted mode/Not lighted mode) .
Firstly, please import com.epson.moverio.btcontrol.BtControllerLedMode.
import com.epson.moverio.btcontrol.BtControllerLedMode;
Next, please create an instance of BtControllerLedMode class and specify constants in the table below as the first argument of the setControllerLedMode() method.
Constants | Description |
---|---|
BtControllerLedMode.MODE_OFF | Not lighted mode |
BtControllerLedMode.LED_MODE_NORMAL | Lighted mode |
public class UIControlActivity extends Activity {
private BtControllerLedMode mBtLed = null;
private Button mButton_ledOff = null;
@Override public final void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mBtLed = new BtControllerLedMode (this);
mButton_ledOff = (Button) findViewById(R.id.button_appSwitch2Home);
mButton_ledOff.setOnClickListener(new View.OnClickListener() {
@Override public void onClick(View view) {
mBtLed.setControllerLedMode(BtControllerLedMode.MODE_OFF);
}
});
}
:
:
}
The Moverio controller has Mirror mode (Same picture is shown between headset and controller) and Trackpad mode(Usable trackpad on controller screnn).
This API can switch these modes.
Firstly, please import com.epson.moverio.btcontrol.UIControl.
import com.epson.moverio.btcontrol.UIControl;
Next, please create an instance of UIControl class and specify constants in the table below as the first argument of the setUiMode() method.
Constants | Description |
---|---|
UIControl.UI_MODE_MIRROR | Switch to Mirror mode |
UIControl. UI_MODE_TRACK | Switch to Trackpad mode |
public class UIControlActivity extends Activity {
private UIControl mUiMode = null;
private Button mButton_modeTrack = null;
@Override public final void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mUiMode = new UIControl (this);
mButton_modeTrack = (Button) findViewById(R.id.button_appSwitch2Home);
mButton_modeTrack.setOnClickListener(new View.OnClickListener() {
@Override public void onClick(View view) {
mUiMode.setUiMode(UIControl. UI_MODE_TRACK);
}
});
}
:
:
}
Note : When the modes are switched by this AP, the application is closed automatically to application screen reconstruction. After completed to switch mode, the application screen (Activity) before closed is shown again automatically.
BT-35E and BT-45C have front facing headset camera. The Moverio controller can get camera data (picture, video) by Android Camera API or Moverio SDK. In addition, the camera data can be applied to various uses (e.g. marker recognition, etc.).
This section describes how to control BT-35E camera and BT-45C camera with the Moverio controller.
*Note : This document is for OS version 2.0.00 of the Moverio controller.
The Moverio controller can control BT-45C/BT-35E camera using Android CameraAPI or Moverio Basic Function SDK. Please refer to MoverioBasicFunctionSDK_DevelopersGuide_JA_1.2.0 for the camera control. However, camera control by Android CameraAPI and Moverio Basic Function SDK cannot use at the same time. After controlling the camera with the Moverio Basic Function SDK, Android CameraAPI cannot detect the camera. When using Android CameraAPI after using camera control by Moverio Basic Function SDK, please reconnect BT-45C / BT-35E.
There are CameraAPI1 and CameraAPI2 available for Android CameraAPI. Please refer to following information for the usages of each API.
https://developer.android.com/training/camera
*Note:CameraAPI1 is deprecated
https://developer.android.com/training/camera2
https://medium.com/google-developers/detecting-camera-features-with-camera2-61675bb7d1bf#.2x3icoqnc
The following information is sample code for a camera application using CameraAPI2. Build and run app to the Moverio controller and launch the application with BT-45C/BT-35E connected, BT-45C/BT-35E camera can now be used. Please refer to this for implementing application.
https://github.com/googlearchive/android-Camera2Basic?utm_campaign=adp_series_cameragithub_030916&utm_source=gdev&utm_medium=yt-desc
It is possible to control the BT-45C/BT-35E camera in the Moverio controller by Android CameraAPI2. However, it is impossible to change some settings from Android CameraAPI2. Please use Moverio Basic Function SDK if want to change these settings. The spec of BT-45C/BT-35E camera and controllability of the settings by each API / SDK are described in "The correspondence table of setting controllability by Android CameraAPI2 / Moverio SDK".
The correspondence table of setting controllability by Android CameraAPI2 / Moverio Basic Function SDK
Settings | BT-35E | BT-45C | Android CameraAPI | Moverio Basic Function SDK |
---|---|---|---|---|
Resolution | 640x480 | 640x480 | ||
1280x720 | 1280x720 | |||
1600x1200 | ||||
1920x1080 | 1920x1080 | |||
2560x1440 | ||||
2592x1944 | ||||
3264x2448 | ||||
Exposure compensation | auto/manual | auto/manual | auto only | |
The step of manual exposure compensation |
-5 ~ +5 | -7 ~ +5 | ||
Focus mode | Off (Pan) | auto/manual | auto only | |
Manual focus | +50 ~ +3000[mm] | |||
Sharpness | 0 ~ +128 | |||
Brightness | -127 ~ +127 | 0 ~ +255 | ||
Gain | 0 ~ +255 | +1024 ~ +16383 | ||
White balance | auto/cloudy_daylight(6000K)/ daylght(5500K)/fluorescent(4200K)/ incandescent(3200K)/twilight(3500K) |
auto/cloudy_daylight(6000K)/ daylight(5500K)/fluorescent(4200K)/ incandescent(3200K)/twilight(3500K) |
auto only | |
Power frequency | 50Hz/60Hz | 50Hz/60Hz/Disable | ||
Indicator mode | auto | Auto/on/off |
The specification of some Android CameraAPI of the Moverio controller are different with standard Android CameraAPI. This topic explains about this specification on CameraAPI2.
The code snippet for getting camera characteristics
CameraManager manager = (CameraManager)getSystemService(CAMERA_SERVICE);
try {
for (String cameraId : manager.getCameraIdList()) {
CameraCharacteristics chars = manager.getCameraCharacteristics(cameraId);
// Do something with the characteristics
}
} catch (CameraAccessException e) {
e.printStackTrace();
}
"The code snippet for getting camera characteristics" specify the cameraId and get camera
characteristics. The Moverio controller has two USB port (Bottom port, Side port) and it is possible to control the BT-45C/BT-35E camera and USB camera by connecting these. However, BT-45C/BT-35E is supported on Bottom port only.
When BT-45C/BT-35E is connected to Bottom port, the cameraId is assigned such as "The cameraId at connecting BT-45C/BT-35E".
The cameraId at connecting BT-45C/BT-35E
Camera API | The Moverio controller Back Camera | Bottom port | Side port * |
---|---|---|---|
Camera API1 | 1 | 0 | 2 |
Camera API2 | /dev/video3 | 0 | /dev/video4 |
* In case of connecting USB camera to Side port
The Moverio controller gets camera characteristics from CameraCharacteristics and can select intended camera.
The code snippet for getting camera lends direction
CameraCharacteristics chars = manager.getCameraCharacteristics(cameraId);
Integer facing = chars.get(CameraCharacteristics.LENS_FACING);
"The code snippet for getting camera lens facing" specify cameraId and get the lens facing from camera characteristics.
When BT-45C/BT-35E is connected to Bottom port, the lens facing is assigned such as "The lens facing at connecting BT-45C/BT-35E".
The lens facing at connecting BT-35E
Camera API | BO-IC400 Back Camera Bottom | Bottom port | Side port * |
---|---|---|---|
Camera API1 | FRONT | BACK | FRONT |
Camera API2 | EXTERNAL | BACK | EXTERNAL |
"The code snippet for using BT-45C/BT-35E camera" is that code snippet in case of using BT-45C/BT-35E camera.
The code snippet for using BT-45C/BT-35E camera
CameraManager manager = (CameraManager)getSystemService(CAMERA_SERVICE);
try {
for (String cameraId : manager.getCameraIdList()) {
CameraCharacteristics chars = manager.getCameraCharacteristics(cameraId);
Integer facing = chars.get(CameraCharacteristics.LENS_FACING);
if (facing != null && facing == CameraCharacteristics.LENS_FACING_BACK) {
// Open BT-45C/BT-35E camera (Please refer to upper link)
}
}
} catch (CameraAccessException e) {
e.printStackTrace();
}
The information of cameraId is used for not only opening camera but setTorchMode API that uses camera flash light. The table "The cameraId at connecting BT-45C/BT-35E" is applied for setTorchMode too. When want to use back flash light of the Moverio controller with connecting BT-45C/BT-35E, need to specify "/dev/video3" as cameraId.
When USB camera is connected to USB port (Bottom or Side), the cameraId is assigned such as "The cameraId at connecting USB camera".
The cameraId at connecting USB camera
Camera API | The Moverio controller Back Camera | Bottom Port * | Side Port * |
---|---|---|---|
Camera API1 | 0 | 1 or 2 | 1 or 2 |
Camera API2 | 0 | /dev/video3 or 4 | /dev/video3 or 4 |
* cameraId can be assigned a lower number Id from the first recognized device
The lens facing is assigned such as "The lens facing at connecting USB camera".
The lens facing at connecting USB camera
Camera API | The Moverio controller Back Camera | Bottom Port | Side Port |
---|---|---|---|
Camera API1 | BACK | FRONT | FRONT |
Camera API2 | BACK | EXTERNAL | EXTERNAL |
If the Moverio controller use USB camera, please specify the parameters of "The cameraId at connecting USB camera" and "The lens facing at connecting USB camera" to the source code of "The code snippet for using BT-45C/BT-35E camera".
At Android CameraAPI2 sample source code, the screen rotation process depending on the Moverio controller rotate state is executed in order to do appropriate camera preview.
However, when the same process is executed using BT-45C/BT-35E camera, the Moverio controller rotate state and BT-35E rotate state don't synchronize. As a result, the mismatch of camera preview is occurred. Therefore, when the Moverio controller use BT-35E camera, recommend to not include the screen rotation process such as "The source code of not including screen rotation process" (Comment out "matrix.postRoatate()").
The source code of not including screen rotation process
if (Surface.ROTATION_90 == rotation || Surface.ROTATION_270 == rotation) {
bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY());
matrix.setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL);
float scale = Math.max((float) viewHeight / mPreviewSize.getHeight(), (float) viewWidth / mPreviewSize.getWidth());
matrix.postScale(scale, scale, centerX, centerY);
// matrix.postRotate(90 * (rotation - 2), centerX, centerY);
}
In addition, the return values of AndroidAPI regarding screen rotation are fixed value on Trackpad mode like "The AndroidAPI regarding screen rotation".
The AndroidAPI regarding screen rotation
Android API | Return value |
---|---|
Display#getRotation() | ROTATION_0 |
Configuration#orientation | ORIENTATION_LANDSCAPE |
The mounting angle differs between the camera mounted on the Moverio controller and the camera mounted on BT-45C/BT-35E. Please refer to the table below for details.
The return value of CameraCharacteristics.get(CameraCharacteristics.SENSOR_ORIENTATION)
Type of Camera | Return value |
---|---|
The Moverio controller Back Camera | 90 |
BT-45C/BT-35E Camera | 0 |
Therefore, if use BT-45C/BT-35E camera and preview the image assuming 90-degree mounting angle, the preview screen may be distorted. For example, a square object will appear as a rectangle. It is recommended that pay attention to the mounting angle and preview the image appropriately for the resolution of the acquired image.
The Android CameraAPI2 sample source code assumes a 90-degree mounting angle for previewing. With the following modification such as "The code of changing appropriate aspect ratio", the BT-45C/BT-35E camera can preview with the proper aspect ratio.
The code of changing appropriate aspect ratio
if(mSensorOrientation != 0){
// When the mounting angle is not 0-degree, it is BO-IC400 back camera, so it should be the same as the original source code.
if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
mTextureView.setAspectRatio(mPreviewSize.getWidth(),mPreviewSize.getHeight());
} else {
mTextureView.setAspectRatio(
mPreviewSize.getHeight(), mPreviewSize.getWidth());
}
} else {
// When the mounting angle is 0-degree, it is determined to be BT-35E camera (USB camera).
//BT-35E camera doesn't rotate regardless of the device state, so the aspect ratio is always assumed to be horizontal preview.
mTextureView.setAspectRatio(
mPreviewSize.getWidth(), mPreviewSize.getHeight());
}
if(mSensorOrientation !=0) {
// For BT-35E camera, the following process is not necessary because BT-35E camera doesn't rotate regardless of the device state.
if (Surface.ROTATION_90 == rotation || Surface.ROTATION_270 == rotation) {
bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY());
matrix.setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL);
float scale = Math.max((float) viewHeight / mPreviewSize.getHeight(), (float) viewWidth / mPreviewSize.getWidth());
matrix.postScale(scale, scale, centerX, centerY);
matrix.postRotate(90 * (rotation - 2), centerX, centerY);
} else if (Surface.ROTATION_180 == rotation) {
matrix.postRotate(180, centerX, centerY);
}
}