Source code for simulate_local_mapping_for_alignment
#!/usr/bin/env pythonimportrospyfromstd_msgs.msgimportHeaderfromutilities.msgimportConePosition,ConeList# Adjust according to your package nameimportjsonimporttracebackimportnumpyasnpimportos
[docs]defpublish_cone_positions(test_track,test_day):# Initialize the ROS noderospy.init_node('cone_positions_publisher',anonymous=True)# Create a publisher objectpub=rospy.Publisher('/local_mapping/cone_positions',ConeList,queue_size=10)rospy.sleep(1)# Create the messagecone_list_msg=ConeList()# Fill in the header fieldscurrent_time=rospy.Time.now()cone_list_msg.header=Header(stamp=current_time,frame_id='base_link')cone_list_msg.image_header=Header(stamp=current_time,frame_id='camera_link')cone_list_msg.lidar_header=Header(stamp=current_time,frame_id='lidar_link')# Fill in the processing timescone_list_msg.processing_time=0.1# Example valuecone_list_msg.lidar_processing_time=0.05# Example valuecone_list_msg.sensor_time_delta=0.01# Example value# Check if manual json file existsifnotos.path.exists(f'/workspace/as_ros/src/slam/plots/maps/{test_day}/{test_track}/manual.json'):rospy.logerr("[Local Mapping Simulation] We might need to talk about creating a manual.json.")exit(69)# Load the cone positions from the manual json filewithopen(f'/workspace/as_ros/src/slam/plots/maps/{test_day}/{test_track}/manual.json')asf:data=json.load(f)# Apply a rigid body transformation to the cone positionscone_positions=[]forx,yinzip(data['x'],data['y']):position=np.array([x,y])position=positionangle=np.deg2rad(TRANSFORM_ANGLE)rotation_matrix=np.array([[np.cos(angle),-np.sin(angle)],[np.sin(angle),np.cos(angle)]])new_position=np.dot(rotation_matrix,position)+TRANSFORM_TRANSLATIONcone_positions.append(new_position)cone_positions_np=np.array(cone_positions)data["x"]=cone_positions_np[:,0].tolist()data["y"]=cone_positions_np[:,1].tolist()# Save the transformed cone positions to a new json ground truth filewithopen(f'/workspace/as_ros/src/slam/plots/maps/{test_day}/{test_track}/ground_truth.json','w')asf:json.dump(data,f)# Apply noise to the cone positionsfor(x,y),idinzip(cone_positions,data['id']):# Move the cones according to the distance between rear axle and lidarx-=0.57# Save the cone positions directly to the message if noise is not appliedifnotAPPLY_NOISE:cone_list_msg.cones.append(ConePosition(x=x,y=y,id=int(id),probability=0.9,is_lidar=True))continue# calculate polar coordinatesangle=np.arctan2(y,x)distance=np.sqrt(x**2+y**2)# Only consider cones within 17 metersifdistance>17:continue# Add noise to the cone positionsifNOISE_TYPE==NoiseType.SYSTEMATIC:passnew_angle=anglenew_distance=0.9*distanceelifNOISE_TYPE==NoiseType.GAUSSIAN:angle_uncertainty=np.deg2rad(1)distance_uncertainty=0.15+0.05*distance# sample from the normal distributionnew_angle=np.random.normal(angle+np.deg2rad(5),angle_uncertainty)new_distance=np.random.normal(distance,distance_uncertainty)x=new_distance*np.cos(new_angle)y=new_distance*np.sin(new_angle)cone_list_msg.cones.append(ConePosition(x=x,y=y,id=int(id),probability=0.9,is_lidar=True))# Publish the messagerospy.loginfo("[Local Mapping] Publishing cone positions message")pub.publish(cone_list_msg)# Send the message again after a short duration to make slam send landmarks after alignmentrospy.sleep(0.5)cone_list_msg.header.stamp=rospy.Time.now()cone_list_msg.image_header.stamp=rospy.Time.now()cone_list_msg.lidar_header.stamp=rospy.Time.now()pub.publish(cone_list_msg)# Sleep for a short duration to ensure the message is sentrospy.sleep(1)
if__name__=='__main__':# Check if test_track/test_day is setifnotrospy.has_param('/test_track/track_layout')ornotrospy.has_param('/test_track/test_day'):rospy.logerr("[Local Mapping Simulation] Let's talk about starting SLAM first.")exit(69)test_track=rospy.get_param('/test_track/track_layout')test_day=rospy.get_param('/test_track/test_day')try:publish_cone_positions(test_track,test_day)exceptrospy.ROSInterruptException:traceback.print_exc()pass