Ajnaware’s Weblog

Web, Mobile & iPhone software development

Sun Seeker – How to use the new azimuth calibration feature

with one comment

I’ve just submitted an update to Sun Seeker for iOS – v4.3.

This update contains an experimental feature which addresses one of the most difficult aspects of using the device’s compass to obtain an accurate heading, when using the augmented reality 3D view to see the solar path. This article seeks to explain what this feature is about, and how best to use it.

Note that the Android version of Sun Seeker does not yet have this feature. I will be relying on feedback from iOS users before deciding whether to implement it in the Android version.

In the last major release (v4.2), I introduced the ability to toggle between Compass+Gyroscope mode and Gyroscope-only mode. This was already a big leap forward, because the gyroscope-only mode allows users to manually adjust the 3D View heading simply by dragging it manually.

SS_Blog2

SS_Blog1

The gyroscope-only mode allows you to set the heading manually, and the device then holds your setting relative to the gyroscope. Although there is likely to be a slow drifting of the gyroscope-only data, provided that you were able to set the heading accurately, this will work well for short periods of time – more than likely long enough to get all the information you need from the app.

Of course this all depends on you being able to set the heading accurately yourself. If the sun is out, then this is very easy – just line up the sun icon in the camera view with the actual position of the sun! Easy. :-)

But what if the sun isn’t out? Well this is where the new “Azimuth Finder” feature comes in. Tap on the settings (gear) icon in the 3D View, and you will see two new options at the bottom of the list of settings.

SS_Blog3

  • Show Reference Azimuth – If you have already selected a location, use this option to to toggle the display of an azimuth line corresponding to the selected location.
  • Set Reference Location – Tap this to open the “Azimuth Finder” view, and select a location or landmark within your line of sight, to use for your reference azimuth.

SS_Blog7

All you have to do in this view is to use the map to browse to a landmark or location that is visible from where you are now. It must be somewhere that you can identify when looking later through the 3D camera overlay view. When you have found a suitable location, just tap and hold to drop a marker. The app will use geocoding to assign a name or address to the location, and calculate it’s azimuth from the current device location.

In this particular example, I am (just) able to see the top of the Sydney Harbour Bridge from here, despite the rain and low cloud, so that makes a good landmark to use.

Then, as soon as you tap “Done“, you are returned to the 3D View, and there is now a new line showing the azimuth of the selected location. Note that you will only see this line if you are already looking in approximately the right direction! Otherwise you may need to pan around until you bring it into view.

SS_Blog6

You may be able to make out the Sydney Harbour Bridge in this screenshot – just to the right of the chimney, directly below the centre cursor.

As this 3D View is already in gyroscope-only mode, all I needed to do next was to manually drag the white azimuth line to the actual location of the bridge – in this case four degrees to the right. And, voila, we now have a very well-calibrated heading!

Note that if you leave this for a while it may drift off again little by little, due to gyroscope drift. In that case, simply repeat the same calibration procedure.

Once you’ve selected a particular landmark for calibration, it is remembered (and the heading automatically adjusts itself if you change location yourself), so you can just switch the reference azimuth line on or off via the settings icon. And at any time you can choose a different reference location too, as you will obviously need to do if you move to a new location from which the original landmark is not visible.

Written by ajnaware

Tuesday, 19 August 2014 at 11:09 am

Oz Weather Plus – Why I’m releasing it as a new app

with one comment

The Oz Weather iPhone app was first released on 20th Nov 2008 – yes that’s more than 5 years ago!!! By all accounts, it’s been a highly successful app. Notably, in January 2009, it reached #1 ranking for paid apps in the Australian app store and stayed there for about 10 days, during the period of an intense heatwave, and deadly bush-fires. And over the entire 5 year period, the app has been installed onto hundreds of thousands of devices.

There have also been more than 30 free app updates released during that period, and also an attempt to use in-app purchase to provide new, advanced features, which were much appreciated by a number of users. This also attracted a lot of very negative and vocal feedback from users who thought they should be getting it all for free, and as a result I eventually re-integrated those features into the app and removed the in-app purchase. But the damage was done, and with a competitor who crowed loudly that their own app’s updates would be free forever (they’ve since reneged of course), Oz Weather lost its lead in the app store to them.

And here’s how Oz Weather sales have gone, over the last few years…

Sales_2010_2013

So as you see, despite the many app updates (seen as comments bubbles in the above graphic) new sales have trailed off considerably. There are a number of reasons for this. The biggest one is that competition has increased a lot over the years. In fact it seems that my own openness in posting my app’s sales figures during those early years probably encouraged quite a few other developers to try their hand at it. And then there were the bigger players in the Australian weather field, such as “WeatherZone” and “Elders Weather”, who had just been slow to get into the app store, and eventually figured out how to make their apps more appealing. Some of those competitors innovated with new types of features that I didn’t think would be as appealing to users as they actually turned out to be. More recently still, it seems to have become something of a trend amongst app developers to use weather apps as a kind of test playground for new app design paradigms. And there have indeed been some really nicely-designed weather apps coming out, especially with iOS7 style interfaces.

And it is indeed the iOS7 operating system update that finally prompted me to consider starting afresh. And with this impetus, suddenly there was a surge of new enthusiasm to create several innovative new features, some of which had been floating around in the back of my head for years, but not seen the light of day due to lack of motivation stemming from the various issues described above.

The big issue was, of course, whether or not this could or should be offered as a (necessarily free) update to the existing Oz Weather app, as opposed to creating a brand new app. I’m sure readers of this post will be well aware of the many precedents for creating new apps as opposed to providing free updates – the first big one of which was Tweetie – and they got some really bad reactions, although over time there has been greater and greater acceptance that this is pretty much a necessary way to go in order for app developers to survive, in particular given the shortcomings of in-app purchases, and the fact that they simply aren’t workable in many types of non-game category apps.

A key metric to consider in my own case is that I’ve spent around 1000hrs building the new app and its associated server code. Even if I were to value my time with only a modest hourly rate, at the current rate of app sales, it would take much more than a year of ongoing income, in fact maybe several years, to pay for the time I’ve invested in it. Obviously that would not be a sustainable way to work or run a business.

Also, many of the existing Oz Weather users bought the app more than 3 years ago – most of them paid around $2.49 for it, although it’s since gone down to $1.99 due to Apple changed pricing tiers, combined with ongoing downward price pressure from the competitors. Further, many users do continue to use the app on a daily basis – so it would be hard for them to argue that they haven’t got good value for money.

Then, of course there are those users – a much smaller number – who bought the app more recently – and it will probably feel less fair to them not to be getting a free upgrade. However, I am not intending to stop providing data feeds to the existing app, at least for the foreseeable future. (I don’t want to make any rash promises that I might not be able to honour – it might be necessary to drop the feed at some point down the line.) So those users will continue to have a fully-featured, working app – the same features that were advertised to them in the app store, and which they paid for. I do know it will suck a little bit more for those who bought it only really recently. So if you really feel that badly about paying for the upgrade, and are financially stressed by it, what the hell, why not send me an email, via the app’s About / Email us button, and if you really make a good case, I’ll see if I can help out.

There it is – that is why I’m releasing the new version of Oz Weather as a new app. For better or for worse. So may god help me. Amen. ;-)

Written by ajnaware

Wednesday, 20 November 2013 at 4:56 pm

Sun Seeker Sizzles!

leave a comment »

The Sun Seeker app has continued to be enhanced and honed in a series of updates, the most recent being v2.8, which includes a modernised interface – yep, those are indeed flat button faces. ;-)

Sun Seeker v2.8 compass screen

Sun Seeker v2.8 Compass Screen

These updates seem to have attracted a bit of positive attention resulting in several new blog reviews, culminating in the following fabulous review from top-notch reviewer John Martellaro (@jmartellaro) of The Mac Observer. This is a must-read review, not just because it is positively glowing, but also because John saw fit to include my detailed answers to his probing questions, including some inside information on how the app works, and especially importantly on how to ensure optimum compass calibration of your device.

Just to show a little more of the app here, my own favorite feature update is the ability to select date and time on the map view via a scroller.

Sun Seeker Map View

 

Written by ajnaware

Thursday, 4 April 2013 at 4:17 pm

Sun Seeker for Android!

with 6 comments

After a long development period I’m delighted to announce that Sun Seeker is now finally available for Android devices!

Click on this logo to see it in the Android Marketplace.

Available in Android Market


Is is real or is it Memorex? (You have to be of a certain age to remember that advertising slogan!)

Yes – it looks just like the iPhone version in most ways, and includes all the same features as the latest iPhone version.

I’m especially interested to see how sales go, and find out just how different the app sales may be between the two devices. Of course Sun Seeker on iPhone is well established, and it may take a while for the Android version to find its momentum. We’ll see!

Written by ajnaware

Thursday, 1 March 2012 at 4:07 pm

Posted in Uncategorized

Sun Seeker Test Shots

with one comment

Here are a couple of images from Sun Seeker put together (unsolicited) by a generous and enthusiastic New York based photographer/cinematographer – Hal Hansen.

He’s currently revamping his website and I’ll provide a link to it here when it’s ready. Thanks Hal!

I love the way he’s featured an iconic yellow cab which is a New York signature. Did anyone notice that it’s not actually the same cab in each shot? That’s clever photography! ;-)

Written by ajnaware

Thursday, 24 March 2011 at 3:20 pm

Posted in iPad, iPhone, Software & Hardware

Tagged with

Sun Seeker Update v1.5

with 5 comments

As part of a series of planned updates for the Sun Seeker augmented reality iPhone app, the latest update v1.5 has just been approved by Apple.

For a video demo of Sun Seeker see this earlier blog post.

The main changes for v1.5 are:

  • Enhanced performance for smoother compass dial rotation
  • Added new table of annual rise and set times
  • Added new table of sun’s daily azimuth and elevation
  • Added tap action to rise/set label to see local times instead of intervals
  • Better handling of disabled Location Services
  • More efficient use of GPS – now only used briefly on startup
  • Fixed some minor bugs and issues with date changes

[Note - v1.5.1 update has been submitted to fix OS3.0 backward compatibility and missing sunset times for some locations west of GMT.]

Following is a more detailed description of some of these items.

1. Enhanced Compass Dial Rotation

The compass dial in Sun Seeker includes text which retains its orientation relative to the device regardless of the compass rotation, and this means that at least part of the image needs to be re-rendered for each incremental rotation of that dial as the compass rotates. Previously the whole image was being redrawn each time, and that performance hit meant that the dial motion was quite jerky when it needed to make large rotational changes. The new implementation involves much less redrawing, and hence allows the compass to be much more responsive.

2. New Tables

The table of rise and set times spans the entire year, and hence allows you to look up rise and set times for any given date.

The table of the solar path lists the sun’s azimuth and elevation at 15 minutes intervals throughout the currently selected day.

3. Tap action to see rise/set time instead of intervals

This was added simply for clarity. Tapping on the rise/set labels on the compass screen toggles the display between showing the rise and set time in local time versus showing time duration between now and the rise and set times.

4. Better handling of Location Services status

A problem to date has been if the user has switched off the device Location Services or (perhaps accidentally) disabled them for this particular app. In these cases the app can only use its last acquired location data, and in this case the app shows data which is correct for that old location, but incorrect for the user’s current location.

This issue has been the biggest generator of email support requests to date, but I now expect that this will lessen considerably, because I have implemented clear warning messages which pop-up whenever location services are disabled, each time that the app starts up or resumes from background.

5. More efficient use of GPS

Previous versions of the app left GPS on continuously while the app was active (although off when inactive or in background), and this presented the app with ongoing positional updates while it was open. But for the sake of efficient use of GPS, it seemed unnecessary to leave it on once the location had been determined to a reasonable accuracy, so GPS is now only on as long as location has not been found to reasonable accuracy. However an important point here is that the app should re-query its location not only every time it starts up, but also whenever it resumes from background. The reason for this of course is that the device may have changed location while it was in background – for example it may resume from background after the user has traveled somewhere by air!

6. Future Updates

By far the most common request from users has been to allow selection of other cities/locations rather than just the current current, and this is the next major feature planned. But please note that it is not a trivial update! A particular difficulty here is in ensuring that the local times reported for other locations respect the correct timezones and daylight savings rules for those locations throughout the year. However, I do have a solution planned, and hope to be able to do this within a reasonable timeframe.

The next most common request has been for an Android version. Due to the particularly technical nature of the app, and the fact that I personally have no grounding in Android development, this is a much more difficult proposition. However I have been looking to outsource it. I apologise to those who have been waiting impatiently, and I can assure you that these plans are progressing.

In the meantime, I hope you continue to enjoy the app!

Written by ajnaware

Saturday, 19 March 2011 at 12:18 pm

Dynamically adding UIActionSheet buttons

with 6 comments

Every once in a while I come across a seemingly simple iPhone coding requirement, but Apple documentation just doesn’t seem to give enough pointers, and nor does web search throw up anything useful. It may just be my inability to find the right keywords to search for, but it might also be that no-one else has posted anything about it. So here is just one such thing in case it proves helpful to anyone.

The UIActionSheet is a very useful class, and I use it frequently in my apps, but its initialisation method doesn’t allow you to add buttons from an array. Instead you apparently typically just add them hardcoded as an initialiser parameter  – and almost all code examples on the web seem to use this method.

Standard example – hardcoded buttons:

- (void)testActionSheetStatic {
	// Create the sheet with buttons hardcoded in initialiser
	UIActionSheet *sheet = [[UIActionSheet alloc] 
		initWithTitle:@"Static UIActionSheet"
		delegate:self
		cancelButtonTitle:@"Cancel"
		destructiveButtonTitle:nil
		otherButtonTitles:@"Item A", @"Item B", @"Item C", nil];

	[sheet showFromRect:view.bounds inView:view animated:YES];
	[sheet release];
}

So that is all well and good if the option buttons are known in advance and never change. But what if I need to change them at runtime? It seems easy enough to add buttons dynamically instead, by leaving out those button declarations from the initialiser, and adding them afterwards instead, and the following code shows how you might assume this should be done.

Dynamically added buttons (first attempt):

- (void)testActionSheetDynamic {
	// Create the sheet with only cancel button
	UIActionSheet *sheet = [[UIActionSheet alloc] 
		initWithTitle:@"Dynamic UIActionSheet"
		delegate:self
		cancelButtonTitle:@"Cancel"
		destructiveButtonTitle:nil
		otherButtonTitles:nil];

	// Add buttons one by one (e.g. in a loop from array etc...)
	[sheet addButtonWithTitle:@"Item A"];
	[sheet addButtonWithTitle:@"Item B"];
	[sheet addButtonWithTitle:@"Item C"];

	[sheet showFromRect:view.bounds inView:view animated:YES];
	[sheet release];
}

The problem with this becomes apparent when you run it – the cancel button appears at the TOP of the sheet, whereas standard practice seems to be that it should be at the bottom. How to achieve this? I didn’t manage to find a way of doing this while adding the cancel button in the initialiser. Instead I eventually found a way of doing so by adding it also as a dynamic button.

Dynamically added buttons (also with dynamic cancel button):

- (void)testActionSheetDynamic {
	// Create the sheet without buttons
	UIActionSheet *sheet = [[UIActionSheet alloc] 
		initWithTitle:@"Dynamic UIActionSheet"
		delegate:self
		cancelButtonTitle:nil
		destructiveButtonTitle:nil
		otherButtonTitles:nil];

	// Add buttons one by one (e.g. in a loop from array etc...)
	[sheet addButtonWithTitle:@"Item A"];
	[sheet addButtonWithTitle:@"Item B"];
	[sheet addButtonWithTitle:@"Item C"];

	// Also add a cancel button
	[sheet addButtonWithTitle:@"Cancel"];
	// Set cancel button index to the one we just added so that we know which one it is in delegate call
	// NB - This also causes this button to be shown with a black background
	sheet.cancelButtonIndex = sheet.numberOfButtons-1;

	[sheet showFromRect:view.bounds inView:view animated:YES];
	[sheet release];
}

In this case the cancel button appears at the bottom, and all works as expected.

The main remaining question I had was what on earth the destructive button was (also apparently not explained in Apple documentation). Some experimentation seemed to show that it was effectively identical to a cancel button with the exception that it had RED background instead of a black one. So if you change the last example to set the destructiveButtonIndex instead of the cancelButtonIndex, then the only difference is that the button labelled “Cancel” would have a red background.

For completeness and sanity, this is the delegate code that goes with all of the above examples.

- (void)actionSheet:(UIActionSheet *)actionSheet 
		clickedButtonAtIndex:(NSInteger)buttonIndex {
	if (buttonIndex == actionSheet.cancelButtonIndex) { return; }
	switch (buttonIndex) {
		case 0:
		{
			NSLog(@"Item A Selected");
			break;
		}
		case 1:
		{
			NSLog(@"Item B Selected");
			break;
		}
		case 2:
		{
			NSLog(@"Item C Selected");
			break;
		}
	}
}

Written by ajnaware

Saturday, 26 February 2011 at 9:21 am

Follow

Get every new post delivered to your Inbox.

Join 775 other followers