Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Model management #188

Merged
merged 42 commits into from
May 6, 2021
Merged
Show file tree
Hide file tree
Changes from 39 commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
08d720b
model management setup
dhruv2295 Apr 20, 2021
2cacc19
filter list based on type
dhruv2295 Apr 20, 2021
57b1655
file download library setup
dhruv2295 Apr 27, 2021
146f6af
add pathtype enum to model class
dhruv2295 Apr 28, 2021
f53667e
model management model listing from config file
dhruv2295 Apr 28, 2021
5bca8f7
style file
dhruv2295 Apr 28, 2021
23abf62
model download progress
dhruv2295 Apr 28, 2021
f21f3e2
replace path with name for download
dhruv2295 Apr 28, 2021
fe4b185
load config from assets if it doesn't exist in app directory and copy…
dhruv2295 Apr 28, 2021
57adbbc
add id key to model class
dhruv2295 Apr 28, 2021
09e3897
storage permission
dhruv2295 Apr 28, 2021
a25caa2
setup file picker and add extension to file name in config
dhruv2295 Apr 28, 2021
33320b7
id setting fix for open picker model
dhruv2295 Apr 28, 2021
24868fe
model details screen
dhruv2295 Apr 29, 2021
280a43d
change submit text to done
dhruv2295 Apr 29, 2021
e3cf427
edit model UI overhaul, and model object update on edit
dhruv2295 Apr 29, 2021
022360a
remove setting model entries from xml
dhruv2295 May 1, 2021
b083251
remove unused code in preferences
dhruv2295 May 1, 2021
9127bf7
model loading doesn't need persmissions. fixed those. update data cha…
dhruv2295 May 1, 2021
0395aa4
hook new model system with all screens
dhruv2295 May 1, 2021
409f793
package autopilot model in app for simplicity and code cleanup
dhruv2295 May 1, 2021
3ede9b9
refactor download gradle file
dhruv2295 May 1, 2021
62b2651
delete model functionality
dhruv2295 May 2, 2021
6c54388
edit icon for model management
dhruv2295 May 2, 2021
5e24e43
style file
dhruv2295 May 2, 2021
3748696
edit model details on add from storage
dhruv2295 May 3, 2021
783c623
filter class in edit model screen based on type
dhruv2295 May 4, 2021
f2d50e8
fix extension in edit model screen
dhruv2295 May 4, 2021
706bc46
1. copy add model only after user approves it
dhruv2295 May 4, 2021
84b4a7a
1. model added message fix
dhruv2295 May 5, 2021
2d330c2
model file path fix after being renamed
dhruv2295 May 5, 2021
c29b68b
style file
dhruv2295 May 5, 2021
341dfbe
remove model picker from autopilot screen
dhruv2295 May 5, 2021
4be8c8b
save selected models
dhruv2295 May 5, 2021
8d9d61e
move file picker to model management
thias15 May 6, 2021
d42982c
fix shared prefs for default activity
thias15 May 6, 2021
7b9a1e5
minor refactor
thias15 May 6, 2021
7dd37bb
apply style
thias15 May 6, 2021
55ee345
default activity resolution fix
dhruv2295 May 6, 2021
69358f5
add some models
thias15 May 6, 2021
e32b804
rename models for consistency
thias15 May 6, 2021
1fed90e
fix number of threads displayed
thias15 May 6, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ android {
noCompress "tflite", "mp3"
}
compileOptions {
coreLibraryDesugaringEnabled true

sourceCompatibility = '1.8'
targetCompatibility = '1.8'
}
Expand Down Expand Up @@ -139,4 +141,9 @@ dependencies {
implementation 'com.google.firebase:firebase-crashlytics'
implementation 'com.google.firebase:firebase-analytics'
implementation 'com.nononsenseapps:filepicker:4.1.0'

coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
implementation 'com.koushikdutta.ion:ion:3.1.0'
implementation 'com.google.code.gson:gson:2.8.6'

}
4 changes: 2 additions & 2 deletions android/app/download.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ task downloadNetworks(type: Download) {
src([
'https://storage.googleapis.com/openbot_models/autopilot_float.tflite',
'https://storage.googleapis.com/openbot_models/mobile_ssd_v1_1.0_quant_coco.tflite',
'https://storage.googleapis.com/openbot_models/mobile_ssd_v3_small_quant_coco.tflite',
'https://storage.googleapis.com/openbot_models/yolo_v4_tiny_float_coco.tflite',
// 'https://storage.googleapis.com/openbot_models/mobile_ssd_v3_small_quant_coco.tflite',
// 'https://storage.googleapis.com/openbot_models/yolo_v4_tiny_float_coco.tflite',
'https://storage.googleapis.com/openbot_models/box_priors.txt',
'https://storage.googleapis.com/openbot_models/coco.txt',
'https://storage.googleapis.com/openbot_models/labelmap.txt',
Expand Down
2 changes: 1 addition & 1 deletion android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@
</activity>

<activity
android:name=".autopilot.BackHandlingFilePickerActivity"
android:name=".modelManagement.BackHandlingFilePickerActivity"
android:label="@string/app_name"
android:theme="@style/FilePickerTheme">
<intent-filter>
Expand Down
38 changes: 38 additions & 0 deletions android/app/src/main/assets/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
[
{
"id": 1,
"class": "AUTOPILOT_F",
"type": "AUTOPILOT",
"name": "Autopilot_F.tflite",
"pathType": "ASSET",
"path": "networks/autopilot_float.tflite",
"inputSize": "256x96"
},
{
"id": 2,
"class": "MOBILENETV1_1_0_Q",
"type": "DETECTOR",
"name": "MobileNetV1_1_0_Q.tflite",
"pathType": "ASSET",
"path": "networks/mobile_ssd_v1_1.0_quant_coco.tflite",
"inputSize": "300x300"
},
{
"id": 3,
"class": "MOBILENETV3_S_Q",
"type": "DETECTOR",
"name": "MobileNetV3_S_Q.tflite",
"pathType": "URL",
"path": "https://storage.googleapis.com/openbot_models/mobile_ssd_v3_small_quant_coco.tflite",
"inputSize": "320x320"
},
{
"id": 4,
"class": "YOLOV4",
"type": "DETECTOR",
"name": "YoloV4.tflite",
"pathType": "URL",
"path": "https://storage.googleapis.com/openbot_models/yolo_v4_tiny_float_coco.tflite",
"inputSize": "416x416"
}
]
173 changes: 42 additions & 131 deletions android/app/src/main/java/org/openbot/autopilot/AutopilotFragment.java
Original file line number Diff line number Diff line change
@@ -1,43 +1,32 @@
package org.openbot.autopilot;

import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Typeface;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.SystemClock;
import android.util.Size;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Toast;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.camera.core.ImageProxy;
import androidx.navigation.Navigation;
import com.google.android.material.bottomsheet.BottomSheetBehavior;
import com.nononsenseapps.filepicker.Utils;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import org.jetbrains.annotations.NotNull;
import org.openbot.R;
import org.openbot.common.CameraFragment;
Expand Down Expand Up @@ -78,77 +67,15 @@ public class AutopilotFragment extends CameraFragment implements ServerListener

private MultiBoxTracker tracker;

private Model model = Model.Autopilot_F;
private Model model;
private Network.Device device = Network.Device.CPU;
private int numThreads = -1;

private ArrayAdapter<CharSequence> modelAdapter;
private ActivityResultLauncher<Intent> mStartForResult;
private int selectedModelIndex = 0;
private ArrayAdapter<String> modelAdapter;

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mStartForResult =
registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
result -> {
if (result.getResultCode() == Activity.RESULT_OK) {

Intent intent = result.getData();
// Handle the Intent
List<Uri> files = Utils.getSelectedFilesFromResult(intent);

String fileName = new File(files.get(0).getPath()).getName();
if (FileUtils.checkFileExistence(requireActivity(), fileName)) {
AlertDialog.Builder builder = new AlertDialog.Builder(requireActivity());
builder.setTitle(R.string.file_available_title);
builder.setMessage(R.string.file_available_body);
builder.setPositiveButton(
"Yes", (dialog, id) -> processModelFromStorage(files, fileName));
builder.setNegativeButton(
"Cancel",
(dialog, id) -> {
// User cancelled the dialog
});
AlertDialog dialog = builder.create();
dialog.show();
} else {
processModelFromStorage(files, fileName);
}
}
});
}

private void processModelFromStorage(List<Uri> files, String fileName) {
try {
InputStream inputStream =
requireActivity().getContentResolver().openInputStream(files.get(0));
FileUtils.copyFile(inputStream, fileName, requireActivity().getFilesDir().getAbsolutePath());
} catch (IOException e) {
e.printStackTrace();
}

modelAdapter.clear();
modelAdapter.addAll(Arrays.asList(getResources().getTextArray(R.array.autopilot_models)));
modelAdapter.addAll(getModelFiles());
modelAdapter.add("Choose From Device");
modelAdapter.notifyDataSetChanged();
binding.modelSpinner.setSelection(modelAdapter.getPosition(fileName));
setModel(
new Model(
Model.ID.AUTOPILOT_F,
Model.TYPE.AUTOPILOT,
fileName,
null,
fileName,
new Size(256, 96)));

Toast.makeText(
requireContext().getApplicationContext(),
"AutoPilotModel added: " + model,
Toast.LENGTH_SHORT)
.show();
}

@Override
Expand All @@ -170,38 +97,37 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat

binding.cameraToggle.setOnClickListener(v -> toggleCamera());

List<CharSequence> models =
Arrays.asList(getResources().getTextArray(R.array.autopilot_models));
modelAdapter =
new ArrayAdapter<>(requireContext(), R.layout.spinner_item, new ArrayList<>(models));
modelAdapter.addAll(getModelFiles());
modelAdapter.add("Choose From Device");
List<String> models =
masterList.stream()
.filter(f -> f.type.equals(Model.TYPE.AUTOPILOT) && f.pathType != Model.PATH_TYPE.URL)
.map(f -> FileUtils.nameWithoutExtension(f.name))
.collect(Collectors.toList());
modelAdapter = new ArrayAdapter<>(requireContext(), R.layout.spinner_item, models);

modelAdapter.setDropDownViewResource(android.R.layout.simple_dropdown_item_1line);
binding.modelSpinner.setAdapter(modelAdapter);
if (!preferencesManager.getAutopilotModel().isEmpty())
binding.modelSpinner.setSelection(
Math.max(
0,
modelAdapter.getPosition(
FileUtils.nameWithoutExtension(preferencesManager.getAutopilotModel()))));

setAnalyserResolution(Enums.Preview.HD.getValue());
binding.modelSpinner.setOnItemSelectedListener(
new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
String selected = parent.getItemAtPosition(position).toString();
if (selected.equals("Choose From Device")) {
binding.modelSpinner.setSelection(selectedModelIndex);
openPicker();
} else
try {
setModel(Model.fromId(selected.toUpperCase()));
} catch (IllegalArgumentException e) {
setModel(
new Model(
Model.ID.AUTOPILOT_F,
Model.TYPE.AUTOPILOT,
selected,
null,
selected,
new Size(256, 96)));
}
selectedModelIndex = position;
try {
masterList.stream()
.filter(f -> f.name.contains(selected))
.findFirst()
.ifPresent(value -> setModel(value));

} catch (IllegalArgumentException e) {
e.printStackTrace();
}
}

@Override
Expand Down Expand Up @@ -272,28 +198,6 @@ public void onNothingSelected(AdapterView<?> parent) {}
binding.autoSwitch.setOnClickListener(v -> setNetworkEnabled(binding.autoSwitch.isChecked()));
}

private void openPicker() {

Intent i = new Intent(requireActivity(), BackHandlingFilePickerActivity.class);
// This works if you defined the intent filter
// Intent i = new Intent(Intent.ACTION_GET_CONTENT);

// Set these depending on your use case. These are the defaults.
i.putExtra(BackHandlingFilePickerActivity.EXTRA_ALLOW_MULTIPLE, false);
i.putExtra(BackHandlingFilePickerActivity.EXTRA_ALLOW_CREATE_DIR, false);
i.putExtra(BackHandlingFilePickerActivity.EXTRA_MODE, BackHandlingFilePickerActivity.MODE_FILE);

// Configure initial directory by specifying a String.
// You could specify a String like "/storage/emulated/0/", but that can
// dangerous. Always use Android's API calls to get paths to the SD-card or
// internal memory.
i.putExtra(
BackHandlingFilePickerActivity.EXTRA_START_PATH,
Environment.getExternalStorageDirectory().getPath());

mStartForResult.launch(i);
}

private void updateCropImageInfo() {
// Timber.i("%s x %s",getPreviewSize().getWidth(), getPreviewSize().getHeight());
// Timber.i("%s x %s",getMaxAnalyseImageSize().getWidth(),
Expand Down Expand Up @@ -342,6 +246,7 @@ protected void onInferenceConfigurationChanged() {
}

private void recreateNetwork(Model model, Network.Device device, int numThreads) {
if (model == null) return;
tracker.clearTrackedObjects();
if (autopilot != null) {
Timber.d("Closing autoPilot.");
Expand Down Expand Up @@ -544,18 +449,28 @@ public void onConnectionEstablished(String ipAddress) {}

@Override
public void onAddModel(String model) {
Model item =
new Model(
masterList.size() + 1,
Model.CLASS.AUTOPILOT_F,
Model.TYPE.AUTOPILOT,
model,
Model.PATH_TYPE.FILE,
requireActivity().getFilesDir() + File.separator + model,
"256x96");

if (modelAdapter != null && modelAdapter.getPosition(model) == -1) {
modelAdapter.add(model);
masterList.add(item);
FileUtils.updateModelConfig(requireActivity(), masterList);
} else {
if (model.equals(binding.modelSpinner.getSelectedItem())) {
setModel(
new Model(
Model.ID.AUTOPILOT_F, Model.TYPE.AUTOPILOT, model, null, model, new Size(256, 96)));
setModel(item);
}
}
Toast.makeText(
requireContext().getApplicationContext(),
"AutoPilotModel added: " + model,
"AutopilotModel added: " + model,
Toast.LENGTH_SHORT)
.show();
}
Expand All @@ -567,7 +482,7 @@ public void onRemoveModel(String model) {
}
Toast.makeText(
requireContext().getApplicationContext(),
"AutoPilotModel removed: " + model,
"AutopilotModel removed: " + model,
Toast.LENGTH_SHORT)
.show();
}
Expand All @@ -580,7 +495,7 @@ private void setModel(Model model) {
if (this.model != model) {
Timber.d("Updating model: %s", model);
this.model = model;
preferencesManager.setAutoPilotModel(model.toString());
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be nice to still maintain the previously selected model.

preferencesManager.setAutopilotModel(model.name);
onInferenceConfigurationChanged();
}
}
Expand Down Expand Up @@ -617,10 +532,6 @@ private void setNumThreads(int numThreads) {
}
}

private String[] getModelFiles() {
return requireActivity().getFilesDir().list((dir1, name) -> name.endsWith(".tflite"));
}

private void setSpeedMode(Enums.SpeedMode speedMode) {
if (speedMode != null) {
switch (speedMode) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import java.util.List;
import org.json.JSONObject;
import org.openbot.R;
import org.openbot.env.AudioPlayer;
Expand All @@ -23,9 +24,11 @@
import org.openbot.env.SharedPreferencesManager;
import org.openbot.env.Vehicle;
import org.openbot.main.MainViewModel;
import org.openbot.tflite.Model;
import org.openbot.utils.ConnectionUtils;
import org.openbot.utils.Constants;
import org.openbot.utils.Enums;
import org.openbot.utils.FileUtils;
import org.openbot.utils.FormatUtils;
import org.openbot.utils.PermissionUtils;
import timber.log.Timber;
Expand All @@ -41,6 +44,7 @@ public abstract class ControlsFragment extends Fragment {
protected AudioPlayer audioPlayer;

protected final String voice = "matthew";
protected List<Model> masterList;

@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
Expand All @@ -53,6 +57,7 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat

preferencesManager = new SharedPreferencesManager(requireContext());
audioPlayer = new AudioPlayer(requireContext());
masterList = FileUtils.loadConfigJSONFromAsset(requireActivity());

requireActivity()
.getSupportFragmentManager()
Expand Down
Loading