-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[CR-1159] Add changelog, bump version to v0.1.7, do miscellaneous cha…
…nges
- Loading branch information
1 parent
bf418bc
commit e2f6a37
Showing
10 changed files
with
455 additions
and
81 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,4 +15,4 @@ | |
] | ||
|
||
# TODO Find a way to use this version in pyproject.toml | ||
__version__ = "0.1.6" | ||
__version__ = "0.1.7" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import numpy as np | ||
|
||
|
||
def is_symmetric(arr: np.ndarray, tol=1e-8) -> bool: | ||
""" | ||
Check if a numpy array is approximately symmetric. | ||
A matrix is symmetric if its transpose is approximately equal to itself. | ||
Examples: | ||
>>> arr1 = np.array([[1, 2, 3], | ||
... [2, 4, 5], | ||
... [3, 5, 6]]) | ||
>>> is_symmetric(arr1) | ||
True | ||
>>> arr2 = np.array([[1, 2, 3], | ||
... [4, 5, 6], | ||
... [7, 8, 9]]) | ||
>>> is_symmetric(arr2) | ||
False | ||
>>> arr3 = np.array([[1.0, 2.0], | ||
... [2.0, 1.0]]) | ||
>>> is_symmetric(arr3) | ||
True | ||
>>> arr4 = np.array([[1.0, 2.0, 3.0], | ||
... [2.0, 1.0, 4.0]]) | ||
>>> is_symmetric(arr4) | ||
False | ||
""" | ||
if arr.ndim != 2: | ||
raise ValueError(f"Input array must be 2D - Current #dims: {arr.ndim}") | ||
|
||
rows, cols = arr.shape | ||
if rows != cols: | ||
return False | ||
|
||
return np.allclose(arr, arr.T, atol=tol) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
__copyright__ = """ | ||
SLAMcore Confidential | ||
--------------------- | ||
SLAMcore Limited | ||
All Rights Reserved. | ||
(C) Copyright 2023 | ||
NOTICE: | ||
All information contained herein is, and remains the property of SLAMcore | ||
Limited and its suppliers, if any. The intellectual and technical concepts | ||
contained herein are proprietary to SLAMcore Limited and its suppliers and | ||
may be covered by patents in process, and are protected by trade secret or | ||
copyright law. Dissemination of this information or reproduction of this | ||
material is strictly forbidden unless prior written permission is obtained | ||
from SLAMcore Limited. | ||
""" | ||
|
||
__license__ = "SLAMcore Confidential" | ||
|
||
|
||
import csv | ||
from pathlib import Path | ||
from geometry_msgs.msg import PoseStamped | ||
|
||
import numpy as np | ||
|
||
from slamcore_utils import DatasetSubdirWriter, MeasurementType, setup_pkg_logging | ||
from slamcore_utils.ros2 import Ros2ConverterPlugin, Ros2PluginInitializationFailureError | ||
|
||
plugin_name = Path(__file__).name | ||
logger = setup_pkg_logging(plugin_name) | ||
|
||
try: | ||
from gps_msgs.msg import GPSFix | ||
except ModuleNotFoundError: | ||
raise Ros2PluginInitializationFailureError( | ||
plugin_name=plugin_name, | ||
msg=( | ||
"Could not import the gps_msgs module. On Ubuntu this is shipped with the ros-<ros-version>-gps-msgs package" | ||
"Please make sure that the latter is installed (or that the gps-msgs are installed via source and retry" | ||
), | ||
) | ||
|
||
|
||
class GPSAsPoseStampedWriter(DatasetSubdirWriter): | ||
"""Convert and save GPSFix messages in the Slamcore dataset format.""" | ||
|
||
# constants for the potential conversion of LLA -> XYZ if given GPS data | ||
EARTH_RADIUS_M = 6378137.0 | ||
FLATTENING_RATIO = 1.0 / 298.257224 | ||
|
||
def __init__(self, directory): | ||
super().__init__(directory=directory) | ||
|
||
def prepare_write(self) -> None: | ||
self.ofs_data = (self.directory / "data.csv").open("w", newline="") | ||
self.csv_writer = csv.writer(self.ofs_data, delimiter=",") | ||
|
||
cols = [ | ||
"#timestamp [ns]", | ||
"p_RS_R_x [m]", | ||
"p_RS_R_y [m]", | ||
"p_RS_R_z [m]", | ||
"q_RS_w []", | ||
"q_RS_x []", | ||
"q_RS_y []", | ||
"q_RS_z []", | ||
] | ||
|
||
self.csv_writer.writerow(cols) | ||
|
||
def write_pose_stamped(self, msg: PoseStamped): | ||
ts = int(msg.header.stamp.sec * 1e9) + int(msg.header.stamp.nanosec) | ||
p = msg.pose.position | ||
q = msg.pose.orientation | ||
self.csv_writer.writerow([ts, p.x, p.y, p.z, q.w, q.x, q.y, q.z]) | ||
|
||
def write(self, msg: GPSFix) -> None: | ||
""" | ||
Convert LLA GPS coordinates XYZ coordinates | ||
Consult the following two resources for the conversion equations: | ||
https://web.archive.org/web/20181018072749/http://mathforum.org/library/drmath/view/51832.html | ||
https://stackoverflow.com/a/8982005/2843583 | ||
""" | ||
|
||
lat_rad = np.deg2rad(msg.latitude) | ||
lon_rad = np.deg2rad(msg.longitude) | ||
alt_m = msg.altitude | ||
|
||
cos_lat = np.cos(lat_rad) | ||
sin_lat = np.sin(lat_rad) | ||
|
||
cos_lon = np.cos(lon_rad) | ||
sin_lon = np.sin(lon_rad) | ||
|
||
C = 1.0 / np.sqrt( | ||
cos_lat * cos_lat | ||
+ (1 - self.FLATTENING_RATIO) * (1 - self.FLATTENING_RATIO) * sin_lat * sin_lat | ||
) | ||
S = (1.0 - self.FLATTENING_RATIO) * (1.0 - self.FLATTENING_RATIO) * C | ||
|
||
pose_out: PoseStamped = PoseStamped() | ||
pose_out.header = msg.header | ||
pose_out.pose.position.x = (self.EARTH_RADIUS_M * C + alt_m) * cos_lat * cos_lon | ||
pose_out.pose.position.y = (self.EARTH_RADIUS_M * C + alt_m) * cos_lat * sin_lon | ||
pose_out.pose.position.z = (self.EARTH_RADIUS_M * S + alt_m) * sin_lat | ||
|
||
# # Cache first pose received and always substract from it so that we start from (0,0,0) | ||
# if self._first_pose is None: | ||
# x = pose_out.pose.position.x | ||
# y = pose_out.pose.position.y | ||
# z = pose_out.pose.position.z | ||
# logger.warning( | ||
# f"Setting the first GPS received pose from ({x}, {y}, {z}) to to (0,0,0) ..." | ||
# ) | ||
|
||
# self._first_pose = Pose() | ||
# self._first_pose.position.x = pose_out.pose.position.x | ||
# self._first_pose.position.y = pose_out.pose.position.y | ||
# self._first_pose.position.z = pose_out.pose.position.z | ||
|
||
# pose_out.pose.position.x -= self._first_pose.position.x | ||
# pose_out.pose.position.y -= self._first_pose.position.y | ||
# pose_out.pose.position.z -= self._first_pose.position.z | ||
|
||
self.write_pose_stamped(pose_out) | ||
|
||
def teardown(self): | ||
self.ofs_data.close() | ||
|
||
|
||
# define plugins for converter to use ------------------------------------------ | ||
# mandatory key in module namespace | ||
converter_plugins = [ | ||
Ros2ConverterPlugin( | ||
writer_type=GPSAsPoseStampedWriter, | ||
measurement_type=MeasurementType( | ||
name="GNSSGroundTruth", shortname="gnss_groundtruth", is_camera=False | ||
), | ||
msg_type="gps_msgs/msg/GPSFix", | ||
), | ||
] |
Oops, something went wrong.