{"id":2568,"date":"2015-05-09T21:46:54","date_gmt":"2015-05-09T12:46:54","guid":{"rendered":"https:\/\/regex.info\/blog\/2015-05-09\/2568"},"modified":"2016-06-05T01:05:39","modified_gmt":"2016-06-04T16:05:39","slug":"the-voodoo-of-elevation-gain-and-strava-and-how-i-got-around-it","status":"publish","type":"post","link":"https:\/\/regex.info\/blog\/2015-05-09\/2568","title":{"rendered":"The Voodoo of Elevation Gain and Strava (and How I Get Around It)"},"content":{"rendered":"\n\n<div class='ic tight'>\n<a href='\/i\/c\/2015-05-06-valley.png'><img loading=\"lazy\" decoding=\"async\" src=\"\/i\/c\/2015-05-06-valley_sm.png\" width=\"690\" height=\"467\"\nid=\"i2015_05_06_valley\"\/><\/a>\n<br\/>\n<span class='caption'><span class='nobr'>A Light<\/span> Mountain Climb After Lunch<\/span>\n\n<br\/>340m climb from the village of Kurodani, Takashima City, Shiga Japan\n<br\/>\u9ad8\u5cf6\u5e02\u9ed2\u8c37\u304b\u3089\u306e\u5c71\u767b\u308a\n<meta itemprop='about' content=\"A Light Mountain Climb After Lunch 340m climb from the village of Kurodani, Takashima City, Shiga Japan \u9ad8\u5cf6\u5e02\u9ed2\u8c37\u304b\u3089\u306e\u5c71\u767b\u308a\"\/><\/div>\n\n<p>In the screenshot of Google Earth above, you can see the route that <span class='nobr'>I rode<\/span> my\nbicycle last Wednesday... the little bit of green coming in from\nthe right is <span class='nobr'>a downhill<\/span> section of road, followed by the long red uphill section\nthrough the tiered rice paddies of the village,\nthen up the mountain on an old road no longer open to traffic.<\/p>\n\n<p>I'd ridden 55km (34mi) to get to that point, and would end up riding\n72km (44mi) farther before <span class='nobr'>I got<\/span> home, but ever\nsince <a href='\/blog\/2015-02-09\/2521'>my first <span\nclass='QO'>&#8220;<\/span>real<span class='QC'>&#8221;<\/span> ride<\/a> in\nFebruary, I've not been so interested in how much distance I've covered,\nbut rather, in how much mountain I've conquered. This means the important\nstatistic for me is how much <span class='QO'>&#8220;<\/span>vertical\nclimb<span class='QC'>&#8221;<\/span> or <span\nclass='QO'>&#8220;<\/span>elevation gain<span class='QC'>&#8221;<\/span>\n<span class='nobr'>I did<\/span> during <span class='nobr'>a ride,<\/span>\nthe sum of all the rises\/climbs\/ascents on the route.<\/p>\n\n<p>And it's not just me... vertical climb is often used as <span class='nobr'>a badge<\/span> of\nachievement for <span class='nobr'>a ride,<\/span> and seems to get more talk than distance. <span class='nobr'>It's a strong<\/span> reflection for how tough <span class='nobr'>a route<\/span> is.<\/p>\n\n<p>The problem is that it's difficult to figure out the vertical climb for\n<span class='nobr'>a particular<\/span> route, and commonly-used methods are often <i>wildly<\/i>\ninaccurate.<\/p>\n\n<p>Cyclers I've met record the ride with <span class='nobr'>a GPS<\/span> unit of some sort\n(their iPhone, <span class='nobr'>a bike<\/span> computer, <span class='nobr'>a runner's<\/span> watch, etc.) and upload the\ndata to <a href='http:\/\/strava.com\/'>Strava<\/a>, <span class='nobr'>a service<\/span> that allows\nyou to analyze your activity and share info about it with others. <span class='nobr'>It's very popular<\/span> and mostly very well done.<\/p>\n\n<p>For example, I mentioned it in my previous post about <a\nhref='\/blog\/2015-05-02\/2567'><span class='nobr'>a long<\/span> mountain bikeride<\/a>\nthat <span class='nobr'>I did<\/span> on April 30th, where Strava had informed me that <span class='nobr'>I had<\/span> beaten my\nrecord for <span class='nobr'>a particularly<\/span> tough mountain climb:<\/p>\n\n<div class='ic tight'><a href='https:\/\/www.strava.com\/activities\/295260708#6939381906'><img loading=\"lazy\" decoding=\"async\" src=\"\/i\/s\/hanase-4-chart.png\" width=\"690\" height=\"208\"\nid=\"ihanase_4_chart\"\/><\/a>\n<br\/><span class='caption'>Data About My Rides<\/span>\n<br\/>Courtesy of Strava.com\n<meta itemprop='about' content=\"Data About My Rides Courtesy of Strava.com\"\/><\/div>\n\n<p>Footnote: I've since beat it again, but by only 10 seconds.<\/p>\n\n\n<p>When you upload your data to Strava, they calculate your vertical climb\nfor the activity, and display it prominently. For example, the\naforementioned <a href='\/blog\/2015-02-09\/2521'>first real\nmountain ride<\/a> shows some impressive stats:<\/p>\n\n<div class='ic tight'><a href='https:\/\/www.strava.com\/activities\/253293557'><img loading=\"lazy\" decoding=\"async\" src=\"\/i\/c\/2015-05-06-first-hanase-stats.png\" width=\"690\" height=\"442\"\nid=\"i2015_05_06_first_hanase_stats\"\/><\/a><\/div>\n\n<p>Since it was my first real ride, <span class='nobr'>I didn't<\/span> know any better but to be\nimpressed by the 3.3 kilometers (2 miles!) of vertical climb that I'd done. <span class='nobr'>I was amazing<\/span>. <span class='nobr'>I was Superman<\/span>.<\/p>\n\n<p>Unfortunately, it's all a lie.<\/p>\n\n<p>Over the course of several big mountain rides, <span class='nobr'>I'd started<\/span> to feel that\nthe numbers reported on Strava were quite <span class='nobr'>a bit<\/span> inflated, but <span class='nobr'>I couldn't<\/span> put\nmy finger on exactly how.<\/p>\n\n<p>A week or so ago I posed about another ride, <span class='QO'>&#8220;<\/span><a\nhref='\/blog\/2015-04-29\/2566' class='pt'>Short but Intense Bike Ride in Northern Kyoto<\/a><span class='QC'>&#8221;<\/span>, where someone <a\nhref='\/blog\/2015-04-29\/2566#comment-53451'>commented<\/a>\nabout the apparent discrepancy between reality and what Strava reported\n(and hence what <span class='nobr'>I claimed<\/span>). This spurred me into investigating, and I've\nspent the last week digging in, writing tracklog-analysis software, doing\ntests, etc.<\/p>\n\n<p>So, when I went out on a long ride last Wednesday, <b><span class='nobr'>I brought<\/span> an\narsenal of equipment with me, recording five separate logs with three\ndifferent GPS\/GLONASS-equipped devices.<\/b><\/p>\n\n<p>The trip ended up being my longest ride ever, about 125km (78mi), and\nalso had the most vertical climb I'd ever done in one day. Among the many ways <span class='nobr'>I\nrecorded<\/span> the trip's data, <span class='nobr'>I used<\/span> <a href='https:\/\/www.strava.com\/mobile'>Strava's mobile\napp<\/a> on <span class='nobr'>my iPhone 6+,<\/span> and when <span class='nobr'>I was<\/span> done <span class='nobr'>I had<\/span> the app\nupload all the data to Strava.<\/p>\n\n<p>Here's what Strava reported about that trip:<\/p>\n\n<div class='ic tight'><img loading=\"lazy\" decoding=\"async\" src=\"\/i\/c\/2015-05-06-wrong-stats.png\" width=\"690\" height=\"467\"\nid=\"i2015_05_06_wrong_stats\"\/>\n<br\/>\n<span class='caption'>Impressive!<\/span>\n<br\/>but wrong\n<meta itemprop='about' content=\"Impressive! but wrong\"\/><\/div>\n\n<p>The elevation graph at the bottom is an accurate representation of the\n11-hour ride, with four separate major mountain peaks transversed, along\nwith many little ones (though they each didn't seem little at the\ntime!).<\/p>\n\n<p>Strava informs me that the trip encompassed an impressive 3,627m\n(11,900') of vertical climb. <span class='nobr'>It looks<\/span> like <span\nclass='nobr'>I started<\/span> at about 50m and initially climbed to about\n500m, and from there went down and up quite <span class='nobr'>a bit<\/span>\n&mdash; and believe me, <span class='nobr'>I did<\/span> &mdash; but looking\nat the graph it's difficult to come up with a 3,637m sum for all the <span\nclass='QO'>&#8220;<\/span>up<span class='QC'>&#8221;<\/span> parts.<\/p>\n\n<p><b>In reality, <span class='nobr'>I believe<\/span> the vertical climb on the trip was about 2,225m (7,300').<\/b><\/p>\n\n<p style='margin-top:40px; margin-bottom:40px'>First, let's look at why Strava's numbers are so wrong, then let's look\nat how to get <span class='nobr'>a better<\/span> answer.<\/p>\n\n<p>There are various ways a unit can record your elevation as you travel,\nand all of them are generally untrustworthy. Modern units like an iPhone\nor <span class='nobr'>a dedicated<\/span> unit like a <a href='http:\/\/bad-elf.com\/products\/be-gps-2300'>Bad Elf GPS Pro+<\/a>\nhave three methods to figure altitude: <a href='http:\/\/en.wikipedia.org\/wiki\/Global_Positioning_System'>GPS<\/a>,\n<a href='http:\/\/en.wikipedia.org\/wiki\/GLONASS'>GLONASS<\/a>, and a\n<a href='http:\/\/en.wikipedia.org\/wiki\/Altimeter#Pressure_altimeter'>barometric altimeter<\/a>.<\/p>\n\n<p>GPS\/GLONASS can be fairly accurate with your latitude and longitude, as I've discussed in prior\nposts, such as\n<span class='QO'>&#8220;<\/span><a class='pt' href='\/blog\/2012-01-15\/1922'>Informal GPS Logger Test: iPhone 4s GPS is Shockingly Good<\/a><span class='QC'>&#8221;<\/span>\nand\n<span class='QO'>&#8220;<\/span><a class='pt' href='\/blog\/2012-06-11\/2016'>Another Informal Location-Logger Test<\/a><span class='QC'>&#8221;<\/span>.\nIt's <i>fantastically-amazing<\/i> technology that is perhaps the only\ntime we come in contact with something that must actually take into account\n<a href='http:\/\/en.wikipedia.org\/wiki\/General_relativity'>Einstein's\ngeneral theory of relativity<\/a>. But it's not perfect, and of the three\ndimensions, elevation is by far the least accurate.<\/p>\n\n<p>Consider these views of three GPS\/GLONASS units' tracklogs plotted in Google Earth,\nof various sections of last Wednesday's ride:<\/p>\n\n<div class='ic tight'><img loading=\"lazy\" decoding=\"async\" src=\"\/i\/c\/2015-05-06-bad2.png\" width=\"690\" height=\"468\"\nid=\"i2015_05_06_bad2\"\/><\/div>\n<div class='ic tight'><img loading=\"lazy\" decoding=\"async\" src=\"\/i\/c\/2015-05-06-bad3.png\" width=\"650\" height=\"459\"\nid=\"i2015_05_06_bad3\"\/><\/div>\n<div class='ic tight'><img loading=\"lazy\" decoding=\"async\" src=\"\/i\/c\/2015-05-06-bad1.png\" width=\"690\" height=\"454\"\nid=\"i2015_05_06_bad1\"\/><\/div>\n\n<p>The three units rarely agreed with each other on the elevation, nor any\nof them with Google data as seen in Google Earth, and they each in their\nown way tended to wander off wildly at times. (The tracks, when viewed\ndirectly from above, all matched up with each other and the road quite\nwell... it's only the elevation data that was, so to speak, all over the\nmap.)<\/p>\n\n<p>When wishing to track vertical climb, the absolute accuracy of <span class='nobr'>a unit<\/span> is\nnot particularly important, it's the relative accuracy and stability that\nare important, and it seems that barometric altimeters provide better results.<\/p>\n\n<p>My first experience with a barometric altimeter, on <a\nhref='\/blog\/2006-04-16\/179'><span class='nobr'>a Garmin<\/span> GPS unit<\/a> <span class='nobr'>a decade<\/span>\nago, was very bad. <span class='nobr'>If there<\/span> was <span class='nobr'>a breeze<\/span> or you walked with the unit, it\nwould record <span class='nobr'>a non<\/span>-trivial change in elevation (up or down, depending on\nhow the unit was physically angled relative to the air movement). <span class='nobr'>It was ridiculous<\/span>.<\/p>\n\n<p>Things seem better now. On last Wednesday's trip, <span class='nobr'>I had two<\/span> barometric\naltimeters with me, the one in my iPhone 6+, and another on <span class='nobr'>a Bad<\/span> Elf GPS+.\nHere's their plots for the last section seen above:<\/p>\n\n<div class='ic tight'><img loading=\"lazy\" decoding=\"async\" src=\"\/i\/c\/2015-05-06-soso1.png\" width=\"690\" height=\"437\"\nid=\"i2015_05_06_soso1\"\/><\/div>\n\n<p>Anyway, a na\u00efve calculation of vertical climb looks at each data point\nand, if the elevation of <span class='nobr'>a point<\/span> is higher than\nthe previous point, add the difference to the total. Minor errors that\nresult in small fluctuations over the short term result in wildly-inflated\noverall results, but one can smooth the raw data (e.g. with <span\nclass='nobr'>a moving<\/span> average) to get more realistic results. That's\napparently what Google Earth does, so let's look at what it calculates for\neach of my five tracklogs:<\/p>\n\n\n<table border='1' cellspacing='0' cellpadding='5' style='margin-left:3em; text-align:center'>\n<tr><th>Unit<\/th><th>Type<\/th><th colspan='2'>Google-Earth Vertical-Climb Calculation<\/th><\/tr>\n<tr><td>BadElf GPS+<\/td>    <td>GPS\/GLONASS<\/td><td>3,479m<\/td><td>11,414'<\/td><\/tr>\n<tr><td>BadElf GPS+<\/td>    <td>Barometric<\/td> <td>2,174m<\/td><td>7,133'<\/td><\/tr>\n<tr><td>Garmin eTrex 20<\/td><td>GPS\/GLONASS<\/td><td>3,265m<\/td><td>10,712'<\/td><\/tr>\n<tr><td>Apple iPhone 6+<\/td><td>GPS\/GLONASS<\/td><td>2,215m<\/td><td>7,267'<\/td><\/tr>\n<tr><td>Apple iPhone 6+<\/td><td>Barometric<\/td> <td>2,009m<\/td><td>6,591'<\/td><\/tr>\n<\/table>\n\n<p>That's quite a range of results from the very same trip. Which is correct?\nFrankly, probably none of them.<\/p>\n\n<p>As we'll see later, there are techniques we can use to eke out some\nfairly reasonable results, but first let's see what Strava actually\ndoes...<\/p>\n\n<p><b>What Strava Does<\/b><\/p>\n\n<p>Strava's iPhone app has access to both iPhone altimeters (barometric and\nGPS\/GLONASS), but in the end it uses neither. Rather, it throws away that\nelevation data and instead relies on its own database of elevation data\n(likely the same data that Google uses to show 3D elevation in Google\nEarth).<\/p>\n\n<p>Strava's approach may well be fine in generally-flat areas, but it produces\nridiculously-overinflated results in the mountainous areas I've checked, and\nit's easy to see why...<\/p>\n\n<p>I created some software to analyze the tracklogs, smooth local\nirregularities, and present uphill sections in red and downhill sections in\ngreen. Let's look at the mountain shown in this article's lead photo, <span class='nobr'>a\nlong<\/span> climb followed by <span class='nobr'>a long,<\/span> enjoyable descent down the other side...<\/p>\n\n<div class='ic tight'><img loading=\"lazy\" decoding=\"async\" src=\"\/i\/c\/2015-05-06-pass-bebaro.jpg\" width=\"690\" height=\"444\"\nalt=\"Reality red means uphill, green means downhill\"\nid=\"i2015_05_06_pass_bebaro\"\ntitle=\"Reality red means uphill, green means downhill\"\/><br\/><span class='caption'>Reality<\/span>\n <br\/>red means uphill, green means downhill\n<meta itemprop='about' content=\"Reality red means uphill, green means downhill\"\/><\/div>\n\n<p>Both the climb and the descent were quite straightfoward;\nthe climb was <span class='nobr'>a solid<\/span> climb without any downhill breaks, and the descent was <span class='nobr'>a solid<\/span> descent\nwithout any uphill sections. That's why the ascent is <span class='nobr'>a solid<\/span> red line above, and the\ndescent is <span class='nobr'>a solid<\/span> green line.<\/p>\n\n<p>Now, let's look at how Strava sees it, as well as all my data sources...<\/p>\n\n<div class='ic' style='position:relative; margin-bottom:20px'>\n\n<div id='img015_6'  style='visibility:visible; margin:0; width:100%;position:absolute; left:0; top:0'><div style='margin-top:0; margin-bottom:0' class='ic' ><img loading=\"lazy\" decoding=\"async\" src=\"\/i\/c\/2015-05-06-pass-strava.jpg\" width=\"690\" height=\"444\"\nalt=\"from Strava's elevation data\"\nid=\"i2015_05_06_pass_strava\"\ntitle=\"from Strava's elevation data\"\/>\n<br\/>\nfrom Strava's elevation data\n<meta itemprop='about' content=\"from Strava's elevation data\"\/><\/div><\/div>\n\n\n<div id='img015_1'  style='visibility:hidden; margin:0; width:100%'><div style='margin-top:0; margin-bottom:0' class='ic' ><img loading=\"lazy\" decoding=\"async\" src=\"\/i\/c\/2015-05-06-pass-bebaro.jpg\" width=\"690\" height=\"444\"\nalt=\"Bad Elf GPS+ (using its barometric altimeter)\"\nid=\"i2015_05_06_pass_bebarox2\"\ntitle=\"Bad Elf GPS+ (using its barometric altimeter)\"\/>\n<br\/>\nBad Elf GPS+ (using its barometric altimeter)\n<meta itemprop='about' content=\"Bad Elf GPS+ (using its barometric altimeter)\"\/><\/div><\/div>\n\n<div id='img015_2'  style='visibility:hidden; margin:0; width:100%;position:absolute; left:0; top:0'><div style='margin-top:0; margin-bottom:0' class='ic' ><img loading=\"lazy\" decoding=\"async\" src=\"\/i\/c\/2015-05-06-pass-begps.jpg\" width=\"690\" height=\"444\"\nalt=\"Bad Elf GPS+ (using GPS\/GLONASS)\"\nid=\"i2015_05_06_pass_begps\"\ntitle=\"Bad Elf GPS+ (using GPS\/GLONASS)\"\/>\n<br\/>\nBad Elf GPS+ (using GPS\/GLONASS)\n<meta itemprop='about' content=\"Bad Elf GPS+ (using GPS\/GLONASS)\"\/><\/div><\/div>\n\n<div id='img015_3'  style='visibility:hidden; margin:0; width:100%;position:absolute; left:0; top:0'><div style='margin-top:0; margin-bottom:0' class='ic' ><img loading=\"lazy\" decoding=\"async\" src=\"\/i\/c\/2015-05-06-pass-galelio.jpg\" width=\"690\" height=\"444\"\nalt=\"iPhone 6+ using GPS\/GLONASS, as recorded with the Galileo Offline Maps app\"\nid=\"i2015_05_06_pass_galelio\"\ntitle=\"iPhone 6+ using GPS\/GLONASS, as recorded with the Galileo Offline Maps app\"\/>\n<br\/>\niPhone 6+ using GPS\/GLONASS, as recorded with\n<strike>Galileo Offline Maps<\/strike> (Name changed Feb 2019 to <a href='https:\/\/gurumaps.app\/'>Guru Maps<\/a>)\n<meta itemprop='about' content=\"iPhone 6+ using GPS\/GLONASS, as recorded with the Galileo Offline Maps app\"\/><\/div>\n\n<\/div>\n<div id='img015_4'  style='visibility:hidden; margin:0; width:100%;position:absolute; left:0; top:0'><div style='margin-top:0; margin-bottom:0' class='ic' ><img loading=\"lazy\" decoding=\"async\" src=\"\/i\/c\/2015-05-06-pass-garmin.jpg\" width=\"690\" height=\"444\"\nalt=\"Garmin eTrex 20 (GPS\/GLONASS)\"\nid=\"i2015_05_06_pass_garmin\"\ntitle=\"Garmin eTrex 20 (GPS\/GLONASS)\"\/>\n<br\/>\nGarmin eTrex 20 (GPS\/GLONASS)\n<meta itemprop='about' content=\"Garmin eTrex 20 (GPS\/GLONASS)\"\/><\/div><\/div>\n\n<div id='img015_5'  style='visibility:hidden; margin:0; width:100%;position:absolute; left:0; top:0'><div style='margin-top:0; margin-bottom:0' class='ic' ><img loading=\"lazy\" decoding=\"async\" src=\"\/i\/c\/2015-05-06-pass-runmeter.jpg\" width=\"690\" height=\"444\"\nalt=\"iPhone 6+ using barometric altimeter, as recorded with Abvio's Runmeter app\"\nid=\"i2015_05_06_pass_runmeter\"\ntitle=\"iPhone 6+ using barometric altimeter, as recorded with Abvio's Runmeter app\"\/>\n<br\/>\niPhone 6+ using barometric altimeter, as recorded with <a href='http:\/\/abvio.com\/runmeter\/'>Abvio's <i>Runmeter<\/i> app<\/a>\n<meta itemprop='about' content=\"iPhone 6+ using barometric altimeter, as recorded with Abvio's Runmeter app\"\/><\/div><\/div>\n\n\n<\/div>\n\n<style type=\"text\/css\">\nspan.b015 { font-size: small; padding: 2px; border: gray 1px solid }\n<\/style>\n<center>\n  <span class='b015' id='but015_6' onmouseover='OnMouse015(6)' style='border-color: red'>Strava<\/span>\n  &nbsp;-&nbsp; <span class='b015' id='but015_1' onmouseover='OnMouse015(1)'>BE (baro)<\/span>\n  &nbsp;-&nbsp; <span class='b015' id='but015_4' onmouseover='OnMouse015(4)'>Garmin (GPS)<\/span>\n  &nbsp;-&nbsp; <span class='b015' id='but015_2' onmouseover='OnMouse015(2)'>BE (gps)<\/span>\n  &nbsp;-&nbsp; <span class='b015' id='but015_3' onmouseover='OnMouse015(3)'>iPhone (GPS)<\/span>\n  &nbsp;-&nbsp; <span class='b015' id='but015_5' onmouseover='OnMouse015(5)'>iPhone (baro)<\/span>\n\n\n  <p>\n  <small>mouseover <span class='nobr'>a button<\/span> to see that image<\/small>\n  <\/p>\n<\/center>\n\n<script type=\"text\/javascript\">\n\/\/<![CDATA[\n var img015 = new Array();\n var but015 = new Array();\n\nimg015[1] = document.getElementById('img015_1');\nbut015[1] = document.getElementById('but015_1');\nimg015[2] = document.getElementById('img015_2');\nbut015[2] = document.getElementById('but015_2');\nimg015[3] = document.getElementById('img015_3');\nbut015[3] = document.getElementById('but015_3');\nimg015[4] = document.getElementById('img015_4');\nbut015[4] = document.getElementById('but015_4');\nimg015[5] = document.getElementById('img015_5');\nbut015[5] = document.getElementById('but015_5');\nimg015[6] = document.getElementById('img015_6');\nbut015[6] = document.getElementById('but015_6');\n\n\n function OnMouse015(num)\n {\n   img015[num].style.visibility      = 'visible';\n   but015[num].style.borderColor     = '#FF4040';\n   but015[num].style.backgroundColor = '#808080';\n   but015[num].style.color           = 'white';\n   but015[num].style.borderWidth     = '3px';\n   but015[num].style.padding         = '4px';\n\n   for (i = 1; i < 7; i++) {\n      if (i != num) {\n          img015[i].style.visibility    = 'hidden';\n          but015[i].style.borderColor     = 'gray';\n          but015[i].style.backgroundColor = '';\n          but015[i].style.borderWidth     = '1px';\n          but015[i].style.padding         = '2px';\n          but015[i].style.color           = '#888';\n      }\n   }\n }\n\/\/]]>\n<\/script>\n\n<p>The Strava data shows many ups and downs on both sides of the mountain... ups and downs that\nsimply weren't there. <span class='nobr'>It's easy to<\/span> see why when you look at the mountain in Google Earth (which <span class='nobr'>I believe<\/span>\nuses the same elevation data) from the side. Here's the side of the mountain that <span class='nobr'>I rode<\/span> down:<\/p>\n\n<div class='ic tight'><img loading=\"lazy\" decoding=\"async\" src=\"\/i\/c\/2015-05-06-down0.jpg\" width=\"690\" height=\"452\"\nid=\"i2015_05_06_down0\"\/>\n<br\/>very-3D mountain pressed into <span class='nobr'>a mostly<\/span>-2D face\n<meta itemprop='about' content=\"very-3D mountain pressed into a mostly -2D face\"\/><\/div>\n\n<p>The road appears undulate up and down as it makes overall progresses lower, and to Strava,\nthe <span class='QO'>&#8220;<\/span>ups<span class='QC'>&#8221;<\/span> count as vertical climb:<\/p>\n\n<div class='ic tight'><img loading=\"lazy\" decoding=\"async\" src=\"\/i\/c\/2015-05-06-down1.jpg\" width=\"690\" height=\"452\"\nid=\"i2015_05_06_down1\"\/>\n<br\/>Strava <span class='QO'>&#8220;<\/span>detects<span class='QC'>&#8221;<\/span> many false climbs (216m\/700' just in this view alone)\n<meta itemprop='about' content=\"Strava &amp;#8220; detects &amp;#8221; many false climbs (216m\/700' just in this view alone)\"\/><\/div>\n\n<p>Of course, the road doesn't undulate up and down (it progresses <span class='QO'>&#8220;<\/span>monotonically<span class='QC'>&#8221;<\/span> down),\nbut it does undulate\n<i>side to side<\/i> around ravines cut into the side of the mountain by eons of water and wind. <span class='nobr'>You can sort<\/span> of see the proper undulation in this path created with <span class='nobr'>a barometric<\/span> altimeter:<\/p>\n\n<div class='ic tight'><img loading=\"lazy\" decoding=\"async\" src=\"\/i\/c\/2015-05-06-down2.jpg\" width=\"690\" height=\"452\"\nid=\"i2015_05_06_down2\"\/>\n<br\/>descending <i>around<\/i> ravines that do exist, but which aren't presented in Google Earth\n<meta itemprop='about' content=\"descending around ravines that do exist, but which aren't presented in Google Earth\"\/><\/div>\n\n<p>I should be clear that I'm not complaining about Google... the resources\nthey've freely gifted to the world in Google Earth and Google Maps\ncontinues to amaze me, and I'm extremely thankful for them.<\/p>\n\n<p>I'm not quite sure that I'm complaining about Strava. Perhaps these\neasily-avoidable inflated results are particular to my area of Japan, and\nthe rest of the world enjoys added accuracy due to Strava's policies. <span\nclass='nobr'>I don't<\/span> know. <span class='nobr'>But I do<\/span> know\nthat <span class='nobr'>a lot<\/span> of folks around the world complain\nabout Strava's inflated elevation claims, so at least <span class='nobr'>I know<\/span> that I'm not\nalone.<\/p>\n\n<p><b>So How Can We Do Better<\/b><\/p>\n\n<p>First of all, I should note that Strava <i>does<\/i> respect the recorded\nelevation in some situations where it recognizes that the data was recorded\nwith <span class='nobr'>a barometric<\/span> altimeter. Their own iPhone app, however, either doesn't\nuse the barometric altimeter or doesn't notice that it does, so users get stuck\nwith Strava's wild elevation data.<\/p>\n\n<p>Where Strava does accept a device's elevation data, they offer the user\n<span class='nobr'>a way<\/span> to get <span class='QO'>&#8220;<\/span>corrected<span class='QC'>&#8221;<\/span> data, whereby Strava throws away the user's data\nand replaces it with their inaccurate elevation-database data. This results\nin <span class='nobr'>a much<\/span> less accurate result for many folks, but they offer no way to\nundo this action, so if you bump the link by accident, you're hosed.<\/p>\n\n<p>They also don't allow you to toggle between your device elevation data\n(barometric or not) and their data. <span class='nobr'>It seems<\/span> that they really want to push\ntheir data, and who can blame them? Folks like me early on, ignorant of the\nhyper-inflated vertical-climb data, get an ego boost from seeing the big\nnumbers. <span class='nobr'>I suppose<\/span> boosted egos help their business interests.<\/p>\n\n<p>(I'm thankful for their service, which <span class='nobr'>I have<\/span>\nenjoyed without cost. <span class='nobr'>I just wish<\/span> this aspect\nwere better.)<\/p>\n\n<p>(Update: Strava has a lot of problems as a company in how they respect their users,\nbut in the end I appreciate the tools that do seem to work, so I've signed up as a paying customer.)<\/p>\n\n<p>Luckily, one crack in their anti-reality armor is that they allow geeky\ntypes like me to create tracklogs with other devices, then <a\nhref='https:\/\/strava.github.io\/api\/v3\/uploads\/#device-and-elevation-data'>modify\nthe tracklog to force Strava to accept the elevation data as is<\/a>, and upload\nthat.<\/p>\n\n<p><b>Massaging Tracklog Data<\/b><\/p>\n\n<p>I've spent the last few days writing software to analyze tracklog data,\nto smooth it out, and to derive meaningful information from it.<\/p>\n\n<p>The first step is to identify when you're stopped, because if you're not\nmoving, you should have no elevation gain or loss, no speed... nothing.\nYou're stopped.<\/p>\n\n<p>Unfortunately, GPS receivers tend to record drifting locations when\nstationary, such as the hour <span class='nobr'>I spent<\/span> visiting\nsomeone (<a href='\/blog\/2015-04-12\/2555#i075131'>this\nsweet lady<\/a>) in the mountains along the way on Wednesday's long ride:<\/p>\n\n<div class='ic tight'><img loading=\"lazy\" decoding=\"async\" src=\"\/i\/c\/2015-05-06-stationary1.jpg\" width=\"690\" height=\"446\"\nid=\"i2015_05_06_stationary1\"\/>\n<br\/>this is what an hour's complete lack of movement looks like\n<meta itemprop='about' content=\"this is what an hour's complete lack of movement looks like\"\/><\/div>\n\n<p>My analysis figured out that all that movement didn't really get me anywhere, so it filters it out\nand marks the stopped location with <span class='nobr'>a little<\/span> blue ring:<\/p>\n\n<div class='ic tight'><img loading=\"lazy\" decoding=\"async\" src=\"\/i\/c\/2015-05-06-stationary2.jpg\" width=\"690\" height=\"446\"\nid=\"i2015_05_06_stationary2\"\/>\n<br\/><span class='QO'>&#8220;<\/span>pause<span class='QC'>&#8221;<\/span> detected\n<meta itemprop='about' content=\"&amp;#8220; pause &amp;#8221; detected\"\/><\/div>\n\n\n<p>I have my software note the length of the pause in the KML label, like this:<\/p>\n\n<div class='ic tight'><img loading=\"lazy\" decoding=\"async\" src=\"\/i\/c\/2015-05-06-stationary3.png\" width=\"300\" height=\"81\"\nclass=\"raw\"\nid=\"i2015_05_06_stationary3\"\/><\/div>\n\n<p>My pause detection seems to be highly accurate, and <span class='nobr'>I compared<\/span> its\nresults with the reality that <span class='nobr'>I remembered<\/span> on the trip, and it's pretty much perfect. <span class='nobr'>It even accurately<\/span> detected <span class='nobr'>a 10<\/span>-second pause at an intersection waiting for <span class='nobr'>a few<\/span> cars to clear\nbefore <span class='nobr'>I crossed<\/span> over:<\/p>\n\n<div class='ic tight'><img loading=\"lazy\" decoding=\"async\" src=\"\/i\/c\/2015-05-06-stationary4.jpg\" width=\"690\" height=\"451\"\nid=\"i2015_05_06_stationary4\"\/>\n<br\/>10-second pause for traffic\n<meta itemprop='about' content=\"10-second pause for traffic\"\/><\/div>\n\n<div class='ic'><img loading=\"lazy\" decoding=\"async\" src=\"\/i\/c\/2015-05-06-stationary5.jpg\" width=\"690\" height=\"451\"\nid=\"i2015_05_06_stationary5\"\/>\n<br\/>45-minute pause wandering in and around <span class='nobr'>a convenience<\/span> store\n<br\/>while waiting for a friend to join me on the trip\n<meta itemprop='about' content=\"45-minute pause wandering in and around a convenience store while waiting for a friend to join me on the trip\"\/><\/div>\n\n<p>Then my software goes through the entire trip to find the highest peak\nand the lowest valley, and pin the elevation at those locations. That\ndivides the whole trip into four parts, each of which is subject to the\nsame analysis, and this analysis recurses (repeats onto itself) over and\nover until the difference between <span class='nobr'>a local<\/span> peak and <span class='nobr'>a local<\/span> valley is almost\nwithin the range of noise.<\/p>\n\n<p>Once all these local peaks and valleys are found, the elevation of all\nthe points in between are smoothed using <span class='nobr'>a moving<\/span> average. <span class='nobr'>The elevation<\/span> of\neach peak\/valley point is left undisturbed, and it's the elevation rise\nbetween them that adds up to the trip's vertical climb.<\/p>\n\n<p>After all this analysis, the software prepares <span class='nobr'>a KML<\/span> file that shows\nthe trip, with red lines for climbs, green for descents, and white for flat sections\n(and, optionally, the blue circles for pauses). Here's one view of the second half of my trip:<\/p>\n\n<div class='ic tight'>\n<a href='\/i\/c\/2015-05-06-view1.jpg'><img loading=\"lazy\" decoding=\"async\" src=\"\/i\/c\/2015-05-06-view1_sm.jpg\" width=\"690\" height=\"395\"\nid=\"i2015_05_06_view1\"\/><\/a>\n<br\/>\nLooking North up the eastern side of Lake Biwa\n<meta itemprop='about' content=\"Looking North up the eastern side of Lake Biwa\"\/><\/div>\n\n<p>The red line at the far right ends at the Shirahige Shrine (<a\nhref='\/blog\/2015-04-26\/2562#i076189'>seen here<\/a> in the\nreport on <span class='nobr'>a ride<\/span> two weeks ago), which we visited briefly after having come\nover the mountain, before turning south to ride home.<\/p>\n\n<p>The distance from the shrine in the background to the spot in the\nforeground where the route turns 90 degrees and pitches up into the\nmountains is 30km (18mi) as the crow flies, which <span class='nobr'>I mention<\/span> for scale.<\/p>\n\n<p>Here's the whole 125km (78mi) trip:<\/p>\n\n<div class='ic tight'>\n<img loading=\"lazy\" decoding=\"async\" src=\"\/i\/c\/2015-05-06-view2.jpg\" width=\"690\" height=\"546\"\nid=\"i2015_05_06_view2\"\/>\n<\/div>\n\n<p>If you'd like to see it yourself, you can download the KML file\n(<a href='\/i\/c\/Jeff-and-Salvo-Ride-2015-05-06-with-Pauses.kml'>with pauses<\/a> \/\n<a href='\/i\/c\/Jeff-and-Salvo-Ride-2015-05-06-without-Pauses.kml'>without pauses<\/a>)\nto view in Google Earth.<\/p>\n\n<p>The <span class='QO'>&#8220;<\/span>with pauses<span class='QC'>&#8221;<\/span> view is best for me when <span class='nobr'>I want<\/span> to <span class='QO'>&#8220;<\/span>relive the experience<span class='QC'>&#8221;<\/span>, and <span class='nobr'>I can<\/span> see,\nfor example,\nthat <span class='nobr'>I stopped<\/span> for half an hour &mdash; 31:26 &mdash; to eat lunch (at <a href='\/blog\/2008-06-28\/851'>this place<\/a>\nthat <span class='nobr'>I last<\/span> visited seven years ago), and then progressed up the mountain stopping at intervals\nfor photos, to check directions, or to fix <span class='nobr'>a popped<\/span> chain.<\/p>\n\n<div class='ic tight'><img loading=\"lazy\" decoding=\"async\" src=\"\/i\/c\/2015-05-06-with-pauses.jpg\" width=\"690\" height=\"376\"\nid=\"i2015_05_06_with_pauses\"\/>\n<\/div>\n\n<p>That view is pretty cluttered if all <span class='nobr'>I want<\/span> to do is analyze whether the vertical-climb data seems reasonable,\nso for that the <span class='QO'>&#8220;<\/span>without pauses<span class='QC'>&#8221;<\/span> version is better:<\/p>\n\n<div class='ic tight'><img loading=\"lazy\" decoding=\"async\" src=\"\/i\/c\/2015-05-06-without-pauses.jpg\" width=\"690\" height=\"376\"\nid=\"i2015_05_06_without_pauses\"\/><\/div>\n\n<p>The duration includes all the intervening pauses, rendering it fairly\nmeaningless, so <span class='nobr'>I should<\/span> probably simply remove it, but at the moment it's\nstill there.<\/p>\n\n<p>Anyway, I did this analysis on all my tracklogs, and found that the one produced\nby the Bad Elf GPS+ with barometric altimeter seemed to most match reality, so that's the one\n<span class='nobr'>I consider,<\/span> relatively speaking, <span class='QO'>&#8220;<\/span>correct<span class='QC'>&#8221;<\/span>.<\/p>\n\n<p>And after all this analysis and cleaning and smoothing, <span class='nobr'>I'm left with<\/span> <span class='nobr'>a tracklog<\/span> that I (relatively speaking) trust,\nso <span class='nobr'>I prepare<\/span> it so that Strava won't override the elevation data, and upload it. Strava doesn't know that I've\ngrooomed it, so it does its standard processing, and comes up with this:<\/p>\n\n<div class='ic tight'><a href='https:\/\/www.strava.com\/activities\/300751761\/overview'><img loading=\"lazy\" decoding=\"async\" src=\"\/i\/c\/2015-05-06-final-strava.jpg\" width=\"400\" height=\"75\"\nid=\"i2015_05_06_final_strava\"\/><\/a><\/div>\n\n<p>They somehow came up with an extra 100m of vertical gain, but since <span class='nobr'>I\ntruly<\/span> don't know what the actual value is, <span class='nobr'>I can't<\/span> say that they're any\nless wrong than <span class='nobr'>I am.<\/span><\/p>\n\n<p>So, now that I have the ability to derive <span class='nobr'>a realistic<\/span> vertical-climb\nvalue, to be honest with myself <span class='nobr'>I must<\/span> go back and correct prior trips:<\/p>\n\n<style type=\"text\/css\">\n table#t2568a td:nth-child(2) { text-align: left; padding-left:1em; padding-right: 0.5em }\n table#t2568a td.ft { font-size: small; white-space: no-break }\n\n<\/style>\n<table id='t2568a' border='1' cellspacing='0' cellpadding='5' style='margin-left:3em; text-align:center'>\n<tr>\n<th valign='baseline'><br\/>Date<\/th>\n<th><br\/>Event<\/th>\n<th style='padding:0 1em'>Vertical Gain<br\/>Claimed at the Time<\/th>\n<th style='padding:0 1em'>Vertical Gain<br\/>Realistic Value<\/th>\n<th>Strava<br\/>Inflation<\/th>\n<th>(in feet)<\/th>\n<\/tr>\n\n<tr>\n <td>Jan 24<\/td>\n <td><a href='\/blog\/2015-01-25\/2517'>My first tentative outing on bike<\/a><\/td>\n <td><i>N\/A<\/i><\/td>\n <td>685m<\/td>\n <td><\/td>\n <td class='ft'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&rarr; 2,090'<\/td>\n<\/tr>\n\n<tr>\n <td>Feb 7<\/td>\n <td><a href='\/blog\/2015-02-09\/2521'>My first real mountain ride<\/a><\/td>\n <td>3,850m<\/td>\n <td>1,517m<\/td>\n <td>274%<\/td>\n <td class='ft'>12,630' &rarr; 4,620'<\/td>\n<\/tr>\n\n<tr>\n <td><span class='nobr'>March 3<\/span><\/td>\n <td><a href='\/blog\/2015-03-03\/2532'>Kuyataki Waterfall with Manseki<\/a><\/td>\n <td>762m<\/td>\n <td>540m<\/td>\n <td>141%<\/td>\n <td class='ft'>2,500' &rarr; 1,650'<\/td>\n<\/tr>\n\n<tr>\n <td><span class='nobr'>March 4<\/span><\/td>\n <td><a href='\/blog\/2015-03-05\/2533'>Group ride southeast of Kyoto<\/a><\/td>\n <td>1,787m<\/td>\n <td>1,282m<\/td>\n <td>140%<\/td>\n <td class='ft'>5,860' &rarr; 3,910'<\/td>\n<\/tr>\n\n<tr>\n <td><span class='nobr'>April 16<\/span><\/td>\n <td><a href='\/blog\/2015-04-19\/2559'><span class='QO'>&#8220;<\/span>Highly Visible<span class='QC'>&#8221;<\/span> mountain ride<\/a><\/td>\n <td>1,607m<\/td>\n <td>1,180m<\/td>\n <td>136%<\/td>\n <td class='ft'>5,270' &rarr; 3,600'<\/td>\n<\/tr>\n\n<tr>\n <td><span class='nobr'>April 23<\/span><\/td>\n <td><a href='\/blog\/2015-04-26\/2562'>Pleasant 105km lake ride<\/a><\/td>\n <td>1,300m<\/td>\n <td>?<\/td>\n <td><\/td>\n <td class='ft'>4,200' &rarr;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/td>\n<\/tr>\n\n<tr>\n <td><span class='nobr'>April 29<\/span><\/td>\n <td><a href='\/blog\/2015-04-29\/2566'>Coffee at Cowbell<\/a><\/td>\n <td>1,720m<\/td>\n <td>991m<\/td>\n <td>174%<\/td>\n <td class='ft'>5,600' &rarr; 3,020'<\/td>\n<\/tr>\n\n<tr>\n <td><span class='nobr'>April 30<\/span><\/td>\n <td><a href='\/blog\/2015-05-02\/2567'>Revisiting my first big mountain ride<\/a><\/td>\n <td>3,159m<\/td>\n <td>1,609m<\/td>\n <td>196%<\/td>\n <td class='ft'>10,360' &rarr; 4,900'<\/td>\n<\/tr>\n\n<\/table>\n\n<p>I didn't have a good barometric-altimeter tracklog for one of the rides.<\/p>\n\n<p>The amount of <span class='QO'>&#8220;<\/span>Strava inflation<span class='QC'>&#8221;<\/span> is shocking. <span class='nobr'>If I could<\/span> solve this\nproblem for myself in <span class='nobr'>a couple<\/span> of days, you'd think <span class='nobr'>a real<\/span> company with\npresumably smart folks could come up with something.<\/p>\n\n<p>Anyway, I'll need to find a better app for keeping tracklogs on the\niPhone, one that lets me record both the GPS\/GLONASS elevation and the\nbarometric elevation, and also my heartrate. <span class='nobr'>As it\nis<\/span> now, I'll use <span class='nobr'>a klugy<\/span> mixture of\nvarious devices and combine all the data myself, massage it, smooth it, and\nthen send it to Strava.<\/p>\n\n<p>If they ever get around to addressing this, <span class='nobr'>I suppose<\/span> that would be <span class='nobr'>a\ngood<\/span> time to bring up the next issue: they ignore elevation changes when\ncalculating distance. They <a\nhref='https:\/\/strava.zendesk.com\/entries\/21278088-How-Distance-is-Calculated'>correctly\nnote<\/a> that the difference is perhaps at most 2%, but on <span class='nobr'>a 100km<\/span> ride that can still\nbe over <span class='nobr'>a mile<\/span> wrong.<\/p>\n\n<p>Overall, I guess Strava is just not as anal about statistics as <span class='nobr'>I am.<\/span>..<\/p>\n\n<p><i><a href='\/blog\/2015-05-15\/2571'>Continued here...<\/a><\/i><\/p>\n\n","protected":false},"excerpt":{"rendered":"<p>In the screenshot of Google Earth above, you can see the route that I rode my bicycle last Wednesday... the little bit of green coming in from the right is a downhill section of road, followed by the long red uphill section through the tiered rice paddies of the village, then up the mountain on an old road no longer open to traffic.<\/p> <p>I'd ridden 55km (34mi) to get to that point, and would end up riding 72km (44mi) farther before I got home, but ever since my first \"real\" ride in February, I've not been so interested in how [...]","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[30,2,31,4],"tags":[],"_links":{"self":[{"href":"https:\/\/regex.info\/blog\/wp-json\/wp\/v2\/posts\/2568"}],"collection":[{"href":"https:\/\/regex.info\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/regex.info\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/regex.info\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/regex.info\/blog\/wp-json\/wp\/v2\/comments?post=2568"}],"version-history":[{"count":0,"href":"https:\/\/regex.info\/blog\/wp-json\/wp\/v2\/posts\/2568\/revisions"}],"wp:attachment":[{"href":"https:\/\/regex.info\/blog\/wp-json\/wp\/v2\/media?parent=2568"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/regex.info\/blog\/wp-json\/wp\/v2\/categories?post=2568"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/regex.info\/blog\/wp-json\/wp\/v2\/tags?post=2568"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}