24
24
from colorama import Fore , Style
25
25
from rospy_message_converter import message_converter
26
26
from std_msgs .msg import Header
27
- from atom_core .config_io import uriReader
28
- from atom_core .naming import generateName , generateKey
27
+ from atom_core .config_io import uriReader , mutually_inclusive_conditions
28
+ from atom_core .naming import generateName , generateKey , generateCollectionKey
29
29
from atom_calibration .collect .label_messages import (
30
30
convertDepthImage32FC1to16UC1 , convertDepthImage16UC1to32FC1 , numpyFromPointCloudMsg )
31
31
@@ -787,7 +787,7 @@ def filterAdditionalTfsFromDataset(dataset, args):
787
787
return dataset
788
788
789
789
790
- def addNoiseToJointParameters (dataset , args ):
790
+ def addBiasToJointParameters (dataset , args ):
791
791
"""
792
792
Adds noise
793
793
:param dataset:
@@ -828,6 +828,25 @@ def addNoiseToJointParameters(dataset, args):
828
828
collection ['joints' ][joint_name ][joint_param ] = collection ['joints' ][joint_name ][
829
829
joint_param ] + joint_bias
830
830
831
+ def addNoiseFromNoisyTFLinks (dataset ,args ,selected_collection_key ):
832
+
833
+ # Verify both arguments were provided
834
+ # Unfortunately, mutually inclusive arguments are not built into argparse
835
+ # https://github.com/python/cpython/issues/55797
836
+
837
+ if not mutually_inclusive_conditions (args ['noisy_tf_links' ], args ['noisy_tf_values' ]):
838
+ return
839
+
840
+
841
+ # Iterate through pairs of tf's and apply noise
842
+ translation_tf_noise = args ['noisy_tf_values' ][0 ]
843
+ rotation_tf_noise = args ['noisy_tf_values' ][1 ]
844
+
845
+ for tf_pair in args ['noisy_tf_links' ]:
846
+
847
+ calibration_parent ,calibration_child = tf_pair [0 ],tf_pair [1 ]
848
+ addNoiseToTF (dataset ,selected_collection_key ,calibration_parent ,calibration_child ,translation_tf_noise ,rotation_tf_noise )
849
+
831
850
832
851
def addNoiseToInitialGuess (dataset , args , selected_collection_key ):
833
852
"""
@@ -836,19 +855,38 @@ def addNoiseToInitialGuess(dataset, args, selected_collection_key):
836
855
:param args: Makes use of nig, i.e., the amount of noise to add to the initial guess atomic transformations to be
837
856
calibrated
838
857
"""
858
+ # TODO create a issue to discuss if its ok to skip this function call when the noise is 0
859
+ # if args['noisy_initial_guess'] == [0,0]:
860
+ # print("No noise added to transform's initial guess")
861
+ # return
862
+
839
863
if args ['sample_seed' ] is not None :
840
864
np .random .seed (args ['sample_seed' ])
841
865
842
866
nig_trans = args ['noisy_initial_guess' ][0 ]
843
867
nig_rot = args ['noisy_initial_guess' ][1 ]
844
868
869
+
870
+ # Checking if tf to add noise is also defined in -ntfl, in which case the noise shouldn't be added here
871
+ # Determining membership in sets is much faster than lists
872
+ ntfl_tfs = set ()
873
+ if args ['noisy_tf_links' ]:
874
+ for tf_pair in args ['noisy_tf_links' ]:
875
+ ntfl_tfs .add (generateKey (tf_pair [0 ],tf_pair [1 ]))
876
+
845
877
# add noise to additional tfs for simulation
846
878
if dataset ['calibration_config' ]['additional_tfs' ] is not None :
847
879
for _ , additional_tf in dataset ['calibration_config' ]['additional_tfs' ].items ():
880
+
848
881
calibration_child = additional_tf ['child_link' ]
849
882
calibration_parent = additional_tf ['parent_link' ]
850
- addNoiseToTF (dataset , selected_collection_key , calibration_parent ,
851
- calibration_child , nig_trans , nig_rot )
883
+
884
+ tf_to_add_noise = generateKey (calibration_parent ,calibration_child )
885
+ if tf_to_add_noise in ntfl_tfs :
886
+ atomWarn (f'Not adding initial guess noise to { tf_to_add_noise } because its defined in -ntfl' )
887
+ continue
888
+
889
+ addNoiseToTF (dataset , selected_collection_key , calibration_parent , calibration_child , nig_trans , nig_rot )
852
890
853
891
# add noise to sensors tfs for simulation
854
892
for sensor_key , sensor in dataset ['sensors' ].items ():
@@ -858,38 +896,63 @@ def addNoiseToInitialGuess(dataset, args, selected_collection_key):
858
896
if sensor_key != dataset ['calibration_config' ]['anchored_sensor' ]:
859
897
calibration_child = sensor ['calibration_child' ]
860
898
calibration_parent = sensor ['calibration_parent' ]
861
- addNoiseToTF (dataset , selected_collection_key , calibration_parent ,
862
- calibration_child , nig_trans , nig_rot )
863
899
900
+ tf_to_add_noise = generateKey (calibration_parent ,calibration_child )
901
+ if tf_to_add_noise in ntfl_tfs :
902
+ atomWarn (f'Not adding initial guess noise to { tf_to_add_noise } because its defined in -ntfl' )
903
+ continue
904
+
905
+ addNoiseToTF (dataset , selected_collection_key , calibration_parent , calibration_child , nig_trans , nig_rot )
864
906
865
- def addNoiseToTF ( dataset , selected_collection_key , calibration_parent , calibration_child , nig_trans , nig_rot ):
907
+ # TODO make a basic function called by fixed and multiple
866
908
909
+ def computeNoise (initial_translation ,initial_euler_angles ,translation_noise_magnitude ,rotation_noise_magnitude ):
910
+ '''
911
+ Computes both the translation and rotation noise given a certain magnitude and returns the new noisy translation/rotation vectors
912
+ '''
913
+ # Translation
914
+
915
+ v = np .random .uniform (- 1.0 , 1.0 , 3 )
916
+ v = v / np .linalg .norm (v )
917
+ translation_delta = v * translation_noise_magnitude
918
+
919
+ new_translation = initial_translation + translation_delta
920
+ # Rotation
921
+
922
+ # Its necessary to redefine 'v' to ensure that the translation and rotation noise aren't always the same given the same magnitude
923
+ v = np .random .uniform (- 1.0 , 1.0 , 3 )
924
+ v = v / np .linalg .norm (v )
925
+ rotation_delta = v * rotation_noise_magnitude
926
+
927
+ new_euler_angles = initial_euler_angles + rotation_delta
928
+
929
+ return new_translation ,new_euler_angles
930
+
931
+
932
+ def addNoiseToTF (dataset , selected_collection_key , calibration_parent , calibration_child , noise_trans , noise_rot ):
933
+
934
+ print (Fore .RED + 'Transformation parent ' + calibration_parent + ' child ' + calibration_child + Style .RESET_ALL )
867
935
transform_key = generateKey (calibration_parent , calibration_child , suffix = '' )
868
936
937
+ atomWarn (f'Adding noise bigger than 1.0m/rad right now is bugged and might yield unexpected results. Check issue #929 for more information' )
938
+
869
939
# because of #900, and for retrocompatibility with old datasets, we will assume that if the transforms field does
870
940
# not exist in the dataset, then the transformation is fixed
871
941
if 'transforms' not in dataset or dataset ['transforms' ][transform_key ]['type' ] == 'fixed' :
872
942
873
943
# Get original transformation
874
944
quat = dataset ['collections' ][selected_collection_key ]['transforms' ][transform_key ]['quat' ]
875
- translation = dataset ['collections' ][selected_collection_key ]['transforms' ][
876
- transform_key ]['trans' ]
877
-
878
- # Add noise to the 6 pose parameters
879
- v = np .random .uniform (- 1.0 , 1.0 , 3 )
880
- v = v / np .linalg .norm (v )
881
- new_translation = translation + v * nig_trans
945
+ translation = dataset ['collections' ][selected_collection_key ]['transforms' ][transform_key ]['trans' ]
882
946
883
- v = np .random .choice ([- 1.0 , 1.0 ], 3 ) * nig_rot
884
947
euler_angles = tf .transformations .euler_from_quaternion (quat )
885
- new_angles = euler_angles + v
948
+
949
+
950
+ new_translation ,new_euler_angles = computeNoise (translation ,euler_angles ,noise_trans ,noise_rot )
886
951
887
952
# Replace the original atomic transformations by the new noisy ones
888
- new_quat = tf .transformations .quaternion_from_euler (
889
- new_angles [0 ], new_angles [1 ], new_angles [2 ])
953
+ new_quat = tf .transformations .quaternion_from_euler (new_euler_angles [0 ], new_euler_angles [1 ], new_euler_angles [2 ])
890
954
dataset ['collections' ][selected_collection_key ]['transforms' ][transform_key ]['quat' ] = new_quat
891
- dataset ['collections' ][selected_collection_key ]['transforms' ][transform_key ]['trans' ] = list (
892
- new_translation )
955
+ dataset ['collections' ][selected_collection_key ]['transforms' ][transform_key ]['trans' ] = list (new_translation )
893
956
894
957
# Copy randomized transform to all collections
895
958
for collection_key , collection in dataset ['collections' ].items ():
@@ -902,26 +965,18 @@ def addNoiseToTF(dataset, selected_collection_key, calibration_parent, calibrati
902
965
903
966
for collection_key , collection in dataset ["collections" ].items ():
904
967
905
- # Get original transformation
906
968
quat = dataset ['collections' ][collection_key ]['transforms' ][transform_key ]['quat' ]
907
- translation = dataset ['collections' ][collection_key ]['transforms' ][transform_key ][
908
- 'trans' ]
969
+ translation = dataset ['collections' ][collection_key ]['transforms' ][transform_key ]['trans' ]
909
970
910
- # Add noise to the 6 pose parameters
911
- v = np .random .uniform (- 1.0 , 1.0 , 3 )
912
- v = v / np .linalg .norm (v )
913
- new_translation = translation + v * nig_trans
914
-
915
- v = np .random .choice ([- 1.0 , 1.0 ], 3 ) * nig_rot
916
971
euler_angles = tf .transformations .euler_from_quaternion (quat )
917
- new_angles = euler_angles + v
972
+
973
+ new_translation ,new_euler_angles = computeNoise (translation ,euler_angles ,noise_trans ,noise_rot )
974
+
975
+ new_quat = tf .transformations .quaternion_from_euler (new_euler_angles [0 ], new_euler_angles [1 ], new_euler_angles [2 ])
918
976
919
977
# Replace the original atomic transformations by the new noisy ones
920
- new_quat = tf .transformations .quaternion_from_euler (
921
- new_angles [0 ], new_angles [1 ], new_angles [2 ])
922
978
dataset ['collections' ][collection_key ]['transforms' ][transform_key ]['quat' ] = new_quat
923
- dataset ['collections' ][collection_key ]['transforms' ][transform_key ]['trans' ] = list (
924
- new_translation )
979
+ dataset ['collections' ][collection_key ]['transforms' ][transform_key ]['trans' ] = list (new_translation )
925
980
926
981
927
982
def copyTFToDataset (calibration_parent , calibration_child , source_dataset , target_dataset ):
0 commit comments