"""Implementation of all math utility functions."""importnumpyasnpimportnumpy.typingasnpt
[docs]defcircular_mean(sigmas:npt.NDArray,Wm:npt.NDArray,normalize:bool=True)->npt.NDArray:""" Calculate weighted mean of angles. Since angles are periodic normal mean functions cannot be used, so this function implements one possibility to calculate circular means. Parameters ---------- sigmas : npt.NDArray Sigma points for UKF. Wm : npt.NDArray Weights for the sigma points. Returns ------- npt.NDArray Weighted mean. """sum_sin=np.sum(np.dot(np.sin(sigmas),Wm))sum_cos=np.sum(np.dot(np.cos(sigmas),Wm))result=np.arctan2(sum_sin,sum_cos)# somehow all weighted circular mean implementations make math errors, when mean is nearly zero.# Direction of vector on unit circle is inverted --> result is shifted by 180 degrees / piaverage=np.average(sigmas,axis=0,weights=Wm)ifabs(normalize_rad_angle(result-average))>3:result=normalize_rad_angle(result+np.pi)ifnormalizeisFalse:result=(np.round((average-result)/(2*np.pi))*2*np.pi)+resultreturnresult
[docs]defnormalize_rad_angle(angle:npt.NDArray[np.floating])->npt.NDArray[np.floating]:""" Normalize angle in unit [rad]. Since angles are periodic, they have to be normalized. Parameters ---------- angle : npt.NDArray[np.floating] Input angle. Returns ------- npt.NDArray[np.floating] Normalized angle. See Also -------- normalize_rad_angles: Normalize multiple angles in [rad] simultaneously. """angle=angle%(2*np.pi)# force in range [0, 2 pi)ifangle>np.pi:# move to [-pi, pi)angle-=2*np.pireturnangle
[docs]defnormalize_rad_angles(angles:npt.NDArray[np.floating])->npt.NDArray[np.floating]:""" Normalize angles in unit [rad]. Since angles are periodic, they have to be normalized. Parameters ---------- angles : npt.NDArray[np.floating] Input angle. Returns ------- npt.NDArray[np.floating] Normalized angles. """angles=np.mod(angles,2*np.pi)angles[angles>np.pi]-=2*np.pireturnangles
[docs]defnormalize_degree_angle(angle:npt.NDArray[np.floating])->npt.NDArray[np.floating]:""" Normalize angle in unit [degrees]. Since angles are periodic, they have to be normalized. Parameters ---------- angle : npt.NDArray[np.floating] Input angle. Returns ------- npt.NDArray[np.floating] Normalized angle. """angle=angle%360ifangle>180:angle-=360returnangle
[docs]defnormalize_degree_angles(angles:npt.NDArray[np.floating])->npt.NDArray[np.floating]:""" Normalize angles in unit [degrees]. Since angles are periodic, they have to be normalized. Parameters ---------- angles : npt.NDArray[np.floating] Input angle. Returns ------- npt.NDArray[np.floating] Normalized angles. """angles=np.mod(angles,360)angles[angles>180]-=360returnangles