High CPU usage and link loss when using Mission Planner's “RF Map” (Propagation) with Rover + QuadPlane

Happy New Year.

[1] Problem

  • Function : “RF Map” Option in Propagation Settings(CTRL + W)

  • How to Reproduce : When the “RF Map” option is enabled, Mission Planner is connected to both a Rover and a QuadPlane simultaneously, and Rover’s hdop is good, a LOS(Line-Of-Sight) circle is drawn on the map, At this point, CPU usage becomes very high, and the Rover connection is not well estabilished(heartbeat is not received for more than ~3 seconds)

  • on 1 laptop(SITL) CPU usage reaches very high even though the circle is not drawing.
    on 1 laptop(Actual Aircraft) CPU usage reaches nearly 100% only while the circle is being drawn.

[2] What I tried

public override void OnRender(IGraphics g)
{
    base.OnRender(g);

    PointLatLng? center = GetCenter(); // get aircraft and rover coordinates

    GPoint centerGp = Control.FromLatLngToLocal(center.Value);
    GPoint mapPosGp = Control.FromLatLngToLocal(Control.Position);

    float cx = (float)(centerGp.X - mapPosGp.X);
    float cy = (float)(centerGp.Y - mapPosGp.Y);
    
    Color color = ConvertRingColor(ringColor);
        
    PointLatLng TopLeft = new PointLatLng(Control.ViewArea.Lat, Control.ViewArea.Lng);
    PointLatLng BottomRight = new PointLatLng(Control.ViewArea.Lat - Control.ViewArea.HeightLat, Control.ViewArea.Lng + Control.ViewArea.WidthLng);

    GPoint PointTopLeft = Control.FromLatLngToLocal(TopLeft);
    GPoint PointBottomRight = Control.FromLatLngToLocal(BottomRight);

    float viewWidth = Control.Width - mapPosGp.X;
    float viewHeight = Control.Height - mapPosGp.Y;

    double metersPerPixel = Control.MapProvider.Projection.GetGroundResolution((int)Control.Zoom, center.Value.Lat);

    using (Pen pen = new Pen(color, 2))
    {
        pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash;

        for (int i = 1; i <= number_of_rings; i++)
        {
            double radiusMeters = scale * i * NM_TO_METER;
            float radiusPixels = (float)(radiusMeters / metersPerPixel);
            float radiusSq = radiusPixels * radiusPixels;

            // 1. Closest Point from circle to screen
            float closestX = Math.Max(0-mapPosGp.X, Math.Min(cx, viewWidth)); 
            float closestY = Math.Max(0-mapPosGp.X, Math.Min(cy, viewHeight));
            float dxMin = cx - closestX;
            float dyMin = cy - closestY;
            float minDistanceSq = (dxMin * dxMin) + (dyMin * dyMin);

            if (minDistanceSq > radiusSq)
            {
                // Console.WriteLine($"Skip. minDistanceSq : {minDistanceSq}, radiusSq : {radiusSq}");
                continue;
            }

            // 2. Farthest point from circle to screen
            float farX = Math.Max(Math.Abs(cx - 0), Math.Abs(cx - viewWidth));
            float farY = Math.Max(Math.Abs(cy - 0), Math.Abs(cy - viewHeight));
            float maxDistanceSq = (farX * farX) + (farY * farY);

            if (maxDistanceSq < radiusSq) continue; 

            // 3. Passing above two conditions, drawing line cross the screen
            // Console.WriteLine($"Drawing Circle : {i}");
            g.DrawEllipse(pen, cx - radiusPixels, cy - radiusPixels, radiusPixels * 2, radiusPixels * 2);
        } // for {}
    } // using Pen
} // OnRender

Sorry for my messy and unmanaged code, Any suggestions for improvement would be greatly appreciated.

Propagation calculation is a cpu intense process, since it needs to check terrain data between home and max distance for every angle.
You can increase azimuth step to speed up the calculation (by decreasing the “circle resolution”)

1 Like