Open-source project
MapIV/eagleye avatar
MapIV/eagleye

Eagleye, GNSS and IMU fusion for lane-level vehicle positioning

Precise localization based on GNSS and IMU.

775 stars171 forksC++BSD-3-Clause

At a glance

What is it?
MapIV/eagleye is a ROS 2 package that estimates vehicle position and orientation from GNSS Doppler, IMU data and wheel speed, with RTKLIB as the GNSS front end. It comes from a research group at Meijo University and still carries an alpha marker, with the last release in March 2026.
Who is it for?
Adopt Eagleye if you work on lane-level vehicle localization in ROS 2 and can supply the hardware it expects, a Septentrio Mosaic class receiver, an IMU and wheel speed from the CAN bus, plus RTKLIB running as the GNSS front end. Do not adopt it if you need a supported production stack, since the README marks the software alpha and the releases are infrequent.
Can I use it commercially?
Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Activity is slowing. The repository last received commits 6 months ago.
What is it written in?
Mainly C++, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What Eagleye computes and where the method comes from

Eagleye is open source software for vehicle localization using GNSS and IMU. The README's claim is that it provides highly accurate and stable vehicle position and orientation by using GNSS Doppler, with a research paper link given for each of the method's components.

The Doppler part is the part that distinguishes it from a plain GNSS receiver output. A standard receiver gives you a position fix with metre-level uncertainty and a latency that varies with the constellation geometry. Doppler velocity is the rate of change of the carrier phase, which a receiver can observe continuously and which does not degrade in the way a position fix does between satellite acquisitions. Estimating heading and precise motion from that observable, combined with inertial data, is what produces lane-level rather than road-level accuracy.

The algorithms are credited to research at the Machinery Information Systems Lab, known as the Meguro Lab, at Meijo University, and the README points at a flowchart diagram in the docs directory rather than reproducing it in text.

The software is packaged for ROS 2, and the repository top level shows the structure: eagleye_core for the estimation, eagleye_rt for the runtime node, eagleye_msgs for the message definitions, eagleye_util for shared utilities, plus a docs directory, an eagleye.repos file for the workspace dependencies and a CONTRIBUTING.md.

The logo is labelled alpha version, the default branch is main-ros2, and the licence is BSD-3-Clause.

The hardware it expects

Eagleye is not a software-only project. The README lists recommended sensors and the expectations are specific enough to plan a vehicle build against.

The GNSS receiver recommendation is the Septentrio Mosaic development kit with a GNSS antenna. That is a high-precision RTK receiver, and it makes sense given the architecture, since RTKLIB is the front end and it expects carrier-phase data rather than a consumer module's position output. The README describes the installation steps for RTKLIB as a separate build of MapIV's fork of RTKLIB, and the flow runs from a fork of RTKLIB with an rtklib_ros_bridge package.

The IMU recommendations are the Tamagawa Seiki TAG300 series and the Analog Devices ADIS16475. Both are industrial or automotive-grade units rather than hobby sensors, and the IMU output rate is specified as 50 Hz.

The third input is wheel speed, and this comes from the vehicle rather than from a dedicated sensor: Eagleye uses the vehicle speed acquired from the CAN bus, and the runtime checks for it on the /can_twist topic. The README notes that the IMU driver from MapIV, the tamagawa ros driver, needs particular care with the coordinate system, and gives the specific case to watch. If the x-direction indicated on the IMU is set to the vehicle's direction and the y-direction to the right side of the vehicle, the roll in the sensors_tf.yaml file should be set to 3.14159.

That single detail is the kind of thing that silently produces wrong results when it is missed, and the README is right to single it out.

Building the stack: RTKLIB, the ROS packages and the geoid data

The build is a three-part sequence, and the geoid step is the one most people would miss.

First, RTKLIB. The README asks for gfortran, then a clone of MapIV's fork on the rtklib_ros_bridge_b34 branch, and two make steps:

bash
sudo apt-get install gfortran
cd $HOME
git clone -b rtklib_ros_bridge_b34 https://github.com/MapIV/RTKLIB.git
cd $HOME/RTKLIB/lib/iers/gcc/
make
cd $HOME/RTKLIB/app/consapp
make

The iers directory is the International Earth Rotation Service data, and building it is required for accurate time and reference frame handling.

Second, the ROS packages. The eagleye repository is cloned into a workspace and the remaining dependencies are imported from the eagleye.repos file, which pulls in rtklib_ros_bridge and nmea_ros_bridge:

bash
cd $HOME/catkin_ws/src
git clone https://github.com/MapIV/eagleye.git -b main-ros2
vcs import . < eagleye/eagleye.repos

Then the geoid data and the build itself:

bash
sudo apt-get install -y libgeographic-dev geographiclib-tools geographiclib-doc
sudo geographiclib-get-geoids best
sudo mkdir /usr/share/GSIGEO
sudo cp llh_converter/data/gsigeo2011_ver2_1.asc /usr/share/GSIGEO/
cd ..
rosdep install --from-paths src --ignore-src -r -y
colcon build --cmake-args -DCMAKE_BUILD_TYPE=Release

The geoid step exists because GNSS gives you ellipsoidal height while almost everything else in the world uses orthometric height above the geoid, and the difference varies by tens of metres across a country. Copying the geoid file into /usr/share/GSIGEO is what lets the llh_converter component convert between the two. Skip it and your height output is offset by that local geoid undulation, which is enough to make a lane-level estimate wrong.

The final colcon build uses a Release cmake build type, which matters for a package doing this much computation per sample.

Running it on sample data and in real time

The sample route is the sensible way to evaluate the package before committing hardware, and the README is explicit about the one thing that confuses newcomers.

Play the bundled bag and launch the runtime:

bash
ros2 bag play -s rosbag_v2 eagleye_sample.bag
ros2 launch eagleye_rt eagleye_rt.launch.xml

The README warns that estimated results are output about 100 seconds after the bag starts playing, because the algorithm needs the data to accumulate before it can produce an estimate. Anyone launching this and seeing nothing for a minute is not looking at a fault.

Real-time operation is a longer sequence, and the order matters. Check that wheel speed is published on /can_twist with a TwistStamped or TwistWithCovarianceStamped message, and that IMU data is on /imu/data_raw. Then start RTKLIB from its directory with the rtklib_ros_bridge.sh script, and confirm it is producing positions by running the status command, which prints positioning information continuously if it is working:

bash
cd $HOME/RTKLIB
bash rtklib_ros_bridge.sh
status 0.1

After that, start the bridges and Eagleye itself:

bash
ros2 run rtklib_bridge rtklib_bridge --ros-args --params-file $HOME/ros2_ws/src/rtklib_ros_bridge/rtklib_bridge/param/param.yaml
ros2 launch nmea_ros_bridge nmea_udp.launch.py
ros2 launch eagleye_rt eagleye_rt.launch.xml

The NMEA bridge is fed by the receiver over UDP, and its address and port are set in the udp_config.yaml file of the nmea_ros_bridge package.

Topics, configuration and the state of the project

The interface is small and documented. Eagleye subscribes to /navsat/nmea_sentence for NMEA sentences, /can_twist for wheel speed, /rtklib_nav for the RTKLIB navigation output and /imu/data_raw for inertial data. It publishes /eagleye/fix as a NavSatFix, /eagleye/twist as a TwistStamped, and /eagleye/twist_with_covariance as a TwistWithCovarianceStamped.

The covariance output is worth noting. A position estimate without an uncertainty is of limited use in a vehicle, and the presence of a covariance variant of the twist tells you the package propagates uncertainty through the fusion rather than treating the estimate as exact.

Two configuration files drive it. The eagleye_config.yaml holds the estimation parameters, with defaults of 5 Hz for GNSS and 50 Hz for IMU, and the sensors_tf.yaml holds the transform tree, describing each sensor's positional relationship to base_link. If you change the base frame, the README directs you to change the basic_parent_flame entry, which is a spelling error in the upstream file worth knowing about before you go looking for it.

For visualisation and conversion there are helper launches, one to output the fix as KML:

bash
ros2 launch eagleye_fix2kml fix2kml.xml

and two to convert the fix into a pose, geo_pose_fusion.launch.xml and geo_pose_converter.launch.xml.

On the state of the project, the release history is sparse: v1.7.3-ros2 on 2026-03-26, v1.7.2-ros2 back in April 2024 and v1.7.1-ros2 in November 2023, with the last push on 2026-04-06. Combined with the alpha marker on the logo, that says research software with a capable architecture and an uncertain maintenance commitment. The BSD-3-Clause licence is permissive and fine for commercial work, and the repository also carries a sample data section with ROS1 bags recorded in Nagoya with named sensors for each.

Editorial conclusion

Adopt Eagleye if you work on lane-level vehicle localization in ROS 2 and can supply the hardware it expects, a Septentrio Mosaic class receiver, an IMU and wheel speed from the CAN bus, plus RTKLIB running as the GNSS front end. Do not adopt it if you need a supported production stack, since the README marks the software alpha and the releases are infrequent. Verify first by playing the bundled rosbag and confirming the /eagleye/fix output appears about 100 seconds in, then check that your IMU mounting matches the roll value in sensors_tf.yaml.

Frequently asked questions

What is Eagleye and what does it estimate?

Eagleye is open source software for vehicle localization that uses GNSS Doppler together with IMU data and wheel speed to produce highly accurate and stable vehicle position and orientation. The algorithms come from research at the Meguro Lab at Meijo University.

Which sensors does Eagleye need?

The README recommends a Septentrio Mosaic development kit with GNSS antenna as the receiver, a Tamagawa Seiki TAG300 series or Analog Devices ADIS16475 IMU running at 50 Hz, and vehicle speed acquired from the CAN bus, which the runtime expects on the /can_twist topic.

How do I build Eagleye and RTKLIB for ROS 2?

Install gfortran, clone MapIV's RTKLIB fork on the rtklib_ros_bridge_b34 branch and build the iers library and consapp, then clone the eagleye repository on the main-ros2 branch into a workspace, import the dependencies with vcs import from eagleye.repos, fetch the geoid data, and run colcon build with a Release cmake build type.

Why do I see no Eagleye output for the first minute?

The README states that estimated results are output about 100 seconds after the rosbag starts playing, because the data has to accumulate before estimation can begin. The same applies to live operation.

Which topics does Eagleye subscribe to and publish?

It subscribes to /navsat/nmea_sentence, /can_twist, /rtklib_nav and /imu/data_raw, and publishes /eagleye/fix as a NavSatFix, /eagleye/twist as a TwistStamped and /eagleye/twist_with_covariance as a TwistWithCovarianceStamped.

Official sources

  1. Issues
  2. License: BSD-3-Clause
  3. MapIV/eagleye on GitHub
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/mapiv-eagleye.svg)](https://hysenlabs.com/projects/mapiv-eagleye)

Was this useful?