[Last Updated February 23, 2019]
In a previous post, we explored how expressions in the calculation column of your XLSForm could be used to programmatically set values on a geopoint question. In this occasion, we will do the opposite. That is, we will describe how you can extract data out of a geopoint. Here are some good reasons why you may want to do this:
We all know that geopoint questions store location information, but what is really inside a geopoint value? At a minimum, unless a geopoint question is empty, you will always find the latitude and longitude of a location. Survey123 never works with projected coordinates: geopoint values are always in geographic coordinates using WGS84. Now, you could potentially find much more than just a latitude/longitude pair within a geopoint value. The most common properties include:
Property Name | Description | Units |
---|---|---|
x | Longitude, positive in eastern hemisphere, negative in western hemisphere | Decimal degrees |
y | Latitude, positive in northern hemisphere, negative in southern hemisphere | Decimal degrees |
z | Altitude, meters above sea level | Meters |
horizontalAccuracy | Horizontal accuracy of the x and y coordinates | Meters |
verticalAccuracy | Vertical accuracy of the z coordinate | Meters |
speed | Ground speed | Meters per second |
verticalSpeed | Vertical speed | Meters per second |
direction | Direction of travel measured clockwise from north | Decimal degrees |
magneticVariation | Angle between magnetic and true north | Decimal degrees |
positionSourceType | Returns the category of the position source. Unknown (0), User (1), System Location (2), External Device (3), and Network Device (4). | |
fixType | Returns the type of position fix the coordinate has. Potential results are NoFix (0), GPS (1), DifferentialGPS (2), PrecisePositioningService (3), RTKFixed (4), RTKFloat (5), Estimated (6), Manual (7), Simulator (8), and SBAS (9). |
If a geopoint question contains all the properties above or a subset, depends on the following:
If relying on consumer devices to retrieve the location properties above, you should take values with a grain of salt. Your average iPad or Android smartphone could often give you a reasonable x,y and horizontal accuracy but everything else could or could not be trustworthy. In fact, many consumer devices do not even populate most of the properties above. I do not want to say consumer devices will give you useless geopoint properties, but you should proceed with caution understanding through trial and error what devices and in what conditions will give you accurate information.
By connecting Survey123 to an external GNSS receiver, not only you can significantly improve the location accuracy of your data, but also get many more properties associated with your geopoint values. Here is a list of the most important properties you can get. The complete list is available in our help.
Property Name | Description |
---|---|
positionSourceInfo.deviceName | The name of your external GNSS device |
positionSourceInfo.deviceType | Indicates how your GNSS is connected to your device. Unknown (-1), Bluetooth (0), Serial Port (1), and Bluetooth LE (2). |
positionSourceInfo.antennaHeight | The user defined GNSS antenna height. |
positionSourceInfo.altitudeType | Indicates the selected altitude type: altitude above mean sea level (0) and height above ellipsoid (1). |
geoidSeparation | Returns the difference between the WGS-84 earth ellipsoid and mean sea level as reported by the GNSS receiver. This is also sometimes referred to as orthometric height. |
accuracyType | RMS (0) and DOP (1) |
positionAccuracy | Returns the mean radial spherical error. Encompasses both horizontal and vertical error. |
differentialAge | Returns the age of the differential signal and correction used by the GNSS receiver to differentially correct the position. |
referenceStationId | Returns the differential reference station ID (DSID) of the station used by the GPS receiver. |
satellitesVisible | Returns the number of satellites visible at the time of location capture. |
satellitesInUse | Returns the number satellites being used to return the position data. |
All the geopoint properties described above can be extracted using the pulldata function. For example:
pulldata("@geopoint", ${location}, "horizontalAccuracy")
The "@geopoint" parameter to the pulldata function indicates that values will be extracted from a geopoint value.
The second parameter indicates the question in your XLSForm that holds the actual geopoint value. You will want to make sure that the question you reference is actually of type geopoint.
The third and last parameter defines the geopoint property you want to extract. You will want to make sure the property name is included in the table above and make sure that you specify it with the proper capitalization: HorizontalAccuracy is not the same as horizontalAccuracy.
Here is a simple XLSForm that will extract the X,Y and horizontal accuracy of your geopoint and store these values as attributes. Using this technique, you have complete freedom as to which fields in your feature service will be used to store the geopoint properties. You use the Name column in the XLSForm to define which field will keep the data.
Type | Name | Label | Calculation |
---|---|---|---|
geopoint | location | Location | |
decimal | Latitude | Latitude | pulldata("@geopoint", ${location},"y") |
decimal | Longitude | Longitude | pulldata("@geopoint", ${location},"x") |
decimal | HorAccMeters | Accuracy | pulldata("@geopoint", ${location},"horizontalAccuracy") |
Realistically, I would never store geopoint properties as illustrated in the example above. Mostly because I would not want end-users to get distracted with questions in the survey that get automatically populated with these properties. I would not want end-users to modify these calculated values either.
A more refined approach would be to set the Type of question as hidden. In this way, the Latitude, Longitude and accuracy questions will not be shown in the form, but their information would still be sent to the feature service on submit. To ensure the actual values are stored as numbers in the feature service, I would also set the esriFieldType column to esriFieldTypeDouble as shown here:
Type | Name | Label | Calculation | bind::esri:fieldType |
---|---|---|---|---|
geopoint | location | Location | ||
hidden | Latitude | Latitude | pulldata("@geopoint", ${location},"y") | esriFieldTypeDouble |
hidden | Longitude | Longitude | pulldata("@geopoint", ${location},"x") | esriFieldTypeDouble |
hidden | HorAccMeters | Accuracy | pulldata("@geopoint", ${location},"horizontalAccuracy") | esriFieldTypeDouble |
When working with horizontal accuracy, you should also learn about the meaning of the accuracyThreshold column.
You can use very similar expressions in your constraints and relevant statements. In the next example, we will pop a message in case that the geopoint value was captured while moving faster than 0.2 meters per second.
Type | Name | Label | Relevant |
---|---|---|---|
geopoint | location | Location | |
calculate | speed | Speed | pulldata("@geopoint", ${location},"speed") |
note | Do not move while fixing location! | 0.2<number(${speed}) |
Like every time you use pulldata() it is best practice to use this function alone. This is why I broke down my last example into two separate questions: One calculate question to invoke pulldata() and a separate question where I compare the output of the pulldata function with a number.
In this blog post I simply wanted to introduce the use of the pulldata("@geopoint") function. With it, you can build expressions to persist location metadata as GIS attributes, but also to create powerful data validation rules in your smart forms.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.