diff --git a/OpenRoadEd/OpenDrive/OpenDriveXmlParser.cpp b/OpenRoadEd/OpenDrive/OpenDriveXmlParser.cpp
index b3785a28b070163cc79b58bb8b1108e59b96aa00..cf93e24ff6def359c0a73dd85102a8e1c8dc7b7e 100644
--- a/OpenRoadEd/OpenDrive/OpenDriveXmlParser.cpp
+++ b/OpenRoadEd/OpenDrive/OpenDriveXmlParser.cpp
@@ -333,6 +333,11 @@ bool OpenDriveXmlParser::ReadPlanView(Road* road, TiXmlElement *node)
 		{
 			ReadGeometryBlock(road, subNode,2);		//load a polynom spline block
 		}
+		else if (subNodeType->ValueStr().compare("paramPoly3")==0)
+		{
+			ReadGeometryBlock(road, subNode,3);		//load a polynom spline block
+		}
+ 
     else  
       cout<<"Unsupported geometry type for road " << road->GetRoadName() << ": " << subNodeType->ValueStr() << endl;
 			
@@ -363,6 +368,9 @@ bool OpenDriveXmlParser::ReadGeometryBlock (Road* road, TiXmlElement *&node, sho
 	case 2:
 		ReadGeometry(geomBlock, node, 3);
 		break;
+	case 3:
+		ReadGeometry(geomBlock, node, 4);
+		break;
 	}
 
 	return true;
@@ -420,7 +428,7 @@ bool OpenDriveXmlParser::ReadGeometry(GeometryBlock* geomBlock, TiXmlElement *no
 		break;
 
 
-	case 3:		//poly3
+  case 3:		//poly3
 		checker=TIXML_SUCCESS;
 		double a,b,c,d;
 		checker+=subNode->QueryDoubleAttribute("a",&a);
@@ -429,12 +437,34 @@ bool OpenDriveXmlParser::ReadGeometry(GeometryBlock* geomBlock, TiXmlElement *no
 		checker+=subNode->QueryDoubleAttribute("d",&d);
 		if (checker!=TIXML_SUCCESS)
 		{
-			cout<<"Error parsing arc attributes"<<endl;
+			cout<<"Error parsing poly3 attributes"<<endl;
 			return false;
 		}
 
 		geomBlock->AddGeometryPoly3(s,x,y,hdg,length,a,b,c,d);
 		break;
+
+  case 4:		//parampoly3
+		checker=TIXML_SUCCESS;
+		double au,bu,cu,du;
+		double av,bv,cv,dv;
+		checker+=subNode->QueryDoubleAttribute("aU",&au);
+		checker+=subNode->QueryDoubleAttribute("bU",&bu);
+		checker+=subNode->QueryDoubleAttribute("cU",&cu);
+		checker+=subNode->QueryDoubleAttribute("dU",&du);
+		checker+=subNode->QueryDoubleAttribute("aV",&av);
+		checker+=subNode->QueryDoubleAttribute("bV",&bv);
+		checker+=subNode->QueryDoubleAttribute("cV",&cv);
+		checker+=subNode->QueryDoubleAttribute("dV",&dv);
+		if (checker!=TIXML_SUCCESS)
+		{
+			cout<<"Error parsing paramPoly3 attributes"<<endl;
+			return false;
+		}
+
+		geomBlock->AddGeometryParamPoly3(s,x,y,hdg,length,au,bu,cu,du,av,bv,cv,dv);
+		break;
+
 	}
 
 	return true;
diff --git a/OpenRoadEd/OpenDrive/OpenDriveXmlWriter.cpp b/OpenRoadEd/OpenDrive/OpenDriveXmlWriter.cpp
index e6fbb959920f176f30536d4c8e9e9defb381c961..34e2ebdd0d2def8a37804a2ca48ddc90b559da22 100644
--- a/OpenRoadEd/OpenDrive/OpenDriveXmlWriter.cpp
+++ b/OpenRoadEd/OpenDrive/OpenDriveXmlWriter.cpp
@@ -220,6 +220,14 @@ bool OpenDriveXmlWriter::WriteGeometryBlock (TiXmlElement *node, GeometryBlock*
 	{
 		WriteGeometry(node, geometryBlock->GetGeometryAt(0), 0);
 	}
+  else if(geometryBlock->CheckIfPoly3())
+  {
+		WriteGeometry(node, geometryBlock->GetGeometryAt(0), 3);
+  }
+  else if(geometryBlock->CheckIfParamPoly3())
+  {
+		WriteGeometry(node, geometryBlock->GetGeometryAt(0), 4);
+  } 
 	else
 	{
 		WriteGeometry(node, geometryBlock->GetGeometryAt(0), 1);
@@ -315,8 +323,58 @@ bool OpenDriveXmlWriter::WriteGeometry(TiXmlElement *node, RoadGeometry* roadGeo
 	case 3:
 		{		
 			//poly3
+			GeometryPoly3 *lPoly3=static_cast<GeometryPoly3*>(roadGeometry);
+			TiXmlElement *nodePoly3 = new TiXmlElement("poly3");
+			nodeGeometry->LinkEndChild(nodePoly3);
+			std::stringstream svalue;
+			svalue << setprecision(16) << setiosflags (ios_base::scientific) << lPoly3->GetA();
+			nodePoly3->SetAttribute("a",svalue.str());
+      svalue.str("");
+			svalue << setprecision(16) << setiosflags (ios_base::scientific) << lPoly3->GetB();
+			nodePoly3->SetAttribute("b",svalue.str());
+      svalue.str("");
+			svalue << setprecision(16) << setiosflags (ios_base::scientific) << lPoly3->GetC();
+			nodePoly3->SetAttribute("c",svalue.str());
+      svalue.str("");
+			svalue << setprecision(16) << setiosflags (ios_base::scientific) << lPoly3->GetD();
+			nodePoly3->SetAttribute("d",svalue.str());
+      svalue.str("");
 			break;
 		}
+	case 4:
+		{		
+			//param poly3
+			GeometryParamPoly3 *lParamPoly3=static_cast<GeometryParamPoly3*>(roadGeometry);
+			TiXmlElement *nodeParamPoly3 = new TiXmlElement("paramPoly3");
+			nodeGeometry->LinkEndChild(nodeParamPoly3);
+			std::stringstream svalue;
+			svalue << setprecision(16) << setiosflags (ios_base::scientific) << lParamPoly3->GetAu();
+			nodeParamPoly3->SetAttribute("aU",svalue.str());
+      svalue.str("");
+			svalue << setprecision(16) << setiosflags (ios_base::scientific) << lParamPoly3->GetBu();
+			nodeParamPoly3->SetAttribute("bU",svalue.str());
+      svalue.str("");
+			svalue << setprecision(16) << setiosflags (ios_base::scientific) << lParamPoly3->GetCu();
+			nodeParamPoly3->SetAttribute("cU",svalue.str());
+      svalue.str("");
+			svalue << setprecision(16) << setiosflags (ios_base::scientific) << lParamPoly3->GetDu();
+			nodeParamPoly3->SetAttribute("dU",svalue.str());
+      svalue.str("");
+ 			svalue << setprecision(16) << setiosflags (ios_base::scientific) << lParamPoly3->GetAv();
+			nodeParamPoly3->SetAttribute("aV",svalue.str());
+      svalue.str("");
+			svalue << setprecision(16) << setiosflags (ios_base::scientific) << lParamPoly3->GetBv();
+			nodeParamPoly3->SetAttribute("bV",svalue.str());
+      svalue.str("");
+			svalue << setprecision(16) << setiosflags (ios_base::scientific) << lParamPoly3->GetCv();
+			nodeParamPoly3->SetAttribute("cV",svalue.str());
+      svalue.str("");
+			svalue << setprecision(16) << setiosflags (ios_base::scientific) << lParamPoly3->GetDv();
+			nodeParamPoly3->SetAttribute("dV",svalue.str());
+      svalue.str("");      
+			break;
+		}
+
 	}
 
 	return true;
diff --git a/OpenRoadEd/OpenDrive/RoadGeometry.cpp b/OpenRoadEd/OpenDrive/RoadGeometry.cpp
index bfffe48d4286cc170de18329db5f961876aba79f..90e0fca82fc3a8cc8bd3da87ee8b208afe807deb 100644
--- a/OpenRoadEd/OpenDrive/RoadGeometry.cpp
+++ b/OpenRoadEd/OpenDrive/RoadGeometry.cpp
@@ -1,6 +1,7 @@
 #include "RoadGeometry.h"
 #define _USE_MATH_DEFINES
 #include <math.h>
+#include <iostream>
 
 //#define PI 3.14159265358979323846264338327950288
 extern int fresnl( double , double *, double * );
@@ -481,6 +482,151 @@ void GeometrySpiral::GetCoords(double s_check, double &retX, double &retY, doubl
 	retY=mY+ tmpY*mRotCos+tmpX*mRotSin;
 }
 
+//***********************************************************************************
+//ParamPoly3 geometry
+//***********************************************************************************
+/**
+ * Constructor that initializes the base properties of the record
+ */
+GeometryParamPoly3::GeometryParamPoly3 (double s, double x, double y, double hdg, double length,double au,double bu,double cu,double du, double av, double bv, double cv, double dv):	RoadGeometry(s, x, y, hdg, length)
+{
+	SetGeomType(4);
+  mAu=au;
+  mBu=bu;
+  mCu=cu;
+  mDu=du;
+  mAv=av;
+  mBv=bv;
+  mCv=cv;
+  mDv=dv;
+	ComputeVars();
+}
+
+/**
+ * Computes the required vars
+ */
+void GeometryParamPoly3::ComputeVars()
+{
+}
+
+/**
+ * Clones and returns the new geometry record
+ */
+RoadGeometry* GeometryParamPoly3::Clone() const
+{
+	GeometryParamPoly3* ret=new GeometryParamPoly3(mS,mX,mY, mHdg, mLength,mAu,mBu,mCu,mDu,mAv,mBv,mCv,mDv);
+	return ret;
+}
+
+
+//-------------------------------------------------
+
+/**
+ * Setter for the base properties
+ */
+void GeometryParamPoly3::SetAll(double s, double x, double y, double hdg, double length,double au,double bu,double cu,double du, double av, double bv, double cv, double dv)
+{
+	SetBase(s,x,y,hdg,length,false);
+  mAu=au;
+  mBu=bu;
+  mCu=cu;
+  mDu=du;
+  mAv=av;
+  mBv=bv;
+  mCv=cv;
+  mDv=dv;
+	ComputeVars();
+}
+
+//-------------------------------------------------
+
+/**
+ * Getter for the base properties
+ */
+double GeometryParamPoly3::GetAu(void)
+{
+  return mAu;
+}
+double GeometryParamPoly3::GetBu(void)
+{
+  return mBu;
+}
+double GeometryParamPoly3::GetCu(void)
+{
+  return mCu;
+}
+double GeometryParamPoly3::GetDu(void)
+{
+  return mDu;
+}
+double GeometryParamPoly3::GetAv(void)
+{
+  return mAv;
+}
+double GeometryParamPoly3::GetBv(void)
+{
+  return mBv;
+}
+double GeometryParamPoly3::GetCv(void)
+{
+  return mCv;
+}
+double GeometryParamPoly3::GetDv(void)
+{
+  return mDv;
+}
+//-------------------------------------------------
+/**
+ * Gets the coordinates at the sample S offset
+ */
+void GeometryParamPoly3::GetCoords(double s_check, double &retX, double &retY)
+{
+  double param=s_check/mLength;
+  double sX,sY;
+
+  sX=mAu+mBu*param+mCu*pow(param,2.0)+mDu*pow(param,3.0);
+  sY=mAv+mBv*param+mCv*pow(param,2.0)+mDv*pow(param,3.0);
+
+  retX=mX+sX*cos(mHdg)-sY*sin(mHdg);
+  retY=mY+sX*sin(mHdg)+sY*cos(mHdg);
+}
+
+void GeometryParamPoly3::GetCoords(double s_check, double &retX, double &retY, double &retHDG)
+{
+  double param=s_check/mLength;
+  double diff_sX,diff_sY;
+  double s1X,s1Y,s2X,s2Y;
+
+  GetCoords(s_check,retX,retY);
+
+  diff_sX=mBu+2.0*mCu*param+3*mDu*pow(param,2.0);
+  diff_sY=mBv+2.0*mCv*param+3*mDv*pow(param,2.0);
+ 
+  if(s_check==0)
+  { 
+    s1X=mAu;
+    s1Y=mAv;
+    s2X=mAu+mBu*(param+0.02)+mCu*pow(param+0.02,2.0)+mDu*pow(param+0.02,3.0);
+    s2Y=mAv+mBv*(param+0.02)+mCv*pow(param+0.02,2.0)+mDv*pow(param+0.02,3.0);
+  }
+  else if(s_check==mLength)
+  {
+    s1X=mAu+mBu*(param-0.02)+mCu*pow(param-0.02,2.0)+mDu*pow(param-0.02,3.0);
+    s1Y=mAv+mBv*(param-0.02)+mCv*pow(param-0.02,2.0)+mDv*pow(param-0.02,3.0);
+    s2X=mAu+mBu*param+mCu*pow(param,2.0)+mDu*pow(param,3.0);
+    s2Y=mAv+mBv*param+mCv*pow(param,2.0)+mDv*pow(param,3.0);
+  }
+  else
+  {
+    s1X=mAu+mBu*(param-0.01)+mCu*pow(param-0.01,2.0)+mDu*pow(param-0.01,3.0);
+    s1Y=mAv+mBv*(param-0.01)+mCv*pow(param-0.01,2.0)+mDv*pow(param-0.01,3.0);
+    s2X=mAu+mBu*(param+0.01)+mCu*pow(param+0.01,2.0)+mDu*pow(param+0.01,3.0);
+    s2Y=mAv+mBv*(param+0.01)+mCv*pow(param+0.01,2.0)+mDv*pow(param+0.01,3.0);
+  }
+  retHDG=mHdg+(s2Y-s1Y)/(s2X-s1X);
+  std::cout << "param: " << param << " heading: " << retHDG << std::endl;
+}
+
 
 
 
@@ -519,6 +665,25 @@ void GeometryPoly3::SetAll(double s, double x, double y, double hdg, double leng
 	ComputeVars();
 }
 
+/**
+ * Getter for the base properties
+ */
+double GeometryPoly3::GetA(void)
+{
+  return mA;
+}
+double GeometryPoly3::GetB(void)
+{
+  return mB;
+}
+double GeometryPoly3::GetC(void)
+{
+  return mC;
+}
+double GeometryPoly3::GetD(void)
+{
+  return mD;
+}
 
 
 
@@ -567,6 +732,10 @@ const GeometryBlock& GeometryBlock::operator=(const GeometryBlock& otherGeomBloc
 			{
 				delete poly;
 			}
+			else if(GeometryParamPoly3 *paramPoly = dynamic_cast<GeometryParamPoly3 *>(*member))
+			{
+				delete paramPoly;
+			}
 		}
 		mGeometryBlockElement.clear();
 
@@ -598,6 +767,10 @@ void GeometryBlock::AddGeometryPoly3(double s, double x, double y, double hdg, d
 {	
 	mGeometryBlockElement.push_back(new GeometryPoly3(s, x, y, hdg, length, a, b, c, d));	
 }
+void GeometryBlock::AddGeometryParamPoly3(double s, double x, double y, double hdg, double length, double au,double bu,double cu,double du,double av,double bv,double cv,double dv)
+{	
+	mGeometryBlockElement.push_back(new GeometryParamPoly3(s, x, y, hdg, length, au, bu, cu, du,av,bv,cv,dv));	
+}
 
 //-------------------------------------------------
 
@@ -627,8 +800,47 @@ double GeometryBlock::GetBlockLength()
  */
 bool GeometryBlock::CheckIfLine()
 {
+  int type;
+
+	if(mGeometryBlockElement.size()>1) return false;
+	else
+  {
+    type=mGeometryBlockElement.at(0)->GetGeomType();
+    if(type==0)
+      return true;
+    else
+      return false;
+  }
+}
+
+bool GeometryBlock::CheckIfParamPoly3()
+{
+  int type;
+
+	if(mGeometryBlockElement.size()>1) return false;
+	else
+  {
+    type=mGeometryBlockElement.at(0)->GetGeomType();
+    if(type==4)
+      return true;
+    else
+      return false;
+  }
+}
+
+bool GeometryBlock::CheckIfPoly3()
+{
+  int type;
+
 	if(mGeometryBlockElement.size()>1) return false;
-	else return true;
+	else
+  {
+    type=mGeometryBlockElement.at(0)->GetGeomType();
+    if(type==3)
+      return true;
+    else
+      return false;
+  }
 }
 
 //-------------------------------------------------
@@ -643,15 +855,38 @@ void GeometryBlock::Recalculate(double s, double x, double y, double hdg)
 	double lX=x;
 	double lY=y;
 	double lHdg=hdg;
+  int type;
 
 	if(mGeometryBlockElement.size()==1)
 	{
-		GeometryLine *lGeometryLine	=  static_cast<GeometryLine*>(mGeometryBlockElement.at(0));
-		if(lGeometryLine!=NULL)
-		{
-			// Updates the line to reflect the changes of the previous block
-			lGeometryLine->SetBase(lS,lX,lY,lHdg,lGeometryLine->GetLength());
-		}
+    type=mGeometryBlockElement.at(0)->GetGeomType();
+    if(type==0)
+    {
+  		GeometryLine *lGeometryLine	=  static_cast<GeometryLine*>(mGeometryBlockElement.at(0));
+	  	if(lGeometryLine!=NULL)
+		  {
+			  // Updates the line to reflect the changes of the previous block
+  			lGeometryLine->SetBase(lS,lX,lY,lHdg,lGeometryLine->GetLength());
+	  	}
+    }
+    else if(type==3)
+    {
+  		GeometryPoly3 *lGeometryPoly3	=  static_cast<GeometryPoly3*>(mGeometryBlockElement.at(0));
+	  	if(lGeometryPoly3!=NULL)
+		  {
+			  // Updates the line to reflect the changes of the previous block
+  			lGeometryPoly3->SetBase(lS,lX,lY,lHdg,lGeometryPoly3->GetLength());
+	  	}
+    }
+    else if(type==4)
+    {
+  		GeometryParamPoly3 *lGeometryParamPoly3	=  static_cast<GeometryParamPoly3*>(mGeometryBlockElement.at(0));
+	  	if(lGeometryParamPoly3!=NULL)
+		  {
+			  // Updates the line to reflect the changes of the previous block
+  			lGeometryParamPoly3->SetBase(lS,lX,lY,lHdg,lGeometryParamPoly3->GetLength());
+	  	}
+    }
 	}
 	else if(mGeometryBlockElement.size()==3)
 	{
@@ -792,6 +1027,10 @@ GeometryBlock::~GeometryBlock()
 		{
 			delete poly;
 		}
+		else if(GeometryParamPoly3 *paramPoly = dynamic_cast<GeometryParamPoly3 *>(*member))
+		{
+			delete paramPoly;
+		}
 	}
 	mGeometryBlockElement.clear();
 }
diff --git a/OpenRoadEd/OpenDrive/RoadGeometry.h b/OpenRoadEd/OpenDrive/RoadGeometry.h
index 52983c75bb41eef3d5e30fa19532603130dd2ed5..df5db79f83e46e2f1276cebe4f794a4fd74502a9 100644
--- a/OpenRoadEd/OpenDrive/RoadGeometry.h
+++ b/OpenRoadEd/OpenDrive/RoadGeometry.h
@@ -46,7 +46,7 @@ public:
 
 	/**
 	 * Sets the type of the geometry
-	 * 0: Line, 1: Arc, 2: Spiral
+	 * 0: Line, 1: Arc, 2: Spiral 3: poly3 4: paramPloy3
 	 */
 	void SetGeomType(short int geomType);
 	
@@ -261,6 +261,77 @@ protected:
 	virtual void ComputeVars();
 };
 
+//----------------------------------------------------------------------------------
+/**
+ * GeometryParamPoly3 inherits the RoadGeometry class and adds parametric properties
+ *
+ */
+class GeometryParamPoly3: public RoadGeometry
+{
+private:
+	/**
+	 * Base record properties
+	 */
+	double mAu;
+	double mBu;
+	double mCu;
+	double mDu;
+	double mAv;
+	double mBv;
+	double mCv;
+	double mDv;
+
+	/**
+	 * Computation variables
+	 */
+	double mEndX;
+	double mEndY;
+
+public:
+	/**
+	 * Constructor that initializes the base properties of the record
+	 */
+	GeometryParamPoly3 (double s, double x, double y, double hdg, double length, double au,double bu,double cu,double du,double av,double bv,double cv,double dv);
+
+	/**
+	 * Clones and returns the new geometry record
+	 */
+	RoadGeometry* Clone() const;
+
+	//-------------------------------------------------
+
+	/**
+	 * Setter for the base properties
+	 */
+	void SetAll(double s, double x, double y, double hdg, double length,double au,double bu,double cu,double du,double av,double bv,double cv,double dv);
+	
+	//-------------------------------------------------
+	/**
+	 * Getter for the base properties
+	 */
+  double GetAu(void);
+  double GetBu(void);
+  double GetCu(void);
+  double GetDu(void);
+  double GetAv(void);
+  double GetBv(void);
+  double GetCv(void);
+  double GetDv(void);
+	
+	//-------------------------------------------------
+	/**
+	 * Gets the coordinates at the sample S offset
+	 */
+	void GetCoords(double s_check, double &retX, double &retY, double &retHDG);
+	void GetCoords(double s_check, double &retX, double &retY);
+protected:
+
+	/**
+	 * Computes the required vars
+	 */
+	virtual void ComputeVars();
+};
+
 
 //----------------------------------------------------------------------------------
 /**
@@ -294,10 +365,17 @@ public:
 	 */
 	void SetAll(double s, double x, double y, double hdg, double length, double a,double b,double c,double d);
 
+	//-------------------------------------------------
+	/**
+	 * Getter for the base properties
+	 */
+  double GetA(void);
+  double GetB(void);
+  double GetC(void);
+  double GetD(void);
 };
 
 
-
 //----------------------------------------------------------------------------------
 /**
  * GeometryBlock is a class used to combine multiple geometry records into blocks.
@@ -337,6 +415,7 @@ public:
 	void AddGeometryArc(double s, double x, double y, double hdg, double length, double curvature);
 	void AddGeometrySpiral(double s, double x, double y, double hdg, double length, double curvatureStart,double curvatureEnd);
 	void AddGeometryPoly3(double s, double x, double y, double hdg, double length, double a,double b,double c,double d);
+	void AddGeometryParamPoly3(double s, double x, double y, double hdg, double length, double au,double bu,double cu,double du,double av,double bv,double cv,double dv);
 	
 	//-------------------------------------------------
 
@@ -354,6 +433,8 @@ public:
 	 *  Checks if the block is a straight line block or a turn
 	 */
 	bool CheckIfLine();
+	bool CheckIfPoly3();
+	bool CheckIfParamPoly3();
 	
 	//-------------------------------------------------
 
diff --git a/OpenRoadEd/Osg/OSGRoad.cpp b/OpenRoadEd/Osg/OSGRoad.cpp
index dd009eb6350447a9974678a423f6551cd181ddb9..31c54ed219ddf0177fb4ccc18b020ea94447c0bc 100644
--- a/OpenRoadEd/Osg/OSGRoad.cpp
+++ b/OpenRoadEd/Osg/OSGRoad.cpp
@@ -334,7 +334,7 @@ void OSGRoad::CreateRoadGeometry (vector<osg::ref_ptr<osg::Geometry>> &geometrie
 								  short int alphaDepthState)
 {
 
-
+  std::cout << "road ID: " << road->GetRoadId() << std::endl;
 	//================================================================
 	//Check if everything needed for the road generation exists
 	//================================================================