Skip to content

Commit

Permalink
feat: sklearn ExtraTrees predictor
Browse files Browse the repository at this point in the history
  • Loading branch information
pavanchhatpar committed Mar 8, 2018
1 parent 694e6a7 commit 21e8467
Show file tree
Hide file tree
Showing 10 changed files with 308 additions and 145 deletions.
2 changes: 2 additions & 0 deletions vta-android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ dependencies {
implementation 'com.android.support:design:27.0.2'
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
implementation 'com.android.volley:volley:1.1.0'
implementation 'com.google.code.gson:gson:2.8.2'
implementation 'com.google.android.gms:play-services-maps:11.8.0'
implementation 'com.google.android.gms:play-services-location:11.8.0'
implementation 'com.google.android.gms:play-services-places:11.8.0'
Expand All @@ -37,6 +38,7 @@ dependencies {
implementation 'com.google.maps.android:android-maps-utils:0.5+'
implementation 'org.tensorflow:tensorflow-android:+'
implementation 'ch.hsr:geohash:1.3.0'
implementation 'org.jetbrains.anko:anko-common:0.9'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.1'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
Expand Down
Binary file removed vta-android/app/libs/wekaSTRIPPED.jar
Binary file not shown.
1 change: 1 addition & 0 deletions vta-android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
<application
android:name=".VTAApplication"
android:allowBackup="true"
android:largeHeap="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,13 @@ import com.android.volley.Response
import com.beproject.group1.vta.R
import com.beproject.group1.vta.VTAApplication
import com.beproject.group1.vta.helpers.APIController
import com.beproject.group1.vta.helpers.ExtraTreesClassifier
import com.beproject.group1.vta.helpers.TFPredictor.Companion.model_name
import com.beproject.group1.vta.helpers.VolleyService
import com.beproject.group1.vta.helpers.WekaPredictor

import kotlinx.android.synthetic.main.activity_login.*
import org.jetbrains.anko.doAsync
import org.jetbrains.anko.uiThread
import org.json.JSONObject
import java.io.*
import java.text.SimpleDateFormat
Expand Down Expand Up @@ -198,41 +200,41 @@ class LoginActivity : AppCompatActivity(), LoaderCallbacks<Cursor> {
spe.putString("email", emailStr)
spe.putString("password", passwordStr)
spe.apply()
wekaSync(sp)
sklearnSync(sp)
// maybeSync(sp)
}

}
}
}

private fun wekaSync(sp: SharedPreferences) {
private fun sklearnSync(sp: SharedPreferences) {
val accessToken = sp.getString("id", null)
val wmtime = sp.getString("wmtime", null)
val smtime = sp.getString("smtime", null)
val intent = Intent(this@LoginActivity, MapsActivity::class.java)
val tz = TimeZone.getTimeZone("UTC")
val sdf = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.getDefault())
sdf.timeZone = tz
apiController.getFileInfo("${WekaPredictor.model_name}.zip", accessToken){ response ->
apiController.getFileInfo("${ExtraTreesClassifier.model_name}.zip", accessToken){ response ->
if(response == null) {
Toast.makeText(applicationContext, getString(R.string.offline_alert), Toast.LENGTH_SHORT).show()
this@LoginActivity.startActivity(intent)
this@LoginActivity.finish()
} else {
val newwmtime = response.getString("mtime")
if(wmtime == null) {
val newsmtime = response.getString("mtime")
if(smtime == null) {
val spe = sp.edit()
spe.putString("wmtime", newwmtime)
spe.putString("smtime", newsmtime)
spe.apply()
syncWekaAndLaunchApp(intent, accessToken)
syncSklearnAndLaunchApp(intent, accessToken)
} else {
val date1 = sdf.parse(wmtime)
val date2 = sdf.parse(newwmtime)
val date1 = sdf.parse(smtime)
val date2 = sdf.parse(newsmtime)
if (date1.before(date2)) {
val spe = sp.edit()
spe.putString("wmtime", newwmtime)
spe.putString("smtime", newsmtime)
spe.apply()
syncWekaAndLaunchApp(intent, accessToken)
syncSklearnAndLaunchApp(intent, accessToken)
} else {
this@LoginActivity.startActivity(intent)
this@LoginActivity.finish()
Expand All @@ -242,25 +244,53 @@ class LoginActivity : AppCompatActivity(), LoaderCallbacks<Cursor> {
}
}

private fun syncWekaAndLaunchApp(intent: Intent, accessToken: String) {
private fun syncSklearnAndLaunchApp(intent: Intent, accessToken: String) {
sync_message.visibility = View.VISIBLE
apiController.downloadFile("${WekaPredictor.model_name}.zip", accessToken, Response.Listener<ByteArray> { response ->
apiController.downloadFile("${ExtraTreesClassifier.model_name}.zip", accessToken, Response.Listener<ByteArray> { response ->
try {
if (response != null) {
val outputStream: FileOutputStream
val name = "${WekaPredictor.model_name}.zip"
val name = "${ExtraTreesClassifier.model_name}.zip"
outputStream = openFileOutput(name, Context.MODE_PRIVATE)
outputStream.write(response)
outputStream.close()
Toast.makeText(this, "WEKA Download complete.", Toast.LENGTH_LONG).show()
val b = unpackZip("${filesDir.absolutePath}/", name)
Toast.makeText(this, "WEKA unzip: $b.", Toast.LENGTH_LONG).show()
sync_message.visibility = View.GONE
this@LoginActivity.startActivity(intent)
this@LoginActivity.finish()
Toast.makeText(this, "Model Download complete.", Toast.LENGTH_LONG).show()
doAsync {
val b = unpackZip("${filesDir.absolutePath}/", name)
uiThread {
Toast.makeText(applicationContext, "Model unzip: $b.", Toast.LENGTH_LONG).show()
}
}
apiController.downloadFile("${ExtraTreesClassifier.map_prefix}-map.zip", accessToken, Response.Listener<ByteArray> {res ->
try {
if (res != null) {
val os: FileOutputStream
val zname = "${ExtraTreesClassifier.map_prefix}-map.zip"
os = openFileOutput(zname, Context.MODE_PRIVATE)
os.write(res)
os.close()
Toast.makeText(this, "Mapping Download complete.", Toast.LENGTH_LONG).show()
doAsync {
val zb = unpackZip("${filesDir.absolutePath}/", zname)
uiThread {
Toast.makeText(applicationContext, "Mapping unzip: $zb.", Toast.LENGTH_LONG).show()
}
}
sync_message.visibility = View.GONE
this@LoginActivity.startActivity(intent)
this@LoginActivity.finish()
}
} catch (e: Exception) {
Log.d("SYNC_ERROR", "UNABLE TO DOWNLOAD MAP FILE")
e.printStackTrace()
}
}, Response.ErrorListener { err ->
err.printStackTrace()
})

}
} catch (e: Exception) {
Log.d("SYNC_ERROR", "UNABLE TO DOWNLOAD WEKA FILE")
Log.d("SYNC_ERROR", "UNABLE TO DOWNLOAD MODEL FILE")
e.printStackTrace()
}
}, Response.ErrorListener { error ->
Expand Down Expand Up @@ -305,6 +335,12 @@ class LoginActivity : AppCompatActivity(), LoaderCallbacks<Cursor> {
}

zis.close()
val f = File(path+zipname)
if(f.delete()) {
Log.d("ZIP", "deleted zip")
} else {
Log.d("ZIP", "failed to delete zip")
}
} catch (e: IOException) {
e.printStackTrace()
return false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import android.Manifest.permission.ACCESS_FINE_LOCATION
import android.content.Context
import android.content.Intent
import android.content.IntentSender
import android.content.SharedPreferences
import android.content.pm.PackageManager
import android.content.res.Resources
import android.graphics.Color
Expand All @@ -32,8 +31,8 @@ import com.beproject.group1.vta.R
import com.beproject.group1.vta.VTAApplication
import com.beproject.group1.vta.helpers.ETA
import com.beproject.group1.vta.helpers.Geofence
import com.beproject.group1.vta.helpers.SklearnPredictor
import com.beproject.group1.vta.helpers.TFPredictor
import com.beproject.group1.vta.helpers.WekaPredictor
import com.google.android.gms.common.api.ApiException
import com.google.android.gms.common.api.ResolvableApiException
import com.google.android.gms.common.api.Status
Expand All @@ -53,6 +52,8 @@ import com.google.maps.model.DirectionsResult
import com.google.maps.model.DirectionsRoute
import com.google.maps.model.GeocodingResult
import com.google.maps.model.TravelMode
import org.jetbrains.anko.doAsync
import org.jetbrains.anko.uiThread
import org.joda.time.DateTime
import java.io.IOException
import java.util.*
Expand Down Expand Up @@ -93,6 +94,8 @@ class MapsActivity : AppCompatActivity(), OnMapReadyCallback, SensorEventListene

private var timeBar: Snackbar? = null

private lateinit var sklearnPredictor: SklearnPredictor

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_maps)
Expand Down Expand Up @@ -173,6 +176,8 @@ class MapsActivity : AppCompatActivity(), OnMapReadyCallback, SensorEventListene
matrixI = FloatArray(9)
matrixValues = FloatArray(3)

sklearnPredictor = SklearnPredictor(this)

my_location.setOnClickListener({_ ->

if (mylocation != null) {
Expand Down Expand Up @@ -353,7 +358,7 @@ class MapsActivity : AppCompatActivity(), OnMapReadyCallback, SensorEventListene
initMarker()
}
Handler().postDelayed({
gmap.setPadding(0, map_bar_layout.height + 60, 0, 0)
gmap.setPadding(0,map_bar_layout.height + 60,0,logout.height+40)
}, 100)
}

Expand Down Expand Up @@ -399,8 +404,9 @@ class MapsActivity : AppCompatActivity(), OnMapReadyCallback, SensorEventListene
private fun addPolyline(results: DirectionsResult, mMap: GoogleMap) {

val c = Calendar.getInstance()
val tfPredictor = TFPredictor(this)
// val tfPredictor = TFPredictor(this)
// val wekaPredictor = WekaPredictor(this)

Log.d("Total routes", ""+results.routes.size)
for(i in 0 until route.size)
{
Expand All @@ -410,6 +416,7 @@ class MapsActivity : AppCompatActivity(), OnMapReadyCallback, SensorEventListene
}
route.clear()
val route_time = ArrayList<Double>()
val route_lengths = ArrayList<Double>()
val routeInFence = ArrayList<Boolean>()
for(i in 0 until results.routes.size) {
val decodedPath = PolyUtil.decode(results.routes[i].overviewPolyline.encodedPath)
Expand All @@ -423,60 +430,66 @@ class MapsActivity : AppCompatActivity(), OnMapReadyCallback, SensorEventListene
val t = ArrayList<Polyline>()
routeInFence.add(true)
var time: Double = 0.toDouble()

var dist = 0.toDouble()
for(j in 0 until decodedPath.size) {
c.time = Date()
c.add(Calendar.SECOND, time.toInt())
//mMap.addMarker(MarkerOptions().position(LatLng(decodedPath[i].latitude.toDouble(), decodedPath[i].longitude.toDouble())))
val traffic = tfPredictor.predict(
decodedPath[j].latitude.toFloat(),
decodedPath[j].longitude.toFloat(),
val traffic = sklearnPredictor.predict(
decodedPath[j].latitude,
decodedPath[j].longitude,
c.get(Calendar.DAY_OF_WEEK) - 1,
c.get(Calendar.HOUR_OF_DAY),
c.get(Calendar.MINUTE))
/*val traffic = wekaPredictor.predict(
decodedPath[j].latitude,
decodedPath[j].longitude,
(c.get(Calendar.DAY_OF_WEEK) - 1).toDouble(),
c.get(Calendar.HOUR_OF_DAY).toDouble(),
c.get(Calendar.MINUTE).toDouble())*/
/*val traffic = tfPredictor.predict(
decodedPath[j].latitude.toFloat(),
decodedPath[j].longitude.toFloat(),
c.get(Calendar.DAY_OF_WEEK) - 1,
c.get(Calendar.HOUR_OF_DAY),
c.get(Calendar.MINUTE))*/
when (j) {
0 -> {
val location0 = midPoint(decodedPath[j].latitude, decodedPath[j].longitude, decodedPath[j+1].latitude, decodedPath[j+1].longitude)
val location0 = midPoint(decodedPath[j].latitude, decodedPath[j].longitude, decodedPath[j + 1].latitude, decodedPath[j + 1].longitude)
val distance0 = ETA.distance(decodedPath[j].latitude, decodedPath[j].longitude, location0.latitude, location0.longitude)
val speed0 = ETA.speed(traffic!!.toInt())
//Log.d("Distance 0 : " ,"" + distance0)
time += distance0 / speed0
dist += distance0
t.add(addSegment(traffic, decodedPath[j], location0))
}
decodedPath.size-1 -> {
val location1 = midPoint(decodedPath[j].latitude, decodedPath[j].longitude, decodedPath[j-1].latitude, decodedPath[j-1].longitude)
decodedPath.size - 1 -> {
val location1 = midPoint(decodedPath[j].latitude, decodedPath[j].longitude, decodedPath[j - 1].latitude, decodedPath[j - 1].longitude)
val distance1 = ETA.distance(decodedPath[j].latitude, decodedPath[j].longitude, location1.latitude, location1.longitude)
val speed1 = ETA.speed(traffic!!.toInt())
//Log.d("Distance 1 : " ,"" + distance1)
time += distance1 / speed1
dist += distance1
t.add(addSegment(traffic, location1, decodedPath[j]))
}
else -> {
val location2 = midPoint(decodedPath[j].latitude, decodedPath[j].longitude, decodedPath[j-1].latitude, decodedPath[j-1].longitude)
val location2 = midPoint(decodedPath[j].latitude, decodedPath[j].longitude, decodedPath[j - 1].latitude, decodedPath[j - 1].longitude)
val distance2 = ETA.distance(decodedPath[j].latitude, decodedPath[j].longitude, location2.latitude, location2.longitude)
val speed2 = ETA.speed(traffic!!.toInt())
//Log.d("Distance 2 : " ,"" + distance2)
time += distance2 / speed2
dist += distance2
t.add(addSegment(traffic, location2, decodedPath[j]))

val location3 = midPoint(decodedPath[j].latitude, decodedPath[j].longitude, decodedPath[j+1].latitude, decodedPath[j+1].longitude)
val location3 = midPoint(decodedPath[j].latitude, decodedPath[j].longitude, decodedPath[j + 1].latitude, decodedPath[j + 1].longitude)
val distance3 = ETA.distance(decodedPath[j].latitude, decodedPath[j].longitude, location3.latitude, location3.longitude)
val speed3 = ETA.speed(traffic.toInt())
//Log.d("Distance 3 : " ,"" + distance3)
time += distance3 / speed3
dist += distance3
t.add(addSegment(traffic, decodedPath[j], location3))
}
}


}
route.add(t)
route_time.add(time)
route_lengths.add(dist)
Log.d("Estimated Time",""+ timeConversion((time).toInt()))
}
else {
Expand All @@ -487,7 +500,8 @@ class MapsActivity : AppCompatActivity(), OnMapReadyCallback, SensorEventListene
if(!route_time.isEmpty()) {
x = route_time.indexOf(Collections.min(route_time))
Log.d("Best Route", "" + x)
timeBar = Snackbar.make(root_view, timeConversion(Collections.min(route_time).toInt()),Snackbar.LENGTH_INDEFINITE)
val barMsg = "${timeConversion(Collections.min(route_time).toInt())} (${"%.2f".toString().format(route_lengths[x]/1000)} km)"
timeBar = Snackbar.make(root_view, barMsg, Snackbar.LENGTH_INDEFINITE)
timeBar!!.show()
}
for(j in 0 until route[x].size) {
Expand All @@ -498,14 +512,15 @@ class MapsActivity : AppCompatActivity(), OnMapReadyCallback, SensorEventListene
val decodedPath = PolyUtil.decode(results.routes[i].overviewPolyline.encodedPath)
val defaultPolylineOptions = PolylineOptions()
.color(ContextCompat.getColor(applicationContext, R.color.routeInactive))
.width(15f)
val t = ArrayList<Polyline>()
t.add(mMap.addPolyline(defaultPolylineOptions.addAll(decodedPath)))
route.add(t)
}
}

private fun addSegment(traffic: Long, source: LatLng, destination: LatLng): Polyline {
val polyLineOptions = PolylineOptions()
val polyLineOptions = PolylineOptions().width(15f)
when (traffic) {
0L -> {
polyLineOptions.add(LatLng(source.latitude, source.longitude)).color(ContextCompat.getColor(applicationContext, R.color.green))
Expand Down Expand Up @@ -536,7 +551,7 @@ class MapsActivity : AppCompatActivity(), OnMapReadyCallback, SensorEventListene
override fun onResult(result: DirectionsResult?) {
runOnUiThread {
addPolyline(result!!, gmap)
gmap.setPadding(0,map_bar_layout.height + 60,0,0)
gmap.setPadding(0,map_bar_layout.height + 60,0,logout.height+40)
positionCamera(result.routes[0], gmap)
}

Expand Down Expand Up @@ -568,7 +583,7 @@ class MapsActivity : AppCompatActivity(), OnMapReadyCallback, SensorEventListene
val minutes:Int = seconds / 60
seconds %= 60
return when(hours) {
0-> "$minutes mins"
0-> if(minutes <= 1) "2 min" else "$minutes mins"
1 -> "$hours hr $minutes mins"
else -> "$hours hrs $minutes mins"
}
Expand Down
Loading

0 comments on commit 21e8467

Please sign in to comment.