function updateVisuals = exampleHelperUpdateEgoMap(egoMap, scene, lidarSensors)
%exampleHelperUpdateEgoMap Updates the layers of the egoMap with readings from DSD lidars

%   Copyright 2020 The MathWorks, Inc.

    if mod(round(scene.SimulationTime,2),lidarSensors{1}.UpdateInterval)~=0
        updateVisuals = false;
        return
    end
    actors = scene.Actors;
    egoVehicle = actors(1);
    
    % Provide upper bound for raycasting
    egoRangeLimits = sqrt(max(abs(egoMap.XLocalLimits))^2 + max(abs(egoMap.YLocalLimits))^2);
    
    % Convert all vehicle poses to the ego frame
    tgts = targetPoses(egoVehicle);
    
    for i = 1:numel(lidarSensors)
        % Retrieve readings from lidar
        sensor = lidarSensors{i};
        [ptCloud, updateVisuals] = sensor(tgts, scene.SimulationTime);
        if ~updateVisuals
            return;
        else
            % Insert point cloud
            maxSensorRange = min(sensor.MaxRange, egoRangeLimits);
            insertPointCloudNanIsMax(sensor,i,egoMap,egoVehicle,ptCloud,maxSensorRange);
        end
    end
end

function insertPointCloudNanIsMax(sensor, i, egoMap, egoVehicle, ptCloud, maxSensorRange)
    % Retrieve endpoints (order does not matter so reshape without
    % randperm is ok)
    
    % Convert NaN readings to maxRange readings
    xy = reshape(ptCloud.Location(:,:,1:2),[],2);
    isMax = any(isnan(xy),2);
    ang = ((find(isMax)-1)*sensor.AzimuthResolution + sensor.AzimuthLimits(1))/180*pi;
    xy(isMax(:),:) = [cos(ang(:)) sin(ang(:))]*maxSensorRange+.01;
    endPts = xy;
    
    % Convert to lidarScan object
    scan = lidarScan(endPts(~any(isnan(endPts),2),:));

    % Update corresponding layer
    occLayer = getLayer(egoMap, egoMap.LayerNames{i});
    ePose = [egoVehicle.Position(1:2) egoVehicle.Yaw/180*pi];
    pose = [ePose(1:2) + ([cos(ePose(3)) -sin(ePose(3)); sin(ePose(3)) cos(ePose(3))]*sensor.SensorLocation(:))' ePose(3)+sensor.Yaw/180*pi];
    insertRay(occLayer, pose, scan, maxSensorRange);
end