# Using Eagleye with Autoware

This page shows you how to set up [Eagleye](<https://github.com/MapIV/eagleye>) to use it with Autoware. For the details of the integration proposal, please refer to [this discussion](<https://github.com/orgs/autowarefoundation/discussions/3257>).

## What is Eagleye?

Eagleye is an open-source GNSS/IMU-based localizer initially developed by [MAP IV. Inc](<https://map4.jp/>). It provides a cost-effective alternative to LiDAR and point cloud-based localization by using low-cost GNSS and IMU sensors to provide vehicle position, orientation, and altitude information.

### Dependencies

The setup of Autoware imports the packages below, because [repositories/autoware.repos](<https://github.com/autowarefoundation/autoware/blob/2.0.0/repositories/autoware.repos>) of Autoware 2.0.0 lists them. Each repository is pinned to a fixed commit.

1. [Eagleye](<https://github.com/MapIV/eagleye>) (commit `575136eb`)
2. [RTKLIB ROS Bridge](<https://github.com/MapIV/rtklib_ros_bridge>) (commit `ef094407`)
3. [LLH Converter](<https://github.com/MapIV/llh_converter>) (commit `4fc2a2e1`)

## Architecture

You can use Eagleye in the Autoware localization stack in two ways.

In the first way, Eagleye gives only the twist to the EKF localizer. Set `twist_source:=eagleye` and keep another pose source, for example `pose_source:=ndt`.

Eagleye gives the twist and NDT gives the pose to the EKF localizer.

In the second way, Eagleye gives both the twist and the pose to the EKF localizer. Set `pose_source:=eagleye` and `twist_source:=eagleye`. You can also use Eagleye only for the pose and keep `twist_source:=gyro_odom`.

Eagleye gives both the twist and the pose to the EKF localizer.

`component_localization.launch.xml` of `autoware_launch` includes `pose_twist_estimator/eagleye/eagleye_rt.launch.xml` of `autoware_localization_launch` for both ways. For more information, see the [Localization launch files](<../index.md>) page.

**Note: RTK positioning is required when using Eagleye as the pose estimator.** On the other hand, it is not mandatory when using it as the twist estimator.

## Requirements

Eagleye requires GNSS, IMU and vehicle speed as inputs.

### IMU topic

`sensor_msgs/msg/Imu` is supported for Eagleye IMU input.

### Vehicle speed topic

`geometry_msgs/msg/TwistStamped` and `geometry_msgs/msg/TwistWithCovarianceStamped` are supported for the input vehicle speed.

### GNSS topic

Eagleye requires latitude/longitude height and doppler velocity generated by the GNSS receiver. Your GNSS ROS driver must publish the following messages:

- `sensor_msgs/msg/NavSatFix`: This message contains latitude, longitude, and height information.
- `geometry_msgs/msg/TwistWithCovarianceStamped`: This message contains gnss doppler velocity information.

  Eagleye has been tested with the following example GNSS ROS drivers: ublox\_gps and septentrio\_gnss\_driver. The settings needed for each of these drivers are as follows:

| GNSS ROS drivers | modification |
| --- | --- |
| [ublox\_gps](<https://github.com/KumarRobotics/ublox/tree/ros2/ublox_gps>) | No additional settings are required. It publishes `sensor_msgs/msg/NavSatFix` and `geometry_msgs/msg/TwistWithCovarianceStamped` required by Eagleye with default settings. |
| [septentrio\_gnss\_driver](<https://github.com/septentrio-gnss/septentrio_gnss_driver/>) | Set `publish.navsatfix` and `publish.twist` in the config file [`gnss.yaml`](<https://github.com/septentrio-gnss/septentrio_gnss_driver/blob/master/config/gnss.yaml>) to `true` |

## Parameter modifications for integration into your vehicle

### Topic name and topic type

Specify the input topics for the GNSS latitude, longitude, and height, the GNSS Doppler velocity, the IMU, and the vehicle speed in [`eagleye_config.param.yaml`](<https://github.com/autowarefoundation/autoware_launch/blob/0.53.0/autoware_universe_launch/autoware_localization_config/config/eagleye_config.param.yaml#L7-L16>) of the `autoware_localization_config` package.

```yaml
# Topic
twist:
  twist_type: 1 # TwistStamped : 0, TwistWithCovarianceStamped: 1
  twist_topic: /sensing/vehicle_velocity_converter/twist_with_covariance
imu_topic: /sensing/imu/imu_data
gnss:
  velocity_source_type: 2 # rtklib_msgs/RtklibNav: 0, nmea_msgs/Sentence: 1, ublox_msgs/NavPVT: 2, geometry_msgs/TwistWithCovarianceStamped: 3, septentrio_gnss_driver/PVTGeodetic: 4
  velocity_source_topic: /sensing/gnss/ublox/navpvt
  llh_source_type: 2 # rtklib_msgs/RtklibNav: 0, nmea_msgs/Sentence: 1, sensor_msgs/NavSatFix: 2
  llh_source_topic: /sensing/gnss/ublox/nav_sat_fix
```

### Sensor frequency

Also, set the frequency of the GNSS and the IMU in [`eagleye_config.param.yaml`](<https://github.com/autowarefoundation/autoware_launch/blob/0.53.0/autoware_universe_launch/autoware_localization_config/config/eagleye_config.param.yaml#L37-L39>):

```yaml
common:
  imu_rate: 50
  gnss_rate: 5
```

### Conversion from the geographic pose to the map frame

When Eagleye is a pose source, `eagleye_geo_pose_fusion` publishes the pose as a `geographic_msgs/msg/GeoPoseWithCovarianceStamped` message. Then [`autoware_geo_pose_projector`](<https://autowarefoundation.github.io/autoware_universe/main/localization/autoware_geo_pose_projector/>) converts it into a `geometry_msgs/msg/PoseWithCovarianceStamped` message in the map frame. The projector reads the map projection from the `/map/map_projector_info` topic. So the projection type and the vertical datum come from `map_projector_info.yaml` of your map. For more information, see [`autoware_map_projection_loader`](<https://autowarefoundation.github.io/autoware_core/main/map/autoware_map_projection_loader/>).

### Other parameters

The [Eagleye documentation](<https://github.com/MapIV/eagleye/tree/575136ebba99892946d36d8398f228aee2136af0/eagleye_rt/config>) describes the other parameters. Usually, you do not need to change them.

## Notes on initialization

Eagleye requires an initialization process for proper operation. **Without initialization, the output for twist will be in the raw value, and the pose data will not be available.**

### 1\. Static initialization

The first step is static initialization, which involves allowing the Eagleye to remain stationary for approximately 5 seconds after startup to estimate the yaw-rate offset.

### 2\. Dynamic initialization

The next step is dynamic initialization, which involves running the Eagleye in a straight line for approximately 30 seconds. This process estimates the scale factor of wheel speed and azimuth angle.

Once dynamic initialization is complete, the Eagleye will be able to provide corrected twist and pose data.

### How to check the progress of initialization

The `monitor` node of Eagleye publishes the state of each estimate on the `/diagnostics` topic. Until an estimate starts, its diagnostic has the level WARN and the message `estimates have not started yet`. When the estimate is available, the message changes to `OK`. Use these diagnostics to follow the initialization:

| Diagnostic name | Initialization step |
| --- | --- |
| `eagleye_yaw_rate_offset_stop` | Static initialization: the yaw rate offset at standstill |
| `eagleye_velocity_scale_factor` | Dynamic initialization: the scale factor of the wheel speed |
| `eagleye_heading_interpolate_1st` | Dynamic initialization: the first estimate of the heading |
| `eagleye_enu_absolute_pos_interpolate` | The position, when Eagleye is a pose source |

You can see the diagnostics in `rqt_runtime_monitor`, or print them in a terminal:

```bash
ros2 topic echo /diagnostics | grep -B 1 -A 1 "eagleye_velocity_scale_factor"
```

You can also read the status of each estimate directly. The Eagleye topics are in the namespace of the estimator, for example `/localization/twist_estimator/eagleye/` when Eagleye is only the twist source, or `/localization/pose_twist_estimator/eagleye/` when it is the pose and the twist source. The `status.enabled_status` field becomes `true` when the first estimate is done:

```bash
ros2 topic echo /localization/twist_estimator/eagleye/velocity_scale_factor --field status
```

## Note on georeferenced maps

Note that the output position might not appear to be in the point cloud maps if you are using maps that are not properly georeferenced. In the case of a single GNSS antenna, initial position estimation (dynamic initialization) can take several seconds to complete after starting to run in an environment where GNSS positioning is available.
