diff --git a/CMakeLists.txt b/CMakeLists.txt
index b3beddcb57454472c4f278701a5db658da2e4ae9..9ec32eefac1059a24af1a451a0352f80f51d4e83 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -85,7 +85,9 @@ SET(SOURCES
     src/navigation.cpp
     src/snapshot.cpp
     src/tdcp.cpp
-    src/ublox_raw.cpp)
+    src/receiver_raw_base.cpp
+    src/receivers/ublox_raw.cpp
+    src/receivers/novatel_raw.cpp)
 
 SET(RTKLIB_SRC
     ${RTKLIB_SRC_DIR}/pntpos.c
diff --git a/deps/RTKLIB b/deps/RTKLIB
index afa374367da135226a3995b7ede987456884e6c8..6ecf8cf16c00fbcf317129a036ba2203b0a85461 160000
--- a/deps/RTKLIB
+++ b/deps/RTKLIB
@@ -1 +1 @@
-Subproject commit afa374367da135226a3995b7ede987456884e6c8
+Subproject commit 6ecf8cf16c00fbcf317129a036ba2203b0a85461
diff --git a/include/gnss_utils/receiver_raw_base.h b/include/gnss_utils/receiver_raw_base.h
new file mode 100644
index 0000000000000000000000000000000000000000..651a38ca73d229ee82afa0bf62f0e706d33a5448
--- /dev/null
+++ b/include/gnss_utils/receiver_raw_base.h
@@ -0,0 +1,75 @@
+#ifndef INCLUDE_GNSS_UTILS_RECEIVER_RAW_BASE_H_
+#define INCLUDE_GNSS_UTILS_RECEIVER_RAW_BASE_H_
+
+#include "gnss_utils/observations.h"
+#include "gnss_utils/navigation.h"
+
+namespace GnssUtils
+{
+enum RawDataType : int
+{
+  NO             = 0,
+  OBS            = 1,
+  NAV_EPH        = 2,
+  NAV_SBAS       = 3,
+  NAV_ALM_IONUTC = 9,
+  NAV_ANT        = 5,
+  NAV_DGPS       = 7,
+  NAV_SSR        = 10,
+  NAV_LEX        = 31,
+  ERROR          = -1
+};
+
+class ReceiverRawAbstract
+{
+public:
+  ReceiverRawAbstract();
+  ~ReceiverRawAbstract();
+
+  virtual RawDataType addDataStream(const std::vector<uint8_t>& data_stream) = 0;
+
+  const Observations& getObservations() const;
+  const Navigation&   getNavigation() const;
+
+  Observations getObservations();
+  Navigation   getNavigation();
+
+  RawDataType getRawDataType() const;
+
+protected:
+  void updateObservations();
+
+  raw_t       raw_data_;
+  RawDataType raw_data_type_;
+
+  Observations obs_;
+  Navigation   nav_;
+};
+
+inline const Observations& ReceiverRawAbstract::getObservations() const
+{
+  return obs_;
+}
+
+inline Observations ReceiverRawAbstract::getObservations()
+{
+  return obs_;
+}
+
+inline const Navigation& ReceiverRawAbstract::getNavigation() const
+{
+  return nav_;
+}
+
+inline Navigation ReceiverRawAbstract::getNavigation()
+{
+  return nav_;
+}
+
+inline RawDataType ReceiverRawAbstract::getRawDataType() const
+{
+  return raw_data_type_;
+}
+
+}  // namespace GnssUtils
+#endif
diff --git a/include/gnss_utils/receivers/novatel_raw.h b/include/gnss_utils/receivers/novatel_raw.h
new file mode 100644
index 0000000000000000000000000000000000000000..5362ef28d3f2893b0f10276e32a05cf60de11b42
--- /dev/null
+++ b/include/gnss_utils/receivers/novatel_raw.h
@@ -0,0 +1,18 @@
+#ifndef INCLUDE_GNSS_UTILS_NOVATEL_RAW_H_
+#define INCLUDE_GNSS_UTILS_NOVATEL_RAW_H_
+
+#include "gnss_utils/receiver_raw_base.h"
+
+namespace GnssUtils
+{
+class NovatelRaw : public ReceiverRawAbstract
+{
+public:
+  NovatelRaw();
+  ~NovatelRaw();
+
+  RawDataType addDataStream(const std::vector<uint8_t>& data_stream);
+};
+} // namespace GnssUtils
+
+#endif
\ No newline at end of file
diff --git a/include/gnss_utils/receivers/ublox_raw.h b/include/gnss_utils/receivers/ublox_raw.h
new file mode 100644
index 0000000000000000000000000000000000000000..a1ba0c6a5f0ffc0849e8eb29b85080403e788a4f
--- /dev/null
+++ b/include/gnss_utils/receivers/ublox_raw.h
@@ -0,0 +1,22 @@
+#ifndef INCLUDE_GNSS_UTILS_UBLOX_RAW_H_
+#define INCLUDE_GNSS_UTILS_UBLOX_RAW_H_
+
+#include "gnss_utils/receiver_raw_base.h"
+
+namespace GnssUtils
+{
+class UBloxRaw : public ReceiverRawAbstract
+{
+public:
+  UBloxRaw();
+  ~UBloxRaw();
+
+  RawDataType addDataStream(const std::vector<uint8_t>& data_stream);
+
+private:
+
+};
+
+}  // namespace GnssUtils
+
+#endif  // INCLUDE_GNSS_UTILS_UBLOX_RAW_H_
diff --git a/include/gnss_utils/ublox_raw.h b/include/gnss_utils/ublox_raw.h
deleted file mode 100644
index f03bb73188d98b53f011b72e0cd1dd6932e76b70..0000000000000000000000000000000000000000
--- a/include/gnss_utils/ublox_raw.h
+++ /dev/null
@@ -1,64 +0,0 @@
-#ifndef INCLUDE_GNSS_UTILS_UBLOX_RAW_H_
-#define INCLUDE_GNSS_UTILS_UBLOX_RAW_H_
-
-#include "gnss_utils/observations.h"
-#include "gnss_utils/navigation.h"
-
-namespace GnssUtils
-{
-enum RawDataType : int
-{
-  NO       = 0,
-  OBS      = 1,
-  NAV_EPH  = 2,
-  NAV_SBAS = 3,
-  NAV_ALM  = 9,
-  NAV_ANT  = 5,
-  NAV_DGPS = 7,
-  NAV_SSR  = 10,
-  NAV_LEX  = 31,
-  ERROR    = -1
-};
-
-class UBloxRaw
-{
-public:
-  UBloxRaw();
-  ~UBloxRaw();
-
-  RawDataType addDataStream(const std::vector<u_int8_t>& data_stream);
-
-  const Observations& getObservations();
-  const Navigation&   getNavigation();
-
-  RawDataType getRawDataType() const;
-
-private:
-  raw_t raw_data_;
-
-  Observations obs_;
-  Navigation   nav_;
-
-  RawDataType raw_data_type_;
-
-  void updateObservations();
-};
-
-inline const Observations& UBloxRaw::getObservations()
-{
-  return obs_;
-}
-
-inline const Navigation& UBloxRaw::getNavigation()
-{
-  return nav_;
-}
-
-inline RawDataType UBloxRaw::getRawDataType() const
-{
-  return raw_data_type_;
-}
-
-}  // namespace GnssUtils
-
-#endif  // INCLUDE_GNSS_UTILS_UBLOX_RAW_H_
diff --git a/include/gnss_utils/utils/rcv_position.h b/include/gnss_utils/utils/rcv_position.h
index 00ea4990e58e3b7f60a1b555004e01e068945c31..9ac529ce72cf96f98344dd16da856a2e9ff76fff 100644
--- a/include/gnss_utils/utils/rcv_position.h
+++ b/include/gnss_utils/utils/rcv_position.h
@@ -20,7 +20,7 @@
 namespace GnssUtils
 {
 
-ComputePosOutput computePos(const Observations& _observations, Navigation& _navigation, const prcopt_t& _prcopt);
+ComputePosOutput computePos(const Observations& _observations, const Navigation& _navigation, const prcopt_t& _prcopt);
 
 // ComputePosOutput computePosOwn(const Observations & _observations,
 //                                Navigation & _navigation,
diff --git a/src/receiver_raw_base.cpp b/src/receiver_raw_base.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ea6e3b5e87b04f20a378158ceca59bf50c7d7f66
--- /dev/null
+++ b/src/receiver_raw_base.cpp
@@ -0,0 +1,29 @@
+#include "gnss_utils/receiver_raw_base.h"
+
+namespace GnssUtils
+{
+ReceiverRawAbstract::ReceiverRawAbstract() : raw_data_type_(NO)
+{
+  if (init_raw(&raw_data_, STRFMT_UBX) == 0)
+  {
+    assert("Failed when allocating memory for raw_t");
+    return;
+  }
+}
+
+ReceiverRawAbstract::~ReceiverRawAbstract()
+{
+  free_raw(&raw_data_);
+}
+
+void ReceiverRawAbstract::updateObservations()
+{
+  // sort and remove duplicated observations
+  sortobs(&raw_data_.obs);
+
+  obs_.clearObservations();
+  for (int ii = 0; ii < raw_data_.obs.n; ++ii)
+    obs_.addObservation(raw_data_.obs.data[ii]);
+}
+
+}  // namespace GnssUtils
\ No newline at end of file
diff --git a/src/receivers/novatel_raw.cpp b/src/receivers/novatel_raw.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..21487f72d97b1321427865097faf352a608dc0da
--- /dev/null
+++ b/src/receivers/novatel_raw.cpp
@@ -0,0 +1,67 @@
+#include "gnss_utils/receivers/novatel_raw.h"
+
+using namespace GnssUtils;
+
+NovatelRaw::NovatelRaw()
+{
+}
+
+NovatelRaw::~NovatelRaw()
+{
+}
+
+RawDataType NovatelRaw::addDataStream(const std::vector<uint8_t>& data_stream)
+{
+ 
+ for (auto data_byte = data_stream.begin(); data_byte != data_stream.end(); ++data_byte)
+  {
+    raw_data_type_ = input_oem4(&raw_data_, (unsigned char)*data_byte);
+
+    switch (raw_data_type_)
+    {
+      case NO:  //
+        // std::cout << "0 received!\n";
+        break;
+
+      case OBS:  // Observations
+        std::cout << "Observations Novatel received!\n";
+        updateObservations();
+        break;
+
+      case NAV_EPH:  // Ephemeris
+        std::cout << "Ephemeris received!\n";
+        nav_.copyEphemeris(raw_data_.nav);
+        nav_.uniqueNavigation();
+        break;
+
+      case NAV_SBAS:  // SBAS
+        std::cout << "SBAS received!\n";
+        break;
+
+      case NAV_ALM_IONUTC:  // Almanac and ion/utc parameters
+        std::cout << "Almanac and ion/utc parameters received!\n";
+        nav_.copyIonUtc(raw_data_.nav);
+        break;
+
+      // Not handled messages
+      case NAV_ANT:
+        std::cout << "NovatelRaw: Received antenna postion parameters. Not handled.\n";
+        break;
+      case NAV_DGPS:
+        std::cout << "NovatelRaw: Received dgps correction. Not handled.\n";
+        break;
+      case NAV_SSR:
+        std::cout << "NovatelRaw: Received ssr message. Not handled.\n";
+        break;
+      case NAV_LEX:
+        std::cout << "NovatelRaw: Received lex message. Not handled.\n";
+        break;
+      case ERROR:
+        std::cout << "NovatelRaw: Received error message. Not handled.\n";
+        break;
+      default:
+        std::cout << "NovatelRaw: Received unknown message. Not handled.\n";
+        break;
+    }
+  }
+}
\ No newline at end of file
diff --git a/src/ublox_raw.cpp b/src/receivers/ublox_raw.cpp
similarity index 64%
rename from src/ublox_raw.cpp
rename to src/receivers/ublox_raw.cpp
index 7c12df5f841df9fa312dd20bc02e94af93c80e5e..0d17bae737a629cd1490c01d4922d42fff007deb 100644
--- a/src/ublox_raw.cpp
+++ b/src/receivers/ublox_raw.cpp
@@ -1,22 +1,16 @@
-#include "gnss_utils/ublox_raw.h"
+#include "gnss_utils/receivers/ublox_raw.h"
 
 using namespace GnssUtils;
 
-UBloxRaw::UBloxRaw() : raw_data_type_(NO)
+UBloxRaw::UBloxRaw()
 {
-  if (init_raw(&raw_data_, STRFMT_UBX) == 0)
-  {
-    assert("Failed when allocating memory for raw_t");
-    return;
-  }
-};
+}
 
 UBloxRaw::~UBloxRaw()
 {
-  free_raw(&raw_data_);
-};
+}
 
-RawDataType UBloxRaw::addDataStream(const std::vector<u_int8_t>& data_stream)
+RawDataType UBloxRaw::addDataStream(const std::vector<uint8_t>& data_stream)
 {
   // Update type based on RTKLIB
   for (auto data_byte = data_stream.begin(); data_byte != data_stream.end(); ++data_byte)
@@ -38,7 +32,6 @@ RawDataType UBloxRaw::addDataStream(const std::vector<u_int8_t>& data_stream)
       case NAV_EPH:  // Ephemeris
         std::cout << "Ephemeris received!\n";
         nav_.copyEphemeris(raw_data_.nav);
-        // std::cout << "Ephemeris copied!\n";
         break;
 
       case NAV_SBAS:  // SBAS
@@ -47,14 +40,11 @@ RawDataType UBloxRaw::addDataStream(const std::vector<u_int8_t>& data_stream)
         // std::cout << "SBAS added!\n";
         break;
 
-      case NAV_ALM:  // Almanac and ion/utc parameters
+      case NAV_ALM_IONUTC:  // Almanac and ion/utc parameters
         std::cout << "Almanac and ion/utc parameters received!\n";
         nav_.freeAlmanac();
-        // std::cout << "Almanac freed!\n";
         nav_.copyAlmanac(raw_data_.nav);
-        // std::cout << "Almanac copied!\n";
         nav_.copyIonUtc(raw_data_.nav);
-        // std::cout << "ION UTC copied!\n";
         break;
 
       // Not handled messages
@@ -81,18 +71,3 @@ RawDataType UBloxRaw::addDataStream(const std::vector<u_int8_t>& data_stream)
 
   return raw_data_type_;
 }
-
-void UBloxRaw::updateObservations()
-{
-  // sort and remove duplicated observations
-  sortobs(&raw_data_.obs);
-  // std::cout << "---------------------------JUST BEFORE!-------------------" << std::endl;
-  // obs_.print();
-
-  obs_.clearObservations();
-  for (int ii = 0; ii < raw_data_.obs.n; ++ii)
-    obs_.addObservation(raw_data_.obs.data[ii]);
-
-  // std::cout << "--------------------------JUST AFTER!---------------------" << std::endl;
-  // obs_.print();
-}
diff --git a/src/utils/rcv_position.cpp b/src/utils/rcv_position.cpp
index 77fa3130f39d28ec65f200558703b89189b23e76..8a2b450c1b9e8ca4d40cc0e19677f7821a2f5aa9 100644
--- a/src/utils/rcv_position.cpp
+++ b/src/utils/rcv_position.cpp
@@ -12,26 +12,26 @@ using namespace GnssUtils;
 namespace GnssUtils
 {
 ComputePosOutput computePos(const GnssUtils::Observations& _observations,
-                            GnssUtils::Navigation&         _navigation,
+                            const GnssUtils::Navigation&   _navigation,
                             const prcopt_t&                _prcopt)
 {
-  // Remove duplicated satellites
-  _navigation.uniqueNavigation();
-
   // Define error msg
   char msg[128] = "";
 
-  // Remove duplicated satellites
-  _navigation.uniqueNavigation();
-
   GnssUtils::ComputePosOutput output;
   sol_t                       sol;
   sol = { { 0 } };
 
-  std::vector<double> sat_elevations(2*_observations.size());
+  std::vector<double> sat_elevations(2 * _observations.size());
 
-  output.pos_stat = pntpos(
-      _observations.data(), _observations.size(), &(_navigation.getNavigation()), &_prcopt, &sol, sat_elevations.data(), NULL, msg);
+  output.pos_stat = pntpos(_observations.data(),
+                           _observations.size(),
+                           &(_navigation.getNavigation()),
+                           &_prcopt,
+                           &sol,
+                           sat_elevations.data(),
+                           NULL,
+                           msg);
 
   if (output.pos_stat == 0)
     std::cout << "computePos: error in computing positioning, message: " << msg << "\n";
@@ -45,7 +45,9 @@ ComputePosOutput computePos(const GnssUtils::Observations& _observations,
   // std::cout << "Covariance:\n" << output.pos_covar << "\n";
 
   if (sol.dtr != NULL)
-    output.rcv_bias = (Eigen::Matrix<double,6,1>() << sol.dtr[0], sol.dtr[1], sol.dtr[2], sol.dtr[3], sol.dtr[4], sol.dtr[5]).finished();
+    output.rcv_bias =
+        (Eigen::Matrix<double, 6, 1>() << sol.dtr[0], sol.dtr[1], sol.dtr[2], sol.dtr[3], sol.dtr[4], sol.dtr[5])
+            .finished();
   output.type    = sol.type;
   output.stat    = sol.stat;
   output.ns      = sol.ns;
@@ -54,7 +56,8 @@ ComputePosOutput computePos(const GnssUtils::Observations& _observations,
   output.lat_lon = ecefToLatLonAlt(output.pos);
 
   for (auto i = 0; i < _observations.size(); i++)
-      output.sat_azel.emplace(_observations.getObservationByIdx(i).sat,Eigen::Vector2d(sat_elevations.at(2*i),sat_elevations.at(2*i+1)));
+    output.sat_azel.emplace(_observations.getObservationByIdx(i).sat,
+                            Eigen::Vector2d(sat_elevations.at(2 * i), sat_elevations.at(2 * i + 1)));
 
   return output;
 }