Merges a list of trajectories into one trajectory.
This function ignores EPSG codes and merges the trajectories based on their timestamps.
Therefore, all trajectories should be in the same coordinate system before merging.
Parameters:
-
trajectories
(List[Trajectory])
–
List of trajectories to merge.
Returns:
Raises:
-
ValueError
–
If no trajectories are provided.
Source code in trajectopy\processing\merging.py
| def merge_trajectories(trajectories: list[Trajectory]) -> Trajectory:
"""Merges a list of trajectories into one trajectory.
This function ignores EPSG codes and merges the trajectories based on their timestamps.
Therefore, all trajectories should be in the same coordinate system before merging.
Args:
trajectories (List[Trajectory]): List of trajectories to merge.
Returns:
Trajectory: Merged trajectory.
Raises:
ValueError: If no trajectories are provided.
"""
if not trajectories:
raise ValueError("Cannot merge empty list of trajectories")
epsg_set = {t.positions.epsg for t in trajectories}
if len(epsg_set) > 1:
logger.warning(
"Merging trajectories with different EPSG codes. "
"This may lead to unexpected results. "
"Consider reprojecting the trajectories to the same EPSG code."
)
epsg = trajectories[0].positions.epsg # the first trajectory's, not an arbitrary one of the set
merged_xyz = np.concatenate([t.positions.xyz for t in trajectories], axis=0)
# orientations only if all trajectories have them: any substitute would be made-up data
with_orientation = all(t.rotations is not None for t in trajectories)
if not with_orientation and any(t.rotations is not None for t in trajectories):
logger.warning("Not all merged trajectories have orientations. The merged trajectory has none.")
merged_rotations = (
Rotations.from_quat(np.concatenate([t.quat for t in trajectories], axis=0)) if with_orientation else None
)
merged_timestamps = np.concatenate([t.timestamps for t in trajectories], axis=0)
merged_velocities = np.concatenate([t.velocity_xyz for t in trajectories], axis=0)
# the trajectory orders the poses chronologically before it derives the path lengths
return Trajectory(
name="Merged",
timestamps=merged_timestamps,
positions=Positions(xyz=merged_xyz, epsg=epsg),
rotations=merged_rotations,
velocity_xyz=merged_velocities,
)
|