Tag Archives: Mobile

Am I Near Public Art? How about Crime?

26 Feb

When you are new to a city, it is hard to walk around and carry a map of all the sites. Wouldn’t it be nice if your phone could alert you when you were near something of interest? In this post, I will show you how to create an alert system.

The Application

The application will build off of our earlier post using Albuquerque Crime Data. In that application, the user clicked the map and was presented with all crimes in the last 180 days within a half mile of the click.

This application will use the same logic but replace the click with the users location.

Building the Application

We will start with a Leaflet.js Mobile map. Place the following HTML in the head of your document.

<meta name=”viewport” content=”width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no” />

<style>
body {
padding: 0;
margin: 0;
}
html, body, #map {
height: 100%;
}
</style>

This will make the map look nice on mobile – and desktop as well. Then create the map.

var map = L.map(‘map’);

L.tileLayer(‘http://{s}.tile.osm.org/{z}/{x}/{y}.png’).addTo(map);

map.locate({setView: true, maxZoom: 16,enableHighAccuracy:true,watch:true});

With mobile maps, we do not pass the setView to the map, we add that parameter to the locate() function. Now we need two functions: one for found and one for not found.

map.on(‘locationfound’, gotcha);

function gotcha(e){ALL OUR CODE GOES HERE}

map.on(‘locationerror’, onLocationError);

function onLocationError(e) {
alert(e.message);}

When our location is found, we want to setup the buffer and prep for calling the Albuquerque Data for Public Art or Incidents.

a=L.marker(e.latlng);
b=a.toGeoJSON();
L.circle(e.latlng, 20).addTo(map);
buffered = turf.buffer(b,.05,”miles”);
var result = turf.featurecollection(buffered.features.concat(b));
g='{“rings”:’+JSON.stringify(buffered.features[0].geometry.coordinates)+’}’;

We create a marker, convert it to GeoJSON to use with Turf.js, then buffer and get the rings to use in the query.

Now we can make our standard AJAX call to an ESRI REST Endpoint. I have commented out the URL for Public Art and the marker. You can uncomment them and comment out the incident url and marker to switch the application.

var params=”f=json&outSR=4326&outFields=*&geometryType=esriGeometryPolygon&spatialRel=esriSpatialRelIntersects&inSR=4326&geometry=”+g;

//var url = “http://coagisweb.cabq.gov/arcgis/rest/services/public/PublicArt/MapServer/0/query&#8221;;
var url = “http://coagisweb.cabq.gov/arcgis/rest/services/public/APD_Incidents/MapServer/0/query&#8221;;
http=new XMLHttpRequest();
http.open(“POST”, url, true);
http.setRequestHeader(“Content-type”, “application/x-www-form-urlencoded”);
http.onreadystatechange = function() {//Call a function when the state changes.
if(http.readyState == 4 && http.status == 200) {
var result= JSON.parse(http.responseText);
…….CODE GOES HERE……..

}}
http.send(params);

Now we get back all the incidents, or art, within 300 feet (.05 miles) of our location. We need to take the results and add them to the map and notify the user they are near something of interest.

for(x=0;x<Object.keys(result.features).length;x++){
xy=result.features[x].geometry;
pattern.push(100);
pattern.push(100);
L.marker([result.features[x].geometry.y,result.features[x].geometry.x]).bindPopup(“<h3>”+result.features[x].attributes.CVINC_TYPE+”</h3>”).addTo(map);}
//L.marker([result.features[x].geometry.y,result.features[x].geometry.x]).bindPopup(“<h3>”+result.features[x].attributes.TITLE+”</h3>”).addTo(map);}

navigator.vibrate(pattern);
pattern=[];

As we move, the service is queried again, constantly watching us and letting us know when we are near something of interest. The vibration pattern is 100ms for each feature we are near and pause for 100ms between each feature. If we are near a lot of features -say crime incidents – our phone will vibrate many times. Possibly signaling a dangerous part of town. If we are using public art, we know we are near a particularly artistic part of the city and maybe we should explore more.

To use the same map for multiple features, you could switch up the vibration patterns, say short fast vibrations for art and longer for crime. Maybe vibrate once for crime but the duration is a function of the number of incidents – 10 incidents results in a 10 second vibration.

Just an idea on how to use open data to alert new comers to the features of the city that they may not be aware of.

Advertisements

A Street Bump Knockoff: Mobile Phone Acceleration

21 Jan

Some time ago, I read about an app that uses your phone to detect speed bumps. It sounded cool, but I didn’t give it much thought. Recently, I was asked a question about the app and took a harder look at it. The app is call Street Bump and is produced by the City of Boston. The app won a Best of the Web Government Achievement award in 2013 for the Government to Citizen category. The first thing that came to mind when reading about the app was could I build it. This article will walk you through how I built a very simple version of the Street Bump app.

My best guess was that the app used the z coordinate of the mobile device. I started reading about the HTML5 APIs that would be needed. As I read, I found that there is a DeviceMotion event that has an acceleration attribute. This is what I will use. Let’s think about it. You are driving down a road and the phone will move up and down. Hitting a pothole, your phone should change elevation quickly. The elevation change, however, will be minimal. Acceleration should be the right choice.

The Final App. A Chart Streaming Data and a Map With Pothole Locations

The Final App. A Chart Streaming Data and a Map With Pothole Locations

The first thing I wanted to do was read out the acceleration values.

window.addEventListener(“devicemotion”,function(e){
console.log(e.acceleration.z);},true);

Now I can see a bunch of numbers in the console. I want the mobile phone user to be able to see them too – there is no console on your phone. I decided to use Smoothie Charts to stream the data to the webpage.

The second part of the app is that the coordinates are sent to a server. To accomplish this, I used Leaflet.js map.locate(). It is just a wrapper around the HTML5 Geolocation API, but it lets me draw a map at the same time using a single API.

The final code

  1. Creates a map and a line for the chart.
  2. It draws a blank map, sets up the location events and functions and initializes the chart.
  3. The action occurs in the devicemotion event listener. When the event is fired, the code adds a time stamp and the z value to the chart and calls map.locate() to get the coordinates and draw a point.

Here is the full JavaScript for the app.

var raw=[];
var map = L.map(‘map’);
var line1 = new TimeSeries();

window.addEventListener(“devicemotion”,function(e){
line1.append(new Date().getTime(), e.acceleration.z);
console.log(e.acceleration.z);
raw.push(e.acceleration.z);
document.getElementById(“rawdata”).innerHTML=raw.join(“,”);
if(e.acceleration.z>3|e.acceleration.z<-3)
{map.locate({setView: true, maxZoom: 16});}},true);

var smoothie = new SmoothieChart({millisPerPixel:70,maxValueScale:0.82,grid:{fillStyle:’rgba(192,192,192,0.15)’,verticalSections:5},labels:{disabled:true,fillStyle:’#000000′,fontSize:12,precision:0},timestampFormatter:SmoothieChart.timeFormatter,maxValue:10,minValue:-10});
smoothie.addTimeSeries(line1, { lineWidth:5,strokeStyle:’#000000′});
smoothie.streamTo(document.getElementById(“mycanvas”), 1000);

function onLocationFound(e) {
L.tileLayer(‘http://{s}.tile.osm.org/{z}/{x}/{y}.png’).addTo(map);
L.marker(e.latlng).addTo(map);}

map.on(‘locationfound’, onLocationFound);

You can play with the if statement to change the values making the app more or less sensitive. The Street Bump algorithm is far more advanced than our simple if > 3 or < -3. Also, the Street Bump app sends the data to a server. If three people mark a pothole at the same location, the city will respond. Sending the data to a server would require an AJAX call or better yet, use WebSockets with a Node.js Server.

Ideally, the app is just a data collector sending a stream of acceleration values with (lat,long) for each to a database. The second part of the app is a program that analyzes the data finding multiple values that would signal a pothole. The more data collected, the smarter the app should become. For example, if a single line segment is recorded multiple times, the app should be able to average the values to account for different vehicle speeds, suspensions, etc. This can be feed back to the algorithm to make it smarter.

Albuquerque Public Art: A Mobile Leaflet.js Example

5 Dec
Mobile Leaflet Map with Geolocation, Clusters, and Icons.

Mobile Leaflet Map with Geolocation, Clusters, and Icons.

I was looking at the Albuquerque OpenData – it’s all in KML – and decided to make a mobile map using the public art file. The first thing I did was write a Python script to get the Long, Lat and URL of the image out as text. I renamed the KML to XML and imported it in to Excel. From there I deleted out several columns and stripped some information out by hand. Then I ran this script to get my JavaScript:

from xlrd import open_workbook
wb=open_workbook(‘PublicArt.xls’)
sheet=wb.sheet_by_index(0)
f=open(‘temp.txt’,’w+’)

for rownum in range(sheet.nrows):
a=”[“+str(sheet.cell_value(rownum,2))+” , “+str(sheet.cell_value(rownum,1))+” , “+'”<img src=’+”‘”+str(sheet.cell_value(rownum,3))+”‘”+’>”‘+”],\n”
f.write(a)

f.close()

I wrote my Leaflet map and put the output in as my markers. Then I made a new PNG using the Albuquerque Vase Logo. Lastly, I grabbed the LocateControl. View the live example.

If you view this page on an iPhone, it will ask for your current location. You can also click the location circle in the top left of the map – under the zoom controls.  Doesnt appear to work on Droid – but only tested on 1 device.

Just grab the code from the example by going to ‘page source’ in your browser – ctrl-u in Firefox.

If you do not have location enabled, you can go to this map.

Fulcrum Mobile Data Collection

2 Apr

I recently posted on Mapping a Graveyard with Field Assets App. In this post, I am going to show how I collect GIS data in the field using my iPhone and the free Fulcrum App.

I created a free account on the Fulcrum website. After creating the account I started a new project and created a form.

Use the tools available on the left to create any type of form. Load the form in to your project and it’s ready to use.

 

Now I have a project and a form to capture my field data.

Using TileMill – a tool for creating maps and exporting as mbtiles – I added some data – Census Blocks for Albuquerque – and exported the map as a mbtile.

Next, upload the map to Fulcrum.

With the map loaded, you now have a project,  a form, and a map – so let’s get started.

 

Open up the iPhone App and select your project. You will see your project and current location in a basemap.

Click the maps button on the bottom of the screen, you will see which basemap you are using and an option to upload your own. Upload your own and select your mbtile map.

My tile is not the best, I just loaded up a very small file with almost no zoom. You should, and can, do much better.

Now that I have my Census Blocks in an mbtile, I can collect data using my own basemap. What I like even more than having my own basemap is that I can download it and use it without having internet access.

now you can add a data point.

 

 

 

 

 

And, see the accuracy of the point by swiping the top of the screen.

I have been told that you will be able to manually place points – instead of using current location – in future updates of the App.

What I like about this App is the ability to customize my data collection forms with ease, add my own basemaps, and use my maps offline. Also, with the free version I can export my data as CSV and KML – without photos.

Yes, Spatial Networks sells a monthly service with this app. for $9 a month you get 20 forms for a single user and CSV and KML export with photos. For $20 a month you get unlimited forms and users and you can export to CSV, KML, SHP, and GeoJSON. — all with photos.

There are an increasing number of GIS services becoming available online but I am sticking to the ones that allow me to export my data out in the formats I need. Fulcrum lets you export out as GeoJson – I think this is cool for being able to incorporate my data in to my Leaflet.js maps and other applications I build myself.If you use JavaScript, then JSON is an easy way to transfer data.