SignalK / specification

Signal K is a JSON-based format for storing and sharing marine data from different sources (e.g. nmea 0183, 2000, seatalk, etc)
Other
91 stars 68 forks source link

Add vessel.type, and update spec to better support data obtained from AIS. #171

Open faceless2 opened 8 years ago

faceless2 commented 8 years ago

There is currently no space in the specification for a few bits of (potentially) important information which will be obtained from other vessels over AIS. Here's a list with suggested modifications to the spec to accomodate them. $vessel means any map under "vessels".

  1. AIS type 5 (vessel static information) includes a "destination" field. This doesn't quite map to our "$vessel.navigation.destination" field, which has no space for a human-readable name, just a waypoint UUID. Suggest the addition of "$vessel.navigation.destination.name".
  2. AIS type 5 again specifies four dimensions - distance from bow, stern, port and starboard to the position reported by the GPS. This is useful information - imagine you are trying to pass behind a 300m long supertanker in fog. We already have "$vessel.details.length" and "$vessel.details.beam" - I suggest we keep these but add optional fields "$vessel.details.bowOffset" and "$vessel.details.portOffset".
  3. AIS class is useful - it gives us some information on the data that's going to be reported and the frequency of the reports (positions ever 30s for Class B, or every 10s for Class A) so we know if the data is still valid. Suggest adding a "$vessel.communication.ais.class" field which is "A" or "B" (or see last paragraph below for an alternative).
  4. There is no way to record broad "type" of vessel in the current spec. I'd argue this is useful information in general for our own vessels, but more so for others we see over AIS.

Specifically, the broad category of the AIS transmitter can be derived from the MMSI: for example any MMSI beginning with 970 is a search-and-rescue transmitter. We can also obtain more detailed vessel type information from AIS type 5 messages, which specifies one of about 100 codes including passenger vessel, hovercraft, "Tanker, Hazardous category A" (whatever that is) etc.

I would suggest using two fields for this data: "$vessel.type", which is an enum that includes at least the following values:

sart
mob
epirb
fixed
aircraft
ship (default if not specified)

While this is directly derivable from the MMSI, the sart (search-and-rescue transponder), mob (man-overboard) and EPIRB are things that you want clearly marked on your moving map, so I'd argue there's value in making this information explicitly available to a consumer. "fixed", "aircraft" and "ship" are also derivable from the MMSI prefix (ship being everything that's not one of the others, so we can make that a default if the value is missing). These values are enough to choose an icon to represent the AIS station on a map.

Second field I'd suggest is "$vessel.subtype" which is a free-form text field. This can store the detail from the AIS type 5 message for other ships, and of course being free-text you can do what you like for your own vessel (e.g. "gin palace").

Finally one variation on the above ideas is to remove "vessel.communication.ais.class" and merge it into the above - e.g. if it's a class B transponder, set $vessel.type to "small ship". The advantage is it's one less field.

rob42 commented 7 years ago

@webmasterkai I agree trees are complex, and we have discussed before the limits of them. Remember the tree is just an organizational representation, a way to categorize messages. Its very useful when you want to filter out information from the whole, and for applying security rules etc. I think of it like a filesystem, and the goal is to make it 'predictably organised', not a perfect mirror of real life. eg try getting just sog from several vessels using NMEA messages, you have to filter misc vars from a variety of sentences, a real mess.

In signalk its just a subscription to vessels.*.navigation.speedOverGround, and I can secure access by any subpath of the key. The power is in a predictable structure, not a perfect structure.

So we can just place amphibious vehicles in either vessels or vehicles, even though its not always strictly true. It still gives us the certainty where we can find that type of object. Likewise RV can go into vehicles, your cabin into shore. There is no reason they cant have position.*, although navigation for the cabin would be a bit weird!

For the cabin with weather and solar etc, the shore entities can simply inherit the existing environment and electrical schemas, or at least the relevant parts. Again, its not about accurate object modelling, just about predictable organisation.

BTW I do wish we had named vessels more generically, but its a bit late now :-(

webmasterkai commented 7 years ago

@rob42 I think vessels and shore are logical root keys on a secondary index that a consumer uses to maintain a list of uuids.

Perhaps I want to subscribe to everything within a geofence surrounding me, I'd likely create a nearby index that finds anything with gps coords near me and put uuid of any type (user submitted hazards, aircraft, boats, atn) in that index. Maybe I want to listen for anything that is putting out a distress signal. Similarly in a race there would be a specific set of uuids that are participating in that race. If I'm piloting a big freighter in a busy harbor I probably want to filter out all the smaller, more maneuverable vessels like is commonly done with turning off AIS class B reception.

Subscribing to specific lists is most likely going to require looking into the tree of each thing or knowing its uuid. I see little value in trying to decide if something should be in vessels or vehicles or shore.

We can just think of a vessel as a container that holds property values about a specific thing. ;-)

[edit] Maybe the cabin is a tiny home on a trailer that I move around every so often and want to build a route for.

rob42 commented 7 years ago

Interesting use cases to consider. You can already subscribe by wildcard, using , so in the case of vehicles and vessels its conveniently `ve:-) With a geo-fence is not implemented on any of our servers yet, but the thinking is to allow jsonpath like syntax in subscriptions. That would allow you to subscribe to something equivalent to$.navigation.position[@latitude>x]or similar. That or we add arange` parameter to the subscription request, which would be simpler for your use case and quite useful

One of the things we avoid by having categories is the all-files-in-desktop mess you see on some pcs. Admittedly thats not working when we have a zillion vessels, but we already carry some legacy design I guess.

I will create a pull request for 'shore', 'aircraft', and add appropriate keys for the missing ais objects. Lets see how that looks.

webmasterkai commented 7 years ago

Will shore and aircraft be limited to specific properties or used solely for the purpose of organization and inherit all props from vessel? What decides what category a thing belongs?

Has thought been given to the time when individual sensors or groups of sensors might want to speak native SK?

Why not just prepend your categories to the uuid?

rob42 commented 7 years ago

I will add the minimum to shore and aircraft, and use the schema inheritance where I can. Its easy to add more at any time, so its not necessary to get them all except to satisfy the ais* values way up above in the thread.

We could prepend the category to the uuid, in fact we could just use uuids for the full key, and have a lookup table. But it would be hell to dev with. The categories are fairly arbitrary, but the idea is just to help guide the dev as much as anything. Its basically understandable by eye, no lookup is usually required.

{
    "updates": [{
        "source": {
            "label": "victron_1"
        },
        "values": [{
            "path": "electrical.chargers.victron.panelVoltage",
            "value": 0.01
        }]
    }]
}

Compare that with N2K and NMEA0183, or really awful stuff like HL7.

MSH|^~\&|MegaReg|XYZHospC|SuperOE|XYZImgCtr|20060529090131-0500||ADT^A01^ADT_A01|01052901|P|2.5
EVN||200605290901||||200605290900
PID|||56782445^^^UAReg^PI||KLEINSAMPLE^BARRY^Q^JR||19620910|M||2028-9^^HL70005^RA99113^^XYZ|260 GOODWIN CREST DRIVE^^BIRMINGHAM^AL^35209^^M~NICKELL’S PICKLES^10000 W 100TH AVE^BIRMINGHAM^AL^35200^^O|||||||0105I30001^^^99DEF^AN
PV1||I|W^389^1^UABH^^^^3||||12345^MORGAN^REX^J^^^MD^0010^UAMC^L||67890^GRAINGER^LUCY^X^^^MD^0010^UAMC^L|MED|||||A0||13579^POTTER^SHERMAN^T^^^MD^0010^UAMC^L|||||||||||||||||||||||||||200605290900
OBX|1|NM|^Body Height||1.80|m^Meter^ISO+|||||F
OBX|2|NM|^Body Weight||79|kg^Kilogram^ISO+|||||F
AL1|1||^ASPIRIN
DG1|1||786.50^CHEST PAIN, UNSPECIFIED^I9|||A
sumps commented 7 years ago

@rob42 I think shore is too big a category. Using Vessels as the precedent, I would suggest:

My impression was that the Resources group was specific navigation info managed by the Self vessel. It might be shared or copied from other vessels but it was a local information store for Self.

I see AIS objects as Signal K objects i.e. not associated with Self, but real world objects that are siblings to vessels. I agree that having them as I originally suggested i.e. aisAtoN, aisBaseStation, etc. was too limiting and I think your proposal of including an AIS SAR in the aircraft object, an AIS AtoN in a navaids object, etc, is a better approach.

faceless2 commented 7 years ago

@sumps eek! Do I put a Marina as a service or a building? It's both.

Personally I think we should resist the temptation to over-specify at this stage. Without actual data to work from, or use-cases for that data when we have it, it's all a bit arbitrary and I think we're better off staying focused on what we have now.

"vessels" is smart, and doesn't just cover boats (as @rob42's MOB example describes). More accurately this might be "things that are moving at sea". It's broad and flexible, and because of that it's useful.

The argument for an "aircraft" hierarchy is good, because they have different properties different to vessels at sea (altitude, rate of climb etc) So far we only have SAR aircraft as a data point, but I'm sure some enterprising sort will get their drone or balloon in there at some point, at which point we can flesh out that part of the model.

We have an existing source (and a use case) for static data, which is AIS AtoN - this covers buoys, lighthouses, wrecks and so on - as you say, this list is expanding as the authorities figure them out. Their universal property is that they're a point at a (relatively) fixed position, they have a description, but not all are at sea (think lighthouse, or a church spire on a hill used for navigation - yet to see this over AtoN, but we've all seen them on charts and I wouldn't rule it out). There are also other fixed objects of interest to mariners - lists of marinas or other useful facilities from openseamap, for example, or the lists of race buoys published by clubs.

Myself, I would put all of these under "fixed" (@rob42 I feel the existing "resources" tree is too general, as it also covers stuff like sources for map tiles). I think "shore" is a bad idea (see below).

Give them a name/type/lat/lon/description - where "type" is an enumeration which we can expand as necessary (buoy, lighthouse, marina and so on) - and define other fields appropriate for particular types as we get them - lights may have "altitude" and "lightPattern", AIS weather buoys can have "swellHeight" and "pressure", Marinas might have "vhfChannel" or "pumpoutAvailable".

I'd suggest keeping it an open-ended list of key-value pairs, and if we find a particular key-value pair is useful, then we can nail the definition for that one down a bit tighter at that point and not before (because debating how to store the list of fuels available at a marina is not a constructive use of our time at this point).

With this data I can display these items on a moving map, regardless of their type, and - crucially - when we expand the model to add new types, the map doesn't care. Just display a generic icon for unrecognised types, and the values of all the other fields when I click on it. This flexibility is also present under "vessels", and is how we can display MOB, EPIRBs and boats on the same map with the same code.

Finally, distinguishing between fixed items on the shore and fixed items at sea is (I think) not helpful, as they all have these same properties, and we are listing these items because they are of use to marine navigation, which is still the core focus of SignalK. If it's ever expanded to (say) mountaineering, then I imagine the data source for these will be a list of mountain huts rather than a list of marinas. These will still go nicely under "fixed".

There's plenty not covered in this model - submarines, cars, people, spacecraft - but without data and a use-case for it, I'm not sure it's worth spending time on defining them.

webmasterkai commented 7 years ago

Admittedly, I have made no contribution to SK yet so my opinion has little weight.

Trying to define useful SK "categories" or terms to establish how groups of attributes should be allowed causes future confusion and trouble. The most useful activity is to define how the attributes should be defined so they can be understood.

I have a wind sensor at the top of my mast. It's useful to know the elevation of that wind sensor. It's an attribute when sending information to wunderground for example. Elevation is not limited to aircraft. Similarly, rate of climb can most certainly be useful in other cases like water in a tank, or water in a bilge.

Take a weather station as an example. It is a prime candidate for speaking SK and transmitting its information to the web. What is important in being able to digest the information from the "weather station" is how to read its attributes, not what attributes are allowed. What category do we put a weather station in? What if it's on land? What if it's a collection of instruments on my boat? The "weather station" could move or be stationary. The sensors could be part of a vessel or an aircraft or a submarine.

My wind sensor is an Airmar 220wx. It has its own GPS, 3-Axis Solid State Compass, and sends many attributes. Temp, wind speed, direction, COG/SOG/Position, heading, pitch and roll, barometric pressure. In many ways, in a rough sea the sensor at the top of the mast moves through the air much like an aircraft. My firm belief is that this single device should be allowed to be its own first class object or vessel. Why can't it join an IP network, maintain its own cache of values and make them available via an http server just like any other vessel might?

The same problem of trying to pre-define a big tree is going to reveal itself all over SK until we let go of this concept of vessels representing a boat. Take #304, #331, #297, #264, #262 etc.

I vote for allowing anything to be a vessel and work on defining how various attributes should be defined as well as establishing a method of building associations.

Composition over Inheritance: https://www.youtube.com/watch?v=wfMtDGfHWpA

rob42 commented 7 years ago

@webmasterkai - all contributions and opinions are appreciated. There is plenty to do, every new contributor helps.

The idea that vessels be redefined to mean a container, aka a bottle or jar is clever :-) There are some good ideas above, and they have become visible because in signalk we now have a workable system. That wasnt the case when we made those design decisions.

I agree that there is merit in reworking these things but thats a big change and we cant do that now.

Also the original goal of this issue is sinking under wider the discussion: "There is currently no space in the specification for a few bits of (potentially) important information which will be obtained from other vessels over AIS."

I didnt get time to do the pull request last night, and looking again this morning that wasnt a bad thing. Lets concentrate on how we add the missing ais data with minimal wider change.

bkp7 commented 7 years ago

May I suggest that at this point in development, ie. prior to V1.0.0, dropping 'vessel' should not be off the table. I'm not particularly arguing either way, but what about 'entity' as a very generic alternative?

Could entity(vessel).navigagtion.state be expanded to included to include: static, fixed, taxiing, hover taxi, parked, gliding, etc, etc.

The issue I see is that so much of what is good about the current 'vessels', and indeed Signal K could/should be made available to the wider world.

The final point I would make is that Signal K should not look to be simply an alternative format for NMEA2000 or AIS data, it should, and I believe is, bigger than that, and whilst NMEA and AIS data should be capable of being accommodated there doesn't need to be a 1-1 relationship. ie. to my mind there is no reason that the AIS state of 'motoring', should not map to 'entityType = vessel' and 'navigation.state = underOwnPower'.

sumps commented 7 years ago

May I suggest that we do not "jump out of the frying pan in to the fire" in a hasty, rush to make a significant change to the Signal K V1 spec that would lose 18 months of real work by the core team.

This change needs to be properly considered, prototyped and specified by the people that feel passionately enough about the change to do the the necessary work and before they do, I suggest they study and fully understand how the current schema works before dismantling it.

rob42 commented 7 years ago

Im going to split this issue up into 2 more:

338 AtoN

339 Non-Vessel AIS data