Compass module for AR view?

Want to create a module together?

This Titanium only code will display overlays depending on the direction you look at:

const win = Ti.UI.createWindow();
const viewAngleX = toRad(19);
const viewAngleY = toRad(29);

const K = 0.5;

var heading = 0;

const pw = Ti.Platform.displayCaps.platformWidth;
const ph = Ti.Platform.displayCaps.platformHeight;
const ldi = Ti.Platform.displayCaps.logicalDensityFactor;

Alloy.Globals.WIDTH = (OS_ANDROID) ? pw / ldi : pw;
Alloy.Globals.HEIGHT = (OS_ANDROID) ? ph / ldi : ph;

const displayCaps = Ti.Platform.displayCaps;
const centerX = Alloy.Globals.WIDTH / 2;
const centerY = Alloy.Globals.HEIGHT / 2;
var currLocation = {
	lat: 0,
	lng: 0,
	alt: 0
};
var currBearing = 0;
const overlay = Ti.UI.createView({
	width: Ti.UI.FILL,
	height: Ti.UI.FILL
});
const locations = [{
	name: 'munich',
	lat: 48.135124,
	lng: 11.581981,
	alt: 0
}];
const locLen = locations.length;

function toRad(x) {
	return x * Math.PI / 180;
}

function toDeg(x) {
	return ((x * 180 / Math.PI) + 360) % 360;
}

function FilterK(sens, oldVal, k) {
	return (sens * k) + (oldVal * (1 - k));
}

function Distance(point1, point2) {
	var R = 6371; // km

	var dLat = toRad(point2.lat - point1.lat);
	var dLon = toRad(point2.lng - point1.lng);
	var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
		Math.cos(toRad(point1.lat)) * Math.cos(toRad(point2.lat)) *
		Math.sin(dLon / 2) * Math.sin(dLon / 2);
	var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
	return R * c;
}


function Bearing(point1, point2) {
	var lat1 = point1.lat * Math.PI / 180;
	var lat2 = point2.lat * Math.PI / 180;
	var dlng = (point2.lng - point1.lng) * Math.PI / 180;

	var y = Math.sin(dlng) * Math.cos(lat2);
	var x = Math.cos(lat1) * Math.sin(lat2) -
		Math.sin(lat1) * Math.cos(lat2) * Math.cos(dlng);
	var brng = Math.atan2(y, x);
	return brng;
}



var locViews = [];

for (var i = 0; i < locations.length; i++) {
	locViews[i] = Ti.UI.createView({
		height: 80,
		width: 120,
	});

	var bg = Ti.UI.createView({
		height: 80,
		width: 120,
		backgroundColor: '#eee',
		borderRadius: 10,
		opacity: 0.7
	});
	locViews[i].add(bg);

	var message = Ti.UI.createLabel({
		text: locations[i].name,
		color: '#111',
		font: {
			fontSize: 12
		},
		textAlign: 'left',
		width: 'auto',
		height: 'auto'
	});
	locViews[i].add(message);
	overlay.add(locViews[i]);
}

function ComputeXDelta(relAngle) {
	var res = Math.sin(relAngle) / Math.sin(viewAngleX / 2);
	return res;
}

function VertAngle(loc) {
	return Math.atan2(loc.alt - currLocation.alt, Distance(currLocation, loc) * 1000);
}


function UpdateView() {

	for (var i = 0; i < locLen; ++i) {

		var horizAngle = Bearing(currLocation, locations[i]);
		var relAngleH = horizAngle - currBearing;

		if (toDeg(relAngleH) >= 90 && toDeg(relAngleH) <= 270) {
			continue;
		}

		var xDelta = ComputeXDelta(relAngleH);
		var viewCenterX = xDelta * centerX + centerX;
		var viewCenterY = centerY;
		var currView = locViews[i];

		currView.left = viewCenterX - currView.width * 0.5
	}

}



win.addEventListener("open", function() {
	Ti.Geolocation.requestLocationPermissions(Ti.Geolocation.AUTHORIZATION_WHEN_IN_USE, function(e) {
		if (e.success) {
			Ti.Media.showCamera({
				overlay: overlay,
				success: function(e) {}
			});

			Ti.Geolocation.accuracy = 3;
			Ti.Geolocation.headingTime = 100;
			Ti.Geolocation.headingFilter = 2;
			Ti.Geolocation.addEventListener('location', function(e) {
				if (e.coords) {
					currLocation.lng = e.coords.longitude;
					currLocation.lat = e.coords.latitude;
					currLocation.alt = e.coords.altitude;

				}
			});


			Ti.Geolocation.addEventListener('heading', function(e) {
				if (e.error) {
					return;
				}
				heading = FilterK(e.heading.magneticHeading, heading, K);
				currBearing = toRad(heading);

			});
		}
	});
	setInterval(function() {
		UpdateView();
	}, 100)
})

win.open();

It “works” but it’s slow. Code is old and got it from somewhere, so even there is room for improvement.

My idea is to draw the infos inside a module so we don’t have to get the coordinates and move stuff in Titanium but keep them in native land. That hopefully will be a lot smoother. Might even work in combination with TiGL.

I’ve started with the compass/location part at: GitHub - m1ga/ti.compass

But I can’t figure out how to match that to screen coodinates.

Idea:

  • call it with compass.init([{"lon":1,"lat":2,"title":"text"},{"lon":1,"lat":2,"title":"text"}];
  • it will add boxes with the title at the coordinates
  • it rotates the elements
  • add a camera view behind it

Some resources:

Perhaps someone has more math knowledge to transfer the JS code to Java :smiley: Feel free to add a PR or join the discussion here.

Interesting idea, I will give it a look this WE, do you plan to make concurrency to Pokemon GO ? :wink:

I want to add some AR texts (notes, infos) into my climbing app :slight_smile: So people can leave a virtual mark on outdoor climbing spots

Frankly the conversion from JS to Java is straightforward as math methods name’s are the same.

The code can nearly be copy/paste to java :slight_smile: just require to change the functions signatures and variables types.

Maybe we could create a repos to start with a blank new Module ?

Note that for real-time programming there are rooms for optimisations like using prée-computed variables rather than methods & division (that re-compute the same value again and again Math.PI / 180) :

function toRad(x) 
{
	return x * Math.PI / 180;
}

Would become :
double toRad = Math.PI / 180.0;

And used like this :
double radValue = degValue * toRad;

It avoid a an attribute access (PI), a function call & a division (the two last are pretty slow), this way is a lot faster and in any language.

There is a lot of others real-time optimisations that I will explain later.

Nice! I’ve clean-up the repo: ti.compass/TiCompassModule.java at main · m1ga/ti.compass · GitHub

it only has function to get the GPS location and sensor data. So the main part is in here

I suggest to add an example application, so testing & developping workflow will be faster & better IMHO ?

Also do you prefer that I fork the repos or can we work together on your repos directly ? (maybe a bit less tedious)

I’ve added the example file. I would prefer a fork since that makes it easier to work on the same project.

Forked and compiled, let’s start !

added some UI stuff:
Screenshot_20220508-194724

not ideal yet, will change.

Oh, and I’ve moved everything into the proxy.

When looking to this project, I have the feeling that TIGL have too much unnecessary folders, is there a clear explanation of modules folders structure ?

In the docs: Android Module Project | Titanium SDK

Wow, thanks, that make me even more confused :slight_smile: