Sunday, August 29, 2010

Which clock should I get?

A seriously geeky clock:



We need to get a new clock for the table across the room in the
bedroom. It would be best if it was readable at night without my
glasses (my vision isn't that bad, but a lighted display is essential)
and if it reset itself using radio broadcasts (refered to as a href="http://en.wikipedia.org/wiki/Radio_clock">radio-controlled
clock) as we have so many power outages. More features would be
nice (weather, AM/FM/Scanner, etc), but I don't want a cluttered
display. What to people recommend?

NIST has a list of manufactures of time and frequency receivers

I'd like to spend less than $100.

Thursday, August 12, 2010

NSFastEnumeration success?

I am definitely a beginner when it comes to Objective-C! Any help would be hugely appreciated.

This code works for me, but I really feel like it will certainly blow up on me in the future. For example, what if someone calls autorelease drain in the middle of a for loop. Also, what the heck is the difference between itemPtr and stackbuf? The documentation for NSFastEnumeration is really weak and my code is not behaving as described:
stackbuf
A C array of objects over which the sender is to iterate.
itemsPtr
A C array of objects

That's not very helpful. I'm using only itemsPtr and it works. What exactly am I supposed to do with stackbuf and how should I handle memory allocation/deallocation of stackbuf and itemsPtr??? I read this discussion on Implementing NSFastEnumeration and feel even less confident that I have any idea what is going on.

The code is online here: simple-fast-enum2.m. I know this is a lot of code, but hang in there with me.
001: #import <Foundation/Foundation.h>
002: #include <assert.h>
003:
004: @interface Datagram : NSObject
005: {
006: int dgId;
007: }
008: -(id)initWithDatagramType:(int)datagramType;
009: -(void)dealloc;
010: -(NSString *)description;
011: @property (readonly) int dgId;
012: @end
013:
014: @implementation Datagram
015: @synthesize dgId;
016: - (NSString *)description {
017: return [NSString stringWithFormat: @"Datagram: dgId:", dgId];
018: }
019:
020: -(id)initWithDatagramType:(int)datagramType {
021: self = [super init];
022: if (!self) return self;
023: dgId = datagramType;
024: return self;
025: }
026:
027: -(void)dealloc {
028: NSLog(@"dealloc datagram: %d",dgId);
029: [super dealloc];
030: }
031: @end
032:
033: // Pretend sequence of packet ID's coming from a sonar
034: int testSeq[] = {
035: 3, 12, 4, 19, 8,
036: 2, 2, 2, 2, 2, 2, 2, 2, 2, 9,
037: 2, 2, 2, 2, 9,
038: 2,2,2,2,9,
039: 1,2,3,4,5,6,7,8,9,
040: 11,12,13,14,15,16,17,18,19,
041: 3,
042: 0 // End of sequence / array sentinal
043: };
044:
045: @interface DatagramFile : NSObject <NSFastEnumeration>
046: {
047: // No ivars
048: }
049: -(id)init;
050: @end
051:
052: @implementation DatagramFile
053: -(id)init {
054: self = [super init];
055: if (!self) return self;
056: // NOP
057: return self;
058: }
059:
060: - (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id *)stackbuf count:(NSUInteger)len
061: {
062: NSLog(@"In countByEnumeratingWithState: stackbuf: %p, count: %d", stackbuf, len);
063: NSLog(@"\t state struct: state=%d %p %p", state->state, state->itemsPtr, state->mutationsPtr);
064: if (stackbuf) {
065: NSLog(@"***INSPECTING STACKBUF\n");
066: for(int i=0;i<1000 && stackbuf[i]!=0;i++) {
067: NSLog(@"Stackbuf %d: %p",i,stackbuf[i]); // What should I do with stackbuf[i]?
068: }
069: }
070: if (0 == state->state) {
071: NSLog(@"Initializing loop");
072: assert(0==state->itemsPtr);
073: state->itemsPtr = malloc(sizeof(id)*16);
074: memset(state->itemsPtr, 0, sizeof(id)*16);
075: } else if (0==len) {
076: // Will this get called if the call uses break inside the for loop?
077: NSLog(@"Finished loop. cleanup");
078: free(state->itemsPtr);
079: state->itemsPtr = 0;
080: return 0;
081: }
082: state->mutationsPtr = (unsigned long *)self; // Tell the caller that the file has not changed
083:
084: NSUInteger count=0;
085: for (; count < len && testSeq[state->state]!=0; count++, state->state++) {
086: NSLog(@"Creating datagram of type %d state: %d count %d",testSeq[state->state], state->state, count);
087: Datagram *dg = [[Datagram alloc] initWithDatagramType:testSeq[state->state]];
088: state->itemsPtr[count] = dg;
089: [dg autorelease];
090: }
091: NSLog(@"countByEnumeratingWithState read %d datagrams. state->state: %d",count, state->state);
092: return count;
093: }
094: @end // implementation DatagramFile
095:
096: int main (int argc, const char * argv[]) {
097: NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
098:
099: DatagramFile *df = [[DatagramFile alloc] init];
100: for (Datagram *dg in df) {
101: NSLog(@"About to read datagram in for");
102: NSLog(@" Datagram type: %d", [dg dgId]);
103: }
104:
105: NSLog(@"about to drain pool");
106: [pool drain];
107: NSLog(@"pool drained. ready for winter");
108: return 0;
109: }

Here is the output of the program that says that, at least in this case, it works.

2010-08-12 07:56:25.213 simple-fast-enum2[22266:a0f] In countByEnumeratingWithState: stackbuf: 0x7fff5fbfd930, count: 16
2010-08-12 07:56:25.215 simple-fast-enum2[22266:a0f] state struct: state=0 0x0 0x0
2010-08-12 07:56:25.216 simple-fast-enum2[22266:a0f] ***INSPECTING STACKBUF
2010-08-12 07:56:25.216 simple-fast-enum2[22266:a0f] Stackbuf 0: 0x7fff5fc005f8
2010-08-12 07:56:25.217 simple-fast-enum2[22266:a0f] Stackbuf 1: 0x7
2010-08-12 07:56:25.217 simple-fast-enum2[22266:a0f] Stackbuf 2: 0x7fff5fc3c028
2010-08-12 07:56:25.218 simple-fast-enum2[22266:a0f] Stackbuf 3: 0x7fff5fbfda40
2010-08-12 07:56:25.218 simple-fast-enum2[22266:a0f] Stackbuf 4: 0x7fff5fbfda00
2010-08-12 07:56:25.219 simple-fast-enum2[22266:a0f] Stackbuf 5: 0x7fff5fc016d2
2010-08-12 07:56:25.219 simple-fast-enum2[22266:a0f] Initializing loop
2010-08-12 07:56:25.220 simple-fast-enum2[22266:a0f] Creating datagram of type 3 state: 0 count 0
2010-08-12 07:56:25.220 simple-fast-enum2[22266:a0f] Creating datagram of type 12 state: 1 count 1
[snip - parsing data and adding it to itemPtr]
2010-08-12 07:56:25.227 simple-fast-enum2[22266:a0f] Creating datagram of type 9 state: 14 count 14
2010-08-12 07:56:25.227 simple-fast-enum2[22266:a0f] Creating datagram of type 2 state: 15 count 15
2010-08-12 07:56:25.228 simple-fast-enum2[22266:a0f] countByEnumeratingWithState read 16 datagrams. state->state: 16
2010-08-12 07:56:25.228 simple-fast-enum2[22266:a0f] About to read datagram in for
2010-08-12 07:56:25.229 simple-fast-enum2[22266:a0f] Datagram type: 3
[snip - inside for loop using datagrams]
2010-08-12 07:56:25.243 simple-fast-enum2[22266:a0f] About to read datagram in for
2010-08-12 07:56:25.244 simple-fast-enum2[22266:a0f] Datagram type: 2

[ snip - 16 blocks handled]

[ snip - 12 blocks handled ... finished the list of datagrams]

Last block...

2010-08-12 07:56:25.314 simple-fast-enum2[22266:a0f] In countByEnumeratingWithState: stackbuf: 0x7fff5fbfd930, count: 16
2010-08-12 07:56:25.314 simple-fast-enum2[22266:a0f] state struct: state=44 0x1001100a0 0x10010c760
2010-08-12 07:56:25.315 simple-fast-enum2[22266:a0f] ***INSPECTING STACKBUF
2010-08-12 07:56:25.315 simple-fast-enum2[22266:a0f] Stackbuf 0: 0x7fff5fc005f8
2010-08-12 07:56:25.316 simple-fast-enum2[22266:a0f] Stackbuf 1: 0x7
2010-08-12 07:56:25.316 simple-fast-enum2[22266:a0f] Stackbuf 2: 0x7fff5fc3c028
2010-08-12 07:56:25.317 simple-fast-enum2[22266:a0f] Stackbuf 3: 0x7fff5fbfda40
2010-08-12 07:56:25.317 simple-fast-enum2[22266:a0f] Stackbuf 4: 0x7fff5fbfda00
2010-08-12 07:56:25.318 simple-fast-enum2[22266:a0f] Stackbuf 5: 0x7fff5fc016d2
2010-08-12 07:56:25.318 simple-fast-enum2[22266:a0f] countByEnumeratingWithState read 0 datagrams. state->state: 44

2010-08-12 07:56:25.319 simple-fast-enum2[22266:a0f] about to drain pool
2010-08-12 07:56:25.319 simple-fast-enum2[22266:a0f] dealloc datagram: 3
2010-08-12 07:56:25.320 simple-fast-enum2[22266:a0f] dealloc datagram: 19
2010-08-12 07:56:25.320 simple-fast-enum2[22266:a0f] dealloc datagram: 18
2010-08-12 07:56:25.321 simple-fast-enum2[22266:a0f] dealloc datagram: 17
[ snip ]
2010-08-12 07:56:25.340 simple-fast-enum2[22266:a0f] dealloc datagram: 12
2010-08-12 07:56:25.341 simple-fast-enum2[22266:a0f] dealloc datagram: 3
2010-08-12 07:56:25.341 simple-fast-enum2[22266:a0f] pool drained. ready for winter

This shows that code runs all the way through and deallocs all of the datagrams when the pool was drained. I'm leaking my itemsPtr array as "Finished loop" never appears in the output. I need to test for the loops to build itemsPtr does not add any items and free itemPtr then.

So... help! Is this right? How do I make it better? What should I be doing with stackBuf? How do I not get in trouble with a break?

Wednesday, August 4, 2010

A cleaner way to have an NSMutableArray of counters?

How do I make this clean. I know how to make this really simple with a C array or a C++ vector, but I'm trying to learn ObjC! Any help greatly appreciated.

NSMutableArray *count_id = [NSMutableArray new];
// Can this be done better for an initialization?
for (int i; i < 256; i++) {
[count_id addObject:[NSNumber numberWithInt:0]];
}

NSData *data = [NSData dataWithContentsOfFile:fileName];

for (size_t dgStart = 0; dgStart < data.length; ) {
unsigned char id;
unsigned int size;
[data getBytes:&size range:NSMakeRange(dgStart, 4)];
[data getBytes:&id range:NSMakeRange(dgStart+5, 1)];

//
// Yuck! I just want to increment the number by 1. How do I improve this?
//
[count_id replaceObjectAtIndex:id withObject: [NSNumber numberWithInt:[[count_id objectAtIndex:id] integerValue]+1 ] ];

// Jump to the next packet
dgStart += size+4;
}

Tech and science podcasts?

I have been listening to a lot of FLOSS
podcasts
lately. What suggestions do you all have for great
podcasts for Mac, Linux, spatial stuff, and science pod casts?

Monday, July 5, 2010

More thoughts on sensor data in GeoRSS

We have started working with GeoRSS fields and my frustration with GeoRSS continues. I posted back in March asking for thoughts on GeoRSS: Sensor data in GeoRSS?. I got some helpful thoughts from Sean Gillies,
but have not heard from any others.

Here is an example of my USCGC Healy feed of science data that is only in HTML table form within the description:

Healy Science feed in Google Maps



It's got some really nice features that include:

  • Being pretty simple (when compared to SensorML and SOS)

  • You can just throw a URL in Google Maps and see the data

  • It works inside normal RSS readers (e.g. my USCGC Healy Feeds)

  • It's a simple file that you can copy from machine to machine or email.

  • It should be easy to parse

  • Points and lines work great


The trouble comes with:

  • Validation is a pain, but appears to be getting better

  • What should you put in the title and description?

  • It seams you have to create separate item tags for points and lines for things like ships

  • There is no standard for machine readable content other than the location


Here are my thoughts on the last point. First a typical entry that has info in the title and description:
<item>
<title>HOS IRON HORSE - 235072115: 0KTS @ 17 Jun 2010 16:07:10 GMT</title>
<description>Time: 17 Jun 2010 16:07:10 GMT Speed: 0</description>
<pubDate>17 Jun 2010 16:07:10 GMT</pubDate>
<georss:where>
<gml:Point>
<gml:pos>28.0287 -89.1005</gml:pos>
</gml:Point>
</georss:where>
</item>

This makes for easy human reading of data and works with GoogleMaps and OpenLayers.

This is how the AIS feed looks in Google Maps... mostly enough to see what is going on. If you know the name of a vessel, you can find it on the left side list of ships. That's a great start, but it is hard to take that info into a database. If the fields change at all in the title or description, all parsers that use that feed MUST be rewritten.



This buoy field shows the opposite idea of putting all the information into fields. It's also missing pubDate and such, but we should focus on the SeaSurfaceTemp and SampleDate. These are more machine readble. The XML and an image:
<item>
<title>SLDMB 43166</title>
<description>Most recent posrep from 43166</description>
<SeaSurfaceTemp>30C</SeaSurfaceTemp>
<SampleDate>2010-06-25 11:00:00.0Z</SampleDate>
<georss:where>
<gml:Point>
<gml:pos>27.241828, -84.663689</gml:pos>
</gml:Point>
</georss:where>
</item>




There are some problems in the sample above. First, the description doesn't contain a human readable version. This causes the GoogleMaps display to give us nothing more than the current position of this
"buoy" (and a recent track history that comes as a separate entry). Ouch. That's hard to preview. Second, the machine readable portion is fine, but I can't write anything that can discover additional data fields if they are added. If someone adds <foo>1234</foo>, is that field a part of something else or is it more sensor data that I should be tracking? A namespace for sensor data would help. Then I could pick off all of the fields that are in the "SimpleSensorData" namespace. But, I have to say that namespaces are good, but a pain. I would prefer a data block, where everything in there is a data field. It would also be good to separate units from the values. Here is how it might look:
<rss xmlns:georss="http://www.georss.org/georss" xmlns:gml="http://www.opengis.net/gml" version="2.0">
<channel>
<title>NOAA GeoRSS Feed</title>
<description>Vessel Tracks</description>

<item>
<title>HOS IRON HORSE - 235072115: 0KTS @ 17 Jun 2010 16:07:10 GMT</title>
<description>Time: 17 Jun 2010 16:07:10 GMT Speed: 17KTS
<a href="http://photos.marinetraffic.com/ais/shipdetails.aspx?MMSI=235072115">MarineTraffic entry for 235072115</a> <!-- or some other site to show vessel details -->
</description>
<updated>2010-06-17T16:07:10Z</updated>
<link href="http://gomex.erma.noaa.gov/erma.html#x=-89.1005&y=28.00287&z=11&layers=3930+497+3392"/>
<!-- Proposed new section -->
<data>
<mmsi>235072115</mmsi>
<name>HOS IRON HORSE</name>

<!-- Enermated lookup data types -->
<type_and_cargo value="244">INVALID</type_and_cargo>
<nav_status value="3">Restricted Maneuverability</nav_status>

<!-- Values with units -->
<cog units="deg true">287</cog>
<sog units="knots">0</sog>
<!-- Add more data fields here -->
</data>

<!-- The meat of GeoRSS -->
<georss:where>
<gml:Point>
<gml:pos>28.0287 -89.1005</gml:pos>
</gml:Point>
</georss:where>
</item>

<!-- more items -->
</channel>
</rss>

Perhaps it would be better inside of data to have each data item have a <DataItem> tag and inside have a name attribute.
<data_value name="sog" long_name="Speed Over Ground" units="knots">12.1</data_value>

Or we could just embed json within a data tag... but that would be mixing apples and oranges. If we start doing json, the entire response should be GeoJSON.

For referece, here is what one of those blue tails looks like in the GeoRSS:
<item>
<title>SLDMB 43166 Track</title>
<georss:where>
<gml:LineString>
<gml:posList>
27.241828 -84.663689
27.243782 -84.664666
27.245442 -84.66574
27.246978 -84.666779
27.248248 -84.668049
27.250104 -84.669318
27.251699 -84.670985
27.253158 -84.673045
27.254232 -84.6749
27.255209 -84.676561
27.256076 -84.678023
</gml:posList>
</gml:LineString>
</georss:where>
</item>

There was also an assertion that KML would be better. However, I would argue against KML as a primary data transport mechanism. KML is a presentation description, not a data encoding format. It's much like when I ask someone for an image and they take a perfectly good JPG, TIF, or PNG and put it in a PowerPoint... sending me only a PowerPoint. That can be useful, especially if there are annotations they want on a final, but I must have the original image or a lot is lost.

Looking at the KML, you can see that we have all the same problems with data being delivered by GeoRSS.
<Placemark>
<name>38681</name>
<description>Sample Date: 2010-07-02 18:00:00.0 Lat: 30.247965 Lon: -87.690424 SST: 35.8C</description>
<styleUrl>#msn_circle</styleUrl>
<Point>
<coordinates>-87.690424,30.247965,0</coordinates>
</Point>
</Placemark>




It's too bad that in Google Earth, you can't put a GeoRSS in a Network Link.

In case you are curious, wikipedia has an entry on SLDMBs: Self-Locating Datum Marker Buoy

Friday, June 11, 2010

Planning an AUV mission on the lake

The gavia is about to be driven across the lake to the test site.