#include <iostream>
#include <complex>
#include <vector>
#include <utility>
#include <queue>
#include <cmath>
using namespace std;

typedef complex<double> Point;
typedef pair<Point, Point> Line;
#define EPS 1e-9
#define INF 1e9

// ?????¢, ??????, ??????
double dis(Point a, Point b){ return abs(a - b); }
double dot(Point a, Point b){ return a.real() * b.real() + a.imag() * b.imag(); }
double cross(Point a, Point b){ return a.real() * b.imag() - a.imag() * b.real(); }


// ccw
//  1: c?????????ab??????????????´????????? (a?????????, b????\\??¨????????¨???)
// -1: c?????????ab??????????????´?????????
//  2: c?????????ab?????¶????????????a?????????????????????
// -2: c?????????ab?????¶????????????b???????\\?????????
//  0: c?????????ab????????????
int ccw(Point a, Point b, Point c){
  if(cross(b - a, c - a) > EPS) return 1;
  if(cross(b - a, c - a) < -EPS) return -1;
  if(dot(b - a, c - a) < -EPS) return 2;
  if(dis(a, b) + EPS < dis(c, a)) return -2;
  return 0;
}
int ccw(Line a, Point b){ return ccw(a.first, a.second, b); }

// ??????????????????(??????2???????????¶??´????????????)
Line CircleCross(Point a, double ra, Point b, double rb){
  double d = dis(a, b);
  double rc = (d * d + ra * ra - rb * rb) / (2 * d);
  double rs = sqrt(ra * ra - rc * rc);
  Point diff = (b - a) / d;
  return make_pair(a + diff * Point(rc, rs), a + diff * Point(rc, -rs));
}


vector<double> dijk(int s, vector<vector<pair<double, int> > > adj){
  int n = adj.size();
  vector<double> result(n, INF);
  priority_queue<pair<double, int> > wait;  
  result[s] = 0;
  wait.push(make_pair(0, s));

  while(!wait.empty()){
    double nowcost = -wait.top().first;
    int nowpoint = wait.top().second;
    wait.pop();
    if(result[nowpoint] < nowcost){ continue; }
    
    for(int i = 0; i < (int)adj[nowpoint].size(); i++){
      double nextcost = adj[nowpoint][i].first + nowcost;
      int nextpoint = adj[nowpoint][i].second;
      if(result[nextpoint] > nextcost){
        wait.push(make_pair(-nextcost, nextpoint));
        result[nextpoint] = nextcost;
      }
    }
  }

  return result;
}


int main(void){
  while(true){
    int n;
    cin >> n;
    if(n == 0){ break; }

    // ??????????????¨?????????????????????
    double x, y, r;
    vector<pair<Point, double> > circles;
    for(int i = 0; i < n; i++){
      cin >> x >> y >> r;
      circles.push_back(make_pair(Point(x, y), r));
    }

    // ????????????(+?§??????¨??????)?????????
    // second??????????????????????????????????????????????¨????
    vector<pair<Point, int> > vertices;
    vertices.push_back(make_pair(circles[0].first, 0));
    for(int i = 0; i < n - 1; i++){
      Line tmp = CircleCross(circles[i].first, circles[i].second, circles[i + 1].first, circles[i + 1].second);
      vertices.push_back(make_pair(tmp.first, 1));
      vertices.push_back(make_pair(tmp.second, -1));
    }
    vertices.push_back(make_pair(circles[n - 1].first, 0));

    // ??????i??¨j????????????????????????
    // ??????k(i+1???j-1)????????????????????????????????????????????°OK
    vector<vector<pair<double, int> > > adj(vertices.size());
    for(int i = 0; i < (int)vertices.size(); i++){
      for(int j = i + 1; j < (int)vertices.size(); j++){
        bool flag = true;
        for(int k = i + 1; k < j; k++){
          int tmp = ccw(vertices[i].first, vertices[j].first, vertices[k].first);
          if(tmp != vertices[k].second){ flag = false; }
        }
        if(flag){ adj[i].push_back(make_pair(dis(vertices[i].first, vertices[j].first), j)); }
      }
    }

    // ??????????????????????????????????????????
    vector<double> result = dijk(0, adj);
    printf("%.10f\n", result[result.size() - 1]);
  }

  return 0;
}

Measured memory_bytes: 3304