Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

base/Trajectory.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002   Copyright (C)2002 David Jung <opensim@pobox.com>
00003 
00004   This program/file is free software; you can redistribute it and/or modify
00005   it under the terms of the GNU General Public License as published by
00006   the Free Software Foundation; either version 2 of the License, or
00007   (at your option) any later version.
00008   
00009   This program is distributed in the hope that it will be useful,
00010   but WITHOUT ANY WARRANTY; without even the implied warranty of
00011   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012   GNU General Public License for more details. (http://www.gnu.org)
00013   
00014   You should have received a copy of the GNU General Public License
00015   along with this program; if not, write to the Free Software
00016   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017   
00018   $Id: Trajectory.cpp 1047 2004-02-27 19:21:35Z jungd $
00019   $Revision: 1.7 $
00020   $Date: 2004-02-27 14:21:35 -0500 (Fri, 27 Feb 2004) $
00021   $Author: jungd $
00022  
00023 ****************************************************************************/
00024 
00025 #include <base/Trajectory>
00026 
00027 #include <sstream>
00028 
00029 #include <base/TrajectoryTimeRep>
00030 #include <base/Externalizer>
00031 #include <base/externalization_error>
00032 #include <base/Application>
00033 #include <base/VFile>
00034 
00035 // concrete representations
00036 #include <base/LineSegTrajectoryRep>
00037 #include <base/WaypointTrajectoryRep>
00038 #include <base/ParametricTrajectoryRep>
00039 
00040 
00041 using base::Trajectory;
00042 
00043 using base::LineSegTrajectoryRep;
00044 using base::WaypointTrajectoryRep;
00045 using base::ParametricTrajectoryRep;
00046 
00047 using base::externalization_error;
00048 using base::Application;
00049 using base::VFile;
00050 using base::PathName;
00051 
00052 using base::dom::DOMNode;
00053 using base::dom::DOMElement;
00054 
00055 
00056 
00057 Trajectory::Trajectory()
00058 {
00059   create();
00060 }
00061 
00062 
00063 Trajectory::Trajectory(const Trajectory& t)
00064 {
00065   create(t);
00066 }
00067 
00068 Trajectory::Trajectory(const Path& p, Int samples)
00069 {
00070   // extract the path in a general way if possible
00071   if (p.numDistinguishedValues() > 2) {
00072 
00073     array<Point3> points(p.numDistinguishedValues());
00074     array<Orient> orients(p.numDistinguishedValues());
00075     array<Time>   times(p.numDistinguishedValues());
00076 
00077     for(Int i=0; i<p.numDistinguishedValues(); i++) {
00078       Real s = p.distinguishedValue(i);
00079       points[i] = p.position(s);
00080       orients[i] = p.orientation(s);
00081       times[i] = s;
00082     }
00083 
00084     create(points, orients, times, false);
00085   }
00086   else {
00087 
00088     array<Point3> points(samples);
00089     array<Orient> orients(samples);
00090     array<Time>   times(samples);
00091 
00092     for(Int i=0; i<samples; i++) {
00093       Real s = Real(i)/Real(samples-1);
00094       points[i] = p.position(s);
00095       orients[i] = p.orientation(s);
00096       times[i] = s;
00097     }
00098 
00099     create(points, orients, times, false);
00100     
00101   }
00102 }
00103 
00104 
00105 Trajectory::Trajectory(const Point3& sp, const Orient& so, const Time& st, 
00106                        const Point3& ep, const Orient& eo, const Time& et)
00107 {
00108   create(sp,so,st,ep,eo,et);
00109 }
00110 
00111 
00112 Trajectory::Trajectory(const array<Point3>& points, const array<Orient>& orients, const array<Time>& times, bool deltas)
00113 {
00114   create(points, orients, times, deltas);
00115 }
00116 
00117 
00118 Trajectory::Trajectory(const array<Vector>& points, bool deltas)
00119 {
00120   create(points,deltas);
00121 }
00122 
00123 
00124 Trajectory::Trajectory(const ExpressionVector& p)
00125 {
00126   create(p);
00127 }
00128 
00129 
00130 
00131 void Trajectory::init(const array<Point3>& points, const array<Orient>& orients, const array<Time>& times, bool deltas)
00132 {
00133   ref<WaypointTrajectoryRep> wrep;
00134 
00135   if (!deltas)
00136     wrep = ref<WaypointTrajectoryRep>(NewObj WaypointTrajectoryRep(points, orients, times));
00137   else {
00138     array<Point3> apoints(points.size()+1);
00139     apoints[0] = Point3(0,0,0);
00140     for(Int i=0; i<points.size(); i++)
00141       apoints[i+1] = apoints[i]+points[i];
00142 
00143     array<Orient> aorients(orients.size()+1);
00144     aorients[0] = Orient();
00145     for(Int i=0; i<orients.size(); i++) {
00146       Quat4 q1(aorients[i].getQuat4());
00147       Quat4 q2(orients[i].getQuat4());
00148       aorients[i+1] = Orient(q2*q1);
00149     }
00150 
00151     array<Time> atimes(times.size()+1);
00152     atimes[0] = 0;
00153     for(Int i=0; i<times.size(); i++)
00154       atimes[i+1] = atimes[i]+times[i];
00155 
00156     wrep = ref<WaypointTrajectoryRep>(NewObj WaypointTrajectoryRep(apoints, aorients, atimes));
00157   }
00158 
00159   rep = wrep;
00160   trep = wrep;
00161 }
00162 
00163 
00164 
00165 void Trajectory::create()
00166 {
00167   // default traj (degenerate traj - create as line segment with both ends the same time)
00168   ref<LineSegTrajectoryRep> lrep(NewObj LineSegTrajectoryRep());
00169   rep = lrep;
00170   trep = lrep;
00171 }
00172 
00173 void Trajectory::create(const Trajectory& t)
00174 {
00175   ref<Referenced> c( &base::clone( *t.trep ) );
00176 
00177   rep = narrow_ref<PathRep>(c);
00178   trep = narrow_ref<TrajectoryTimeRep>(c);
00179 }
00180 
00181 void Trajectory::create(const Point3& sp, const Orient& so, const Point3& ep, const Orient& eo)
00182 {
00183   ref<LineSegTrajectoryRep> lrep(NewObj LineSegTrajectoryRep(sp, so, 0, ep, eo, 1));
00184   rep = lrep;
00185   trep = lrep;
00186 }
00187 
00188 void Trajectory::create(const Point3& sp, const Orient& so, const Time& st,
00189                         const Point3& ep, const Orient& eo, const Time& et)
00190 {
00191   ref<LineSegTrajectoryRep> lrep(NewObj LineSegTrajectoryRep(sp, so, st, ep, eo, et));
00192   rep = lrep;
00193   trep = lrep;
00194 }
00195 
00196 void Trajectory::create(const array<Point3>& points, const array<Orient>& orients, bool deltas)
00197 {
00198   // init default times to range over [0..1]
00199   array<Time> times(points.size());
00200   for(Int i=0; i<times.size(); i++)
00201     times[i] = Time( i/times.size() );
00202 
00203   init(points,orients,times,false);
00204 }
00205 
00206 void Trajectory::create(const array<Point3>& points, const array<Orient>& orients, const array<Time>& times, bool deltas)
00207 {
00208   init(points,orients,times,deltas);
00209 }
00210 
00211 void Trajectory::create(const array<Vector>& points, bool deltas)
00212 {
00213   // convert points to arrays of Point3, Orients & Times
00214   Assert(points.size() > 0);
00215   Assert(points[0].size() >= 4);
00216 
00217   array<Point3> pos(points.size());
00218   array<Time>   time(points.size());
00219   for(Int i=0; i<points.size(); i++) {
00220     const Vector& v(points[i]);
00221     pos[i] = Point3(v[0],v[1],v[2]);
00222     time[i] = Time(v[3]);
00223   }
00224   
00225   array<Orient> orient(points.size());
00226   if (points[0].size() == 7) { // assuming EulerRPY
00227     for(Int i=0; i<points.size(); i++) {
00228       const Vector& v(points[i]);
00229       orient[i] = Orient(v[3],v[4],v[5]);
00230       time[i] = Time(v[6]);
00231     }
00232   }
00233   else
00234     if (points[0].size() == 8) { // assuming quat
00235       for(Int i=0; i<points.size(); i++) {
00236         const Vector& v(points[i]);
00237         orient[i] = Orient(Quat4(v[3],v[4],v[5],v[6]));
00238         time[i] = Time(v[7]);
00239       }
00240     }
00241 
00242   init(pos,orient,time,deltas);
00243 }
00244 
00245 
00246 /// \todo implement
00247 void Trajectory::create(const ExpressionVector& p)
00248 {
00249   Unimplemented;
00250 }
00251 
00252 
00253 
00254 base::Path Trajectory::toPath() const
00255 {
00256   return Path(*this);
00257 }
00258 
00259 
00260 void Trajectory::resample(Int samples)
00261 {
00262   array<Point3> points(samples);
00263   array<Orient> orients(samples);
00264   array<Time>   times(samples);
00265 
00266   Time start = time(0);
00267   Time end = time(1);
00268   Time duration = end-start;
00269 
00270   for(Int i=0; i<samples; i++) {
00271     Real s = Real(i)/Real(samples-1);
00272     points[i] =  Path::position(s);
00273     orients[i] = Path::orientation(s);
00274     times[i] = start + duration*s;
00275   }
00276 
00277   init(points, orients, times, false);
00278    
00279 }
00280 
00281 
00282 void Trajectory::resample(const Real dxmax)
00283 {
00284   Assert(dxmax > 0);
00285   
00286   array<Point3> points;
00287   array<Orient> orients;
00288   array<Time>   times;
00289   
00290   // start with first distinguished value
00291   Time t = time( distinguishedValue(0) );
00292   Point3 pos( position(t) );
00293   Orient orient( orientation(t) );
00294   points.push_back( pos );
00295   orients.push_back( orient );
00296   times.push_back( t );
00297 
00298   Time lasttime( t );
00299   Point3 lastpos( pos );
00300   Int i = 1; // current distinguished value index
00301   while (i < numDistinguishedValues()) {
00302 
00303     // get next distinguished value
00304     t = time(distinguishedValue(i) );
00305     pos = position(t);
00306     orient = orientation(t);
00307     
00308     // calc dx = this pos - last pos
00309     Vector3 dx = pos - lastpos;
00310     if (dx.length() > dxmax) { // dist was too big, set current pos to a distance of maxdx from last pos
00311       Real scale = dxmax/dx.length();
00312       t = lasttime + scale*(t-lasttime);
00313       pos = position(t);
00314       orient = orientation(t);
00315     }
00316     else
00317       ++i;
00318     
00319     points.push_back( pos );
00320     orients.push_back( orient );
00321     times.push_back( t );
00322 
00323     lasttime = t;
00324     lastpos = pos;
00325   }
00326   
00327   init(points, orients, times, false);
00328   
00329 }
00330 
00331   
00332   
00333 
00334 void Trajectory::serialize(Serializer& s)
00335 {
00336   // register instantiators for all the TrajectoryRep classes for dynamic instantiation upon deserialization
00337   Serializable::registerSerializableInstantiator<TrajectoryTimeRep,LineSegTrajectoryRep>(lineSegTrajectoryRepInstantiator);
00338   Serializable::registerSerializableInstantiator<TrajectoryTimeRep,WaypointTrajectoryRep>(waypointTrajectoryRepInstantiator);
00339   
00340   s.baseRef(trep,"TrajectoryTimeRep");
00341 }
00342 
00343 
00344 bool Trajectory::formatSupported(String format, Real version, ExternalizationType type) const
00345 {
00346   return    ((format == "txt") && (version==1.0))
00347          || ((format == "xml") && (version==1.0));
00348 }
00349 
00350 
00351 void Trajectory::externalize(Externalizer& e, String format, Real version)
00352 {
00353   if (format=="") format = String("xml");
00354 
00355   if (!formatSupported(format,version,e.ioType()))
00356     throw std::invalid_argument(Exception(String("format ")+format+" "+base::realToString(version)+" unsupported"));
00357 
00358   if (format == "txt") {
00359 
00360     if (e.isInput()) {
00361       
00362       array<Point3> points;
00363       array<Orient> orients;
00364       array<Time> times;
00365       
00366       while (e.moreInput()) {
00367         
00368         String line(e.readLine());
00369         if (line.empty()) break; // empty line or eof indicates end of list
00370         while (line[0] == '#') line = e.readLine(); // skip comment lines
00371         
00372         // count separating spaces to determine if there are 7 or 8
00373         // numbers present
00374         Int spaces=0;
00375         for(Int i=0; i<line.size(); i++) 
00376           if (line[i]==' ') { 
00377             spaces++;
00378             while ( (i<line.size()-1) && (line[i]==' ')) i++;
00379           }
00380         if (line[0]==' ') spaces--; // don't count leading space(s)
00381         
00382         Assert(spaces >= 6);
00383         bool quat = (spaces>6);
00384         std::istringstream iss(line);
00385         iss.setf(std::ios_base::skipws | std::ios_base::dec);
00386         
00387         Point3 p;
00388         iss >> p.x >> p.y >> p.z;
00389         Vector v(quat?4:3);
00390         iss >> v[0] >> v[1] >> v[2];
00391         if (quat) iss >> v[3];
00392         Real t;
00393         iss >> t;
00394         
00395         points.push_back(p);
00396         
00397         orients.push_back(Orient(v, quat? Orient::Quat : Orient::EulerRPY));
00398         
00399         times.push_back(Time(t));
00400       }
00401       
00402       init(points,orients,times,false);
00403       
00404     }
00405     else { // output
00406       std::ostringstream out;
00407       
00408       // comment header
00409       out << "# waypoint trajectory (positions, orientations & times)" << std::endl;
00410       out << "#           x             y             z ";
00411       if (orientation(distinguishedValue(0)).representation() == Orient::EulerRPY)
00412         out << "            R             P             Y" << std::endl;
00413       else
00414         out << "           qx            qy            qz            qw            t" << std::endl;
00415       
00416       std::ostream::fmtflags savedFlags = out.setf(std::ios_base::dec | std::ios_base::right);
00417       Int savedPrec = out.precision(10);
00418       Int savedWidth = out.width(13);
00419       
00420       for(Int i=0; i<numDistinguishedValues(); i++) {
00421         Point3 p(position(distinguishedValue(i)));
00422         Orient o(orientation(distinguishedValue(i)));
00423         Time t(time(distinguishedValue(i)));
00424         
00425         // this is a hack, as under gcc the flags don't appear to stay set after an output op (!?)
00426 #define setflags \
00427       out.setf(std::ios_base::dec | std::ios_base::right); \
00428       out.precision(10); \
00429       out.width(13); 
00430         
00431         out << p.x << " "; setflags
00432         out << p.y << " "; setflags
00433         out << p.z << " "; setflags
00434         if ( (o.representation() != Orient::Quat) && (o.representation() != Orient::EulerRPY) )
00435           o.changeRepresentation(Orient::Quat);
00436         
00437         Vector v(o);
00438         out << v[0] << " "; setflags
00439         out << v[1] << " "; setflags
00440         out << v[2]; setflags
00441         if (v.size() > 3 ) out << " " << v[3];
00442         out << t.seconds(); setflags;
00443         out << std::endl;
00444         
00445       }
00446 
00447       out.setf(savedFlags);
00448       out.precision(savedPrec);
00449       out.width(savedWidth);
00450       
00451       e.writeString(out.str());
00452     }
00453   } 
00454   else if (format == "xml") {
00455 
00456     if (e.isOutput()) {
00457 
00458       DOMElement* trajElem = e.createElement("trajectory");
00459 
00460       bool parametric = instanceof(*rep, ParametricTrajectoryRep);
00461       
00462       if (parametric) { // special case for parametric representation to retain symbolic expressions
00463        
00464         // dig into the parametric representation and output the actual Expression strings
00465         ref<ParametricTrajectoryRep> trep(narrow_ref<ParametricTrajectoryRep>(rep));
00466         ExpressionVector v(trep->v);
00467         Expression times(trep->times);
00468         bool hasorient = (v.size() > 3);
00469         bool quatrep = false;
00470         if (hasorient && v.size() > 6) quatrep = true;
00471         
00472         if (!hasorient) {
00473           e.setElementAttribute(trajElem,"representation", "x(s) y(s) z(s) t(s)");
00474           e.appendComment(trajElem, "position functions x(s),y(s),z(s) and time t(s) [one per line]");
00475         }
00476         else {
00477           if (quatrep) {
00478             e.setElementAttribute(trajElem,"representation", "x(s) y(s) z(s) qx(s) qy(s) qz(s) qw(s) t(s)");
00479             e.appendComment(trajElem,"position functions x(s),y(s),z(s) orientation quaternion element functions (qx, qy, qz, qw) and time(s) (secs) [one per line; w is scalar]");
00480           }
00481           else {
00482             e.setElementAttribute(trajElem,"representation", "x(s) y(s) z(s) r(s) p(s) y(s) t(s)");
00483             e.appendComment(trajElem,"position functions x(s),y(s),z(s) orientation Euler angle functions (roll, pitch yaw) and time(s) (secs) [one per line]");
00484           }
00485         }
00486         
00487         
00488         for (Int i=0; i<v.size(); i++) {
00489           e.appendText( trajElem, v[i].toString() );
00490           e.appendBreak( trajElem);
00491         }
00492         e.appendText( trajElem, times.toString() );
00493         e.appendBreak( trajElem);
00494         
00495       }
00496       else { // output distinguished points as waypoints
00497         Orient::Representation rep = orientation(distinguishedValue(0)).representation();
00498         if ((rep != Orient::Quat) && (rep != Orient::EulerRPY) )
00499           rep = Orient::Quat;
00500   
00501         if (rep==Orient::Quat) {
00502           e.setElementAttribute(trajElem,"representation", "x y z qx qy qz qw t" );
00503           e.appendComment(trajElem, "position (x,y,z) orientation quaternion (qx,qy,qz,qw) [w is scalar component] time (secs)");
00504         } else {
00505           e.setElementAttribute(trajElem,"representation", "x y z r p y t" );
00506           e.appendComment(trajElem,"position (x,y,z) orientation Euler angles (roll, pitch yaw) time (secs)");
00507         }
00508   
00509         e.setElementAttribute(trajElem,"pointtype", "absolute");
00510         if (frame!="")
00511           e.setElementAttribute(trajElem,"frame", frame);
00512         if (units!="")
00513           e.setElementAttribute(trajElem,"units", units);
00514   
00515         for(Int i=0; i<numDistinguishedValues(); i++) {
00516           Point3 p(position(distinguishedValue(i)));
00517           Orient o(orientation(distinguishedValue(i)));
00518           Time t(time(distinguishedValue(i)));
00519   
00520           o.changeRepresentation(rep);
00521           Vector vo(o);
00522           Vector v(3+vo.size()+1);
00523           v[0] = p.x; v[1] = p.y; v[2] = p.z;
00524           if (vo.size() == 3) { // rpy
00525             v[3] = vo[0]; v[4] = vo[1]; v[5] = vo[2];
00526             v[6] = t.seconds();
00527           }
00528           else { // quat
00529             v[3] = vo[0]; v[4] = vo[1]; v[5] = vo[2]; v[6] = vo[3];
00530             v[7] = t.seconds();
00531           }
00532   
00533           e.appendText( trajElem, e.toString(v) );
00534           e.appendBreak( trajElem );
00535   
00536         }
00537       }
00538       
00539       e.appendElement(trajElem);    
00540 
00541     }
00542     else { // input
00543       DOMNode* context = e.context();
00544       
00545       // will accept either <trajectory> or <path>
00546 
00547       DOMElement* trajElem = e.getFirstElement(context, "trajectory", false);
00548 
00549       if (trajElem) { // <trajectory>
00550 
00551         // handle link
00552         String link = e.getElementAttribute(trajElem,"link",false);
00553         if (link != "") {
00554           
00555           ref<VFile> linkFile = Application::getInstance()->universe()->cache()->findFile(link,e.getArchivePath());
00556           load(linkFile,format,version);
00557         }
00558         else {
00559 
00560           String repText = e.getElementAttribute(trajElem, "representation");
00561         
00562           bool absolute = ( e.getDefaultedElementAttribute(trajElem, "pointtype", "absolute") == "absolute" );
00563           frame = e.getDefaultedElementAttribute(trajElem, "frame", "");
00564           units = e.getDefaultedElementAttribute(trajElem, "units", "");
00565         
00566           Orient::Representation rep;
00567           bool hasorient = true;
00568           bool parametric = false;
00569           bool scalarFirst=false;
00570           
00571           if (repText == "x y z t") {
00572             hasorient=false;
00573           }
00574           else if (repText == "x y z qx qy qz qw t") {
00575             rep = Orient::Quat;
00576           }
00577           else if (repText == "x y z qw qx qy qz t") {
00578             rep = Orient::Quat;
00579             scalarFirst=true;
00580           }
00581           else if (repText == "x y z r p y t") {
00582             rep = Orient::EulerRPY;
00583           }
00584           else if (repText == "x(s) y(s) z(s) t(s)") {
00585             hasorient = false;
00586             parametric = true;
00587           }
00588           else if (repText == "x(s) y(s) z(s) qx(s) qy(s) qz(s) qw(s) t(s)") {
00589             parametric = true;
00590             rep = Orient::Quat;
00591           }
00592           else if (repText == "x(s) y(s) z(s) qw(s) qx(s) qy(s) qz(s) t(s)") {
00593             parametric = true;
00594             rep = Orient::Quat;
00595             scalarFirst=true;
00596           }
00597           else if (repText == "x(s) y(s) z(s) r(s) p(s) y(s) t(s)") {
00598             parametric = true;
00599             rep = Orient::EulerRPY;
00600           }
00601           else            
00602             throw externalization_error(Exception("unknown or unsupported trajectory representation"));
00603           
00604           String trajText = e.getContainedText(trajElem,true);
00605           array<String> trajLines = e.splitIntoLines(trajText);
00606 
00607           if (!parametric) {
00608             array<Point3> points;
00609             array<Orient> orients;
00610             array<Time> times;
00611             
00612             if (trajLines.size() < 2)
00613               throw externalization_error(Exception("trajectory must contain at least two points"));
00614           
00615             for(Int i=0; i<trajLines.size(); i++) {
00616               array<String> elts = e.splitAtDelimiter(trajLines[i], ' ');
00617               if (    ((rep==Orient::Quat) && (elts.size() != 8))
00618                    || ((rep==Orient::EulerRPY) && (elts.size() != 7)) )
00619                 throw externalization_error(Exception("trajectory point with wrong number of elements encountered"));
00620               Vector v( e.stringsToReals(elts) );
00621               points.push_back( Point3(v[0],v[1],v[2]) );
00622               if (hasorient) {
00623                 if (rep==Orient::Quat) {
00624                   if (!scalarFirst)
00625                     orients.push_back( Orient(Quat4(v[3],v[4],v[5],v[6])) );
00626                   else
00627                     orients.push_back( Orient(Quat4(v[6],v[3],v[4],v[5])) );
00628                 }
00629                 else if (rep==Orient::EulerRPY) {
00630                   orients.push_back( Orient(v[3],v[4],v[5]) );
00631                 }
00632               }
00633               else
00634                 orients.push_back( Orient() );
00635               
00636               times.push_back( Time(v[v.size()-1]) );
00637             }
00638   
00639             init(points,orients,times,!absolute);
00640           }
00641           else { // parametric
00642             
00643             if (!absolute)
00644               throw externalization_error(Exception("pointtype of 'relative' doesn't make sense for parametric expression trajectories"));
00645             
00646             ExpressionVector v(4);
00647   
00648             try {
00649             
00650               if (!hasorient) {
00651                 if (trajLines.size() != 4)
00652                   throw externalization_error(Exception("trajectory should have one line for each parametric expression x(s), y(s), z(s) and t(s)"));
00653                 v[0] = Expression(trajLines[0]);
00654                 v[1] = Expression(trajLines[1]);
00655                 v[2] = Expression(trajLines[2]);
00656                 v[3] = Expression(trajLines[3]);
00657               }
00658               else { // hasorient
00659                 if (rep == Orient::Quat) {
00660                   if (trajLines.size() != 8)
00661                     throw externalization_error(Exception("trajectory should have one line for each parametric expression x(s), y(s), z(s), qx(s), qy(s), qz(s),qw(s) and t(s)"));
00662                   v.resize(8);
00663                   v[0] = Expression(trajLines[0]);
00664                   v[1] = Expression(trajLines[1]);
00665                   v[2] = Expression(trajLines[2]);
00666                   if (!scalarFirst) {
00667                     v[3] = Expression(trajLines[3]);
00668                     v[4] = Expression(trajLines[4]);
00669                     v[5] = Expression(trajLines[5]);
00670                     v[6] = Expression(trajLines[6]);
00671                   }
00672                   else {
00673                     v[3] = Expression(trajLines[6]);
00674                     v[4] = Expression(trajLines[3]);
00675                     v[5] = Expression(trajLines[4]);
00676                     v[6] = Expression(trajLines[5]);
00677                   }
00678                   v[7] = Expression(trajLines[7]);
00679                 }
00680                 else {
00681                   if (trajLines.size() != 7)
00682                     throw externalization_error(Exception("trajectory should have one line for each parametric expression x(s), y(s), z(s), R(s), P(s), Y(s) and t(s)"));
00683                   v.resize(7);
00684                   v[0] = Expression(trajLines[0]);
00685                   v[1] = Expression(trajLines[1]);
00686                   v[2] = Expression(trajLines[2]);
00687                   v[3] = Expression(trajLines[3]);
00688                   v[4] = Expression(trajLines[4]);
00689                   v[5] = Expression(trajLines[5]);
00690                   v[6] = Expression(trajLines[6]);
00691                 }
00692               }
00693             } catch (std::exception& e) {
00694               throw externalization_error(Exception("error parsing parametric trajectory component expression:"+String(e.what())));
00695             }
00696 
00697             ref<ParametricTrajectoryRep> prep;
00698             try {
00699               prep = ref<ParametricTrajectoryRep>(NewObj ParametricTrajectoryRep(v));
00700             } catch (std::exception& e) {
00701               throw externalization_error(Exception("error creating parametric trajectory:"+String(e.what())));
00702             }
00703             this->rep = prep;
00704             this->trep = prep;
00705 
00706           } // else parametric
00707           
00708         }
00709 
00710         e.removeElement(trajElem);
00711 
00712       }
00713       else { // !trajElem 
00714 
00715         DOMElement* pathElem = e.getFirstElement(context, "path", false);
00716 
00717         if (pathElem) {
00718 
00719           // In general, to use a Path as a Trajectory without knowing its representation,
00720           //  we just sample the path and use the sample points while adding a default
00721           //  time interval of [0..1]
00722           // However, we handle some special cases of known representations explicitly
00723           
00724           // First, load the Path
00725           Path path;
00726           path.externalize(e, format, version);
00727 
00728           frame = path.getCoordFrame();
00729           units = path.getUnits();
00730 
00731           // check for parametric representation
00732           if (instanceof(*path.rep, ParametricPathRep)) { // use the PathRep directly
00733             
00734             ref<ParametricPathRep> ppathrep( narrow_ref<ParametricPathRep>(path.rep) );
00735             
00736             ExpressionVector v( ppathrep->v.size()+1 ); // make room for times Expression and copy other elements over
00737             for(Int i=0; i<ppathrep->v.size(); i++) v[i] = ppathrep->v[i];
00738             v[v.size()-1] = Expression::p[0]; // i.e. t = s
00739 
00740             ref<ParametricTrajectoryRep> prep;
00741             try {
00742               prep = ref<ParametricTrajectoryRep>(NewObj ParametricTrajectoryRep(v));
00743             } catch (std::exception& e) {
00744               throw externalization_error(Exception("error creating parametric trajectory from path:"+String(e.what())));
00745             }
00746 
00747             this->rep = prep;
00748             this->trep = prep;
00749 
00750           }
00751           else { // general case, Resample and use Path's distinguished points.
00752 
00753             // Resample and use it's distinguished points.  Times will default to [0..1]
00754             array<Point3> points;
00755             array<Orient> orients;
00756             array<Time> times;
00757   
00758             for(Int i=0; i<path.numDistinguishedValues(); i++) {
00759               Real s = path.distinguishedValue(i);
00760               points.push_back(path.position(s));
00761               orients.push_back(path.orientation(s));
00762               times.push_back( Time( Real(i)/Real(path.numDistinguishedValues()-1) ) );
00763             }
00764   
00765             init(points,orients,times,false);
00766           }
00767           
00768         }
00769         else
00770           throw externalization_error(Exception("either <trajectory> or <path> expected"));
00771 
00772       }
00773 
00774     }
00775 
00776   } // format xml
00777   
00778 }
00779 
00780 

Generated on Thu Jul 29 15:56:15 2004 for OpenSim by doxygen 1.3.6