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
- Tested on two different laptops, with the same result. Tested with both SITL and actual aircraft.
- I found the related code here, but I have no idea :
MissionPlanner/ExtLibs/Maps/Propagation.cs at e873bcc33cc205d43004d48668c668346b7eaac6 · ArduPilot/MissionPlanner · GitHub
MissionPlanner/ExtLibs/Utilities/SightGen.cs at e873bcc33cc205d43004d48668c668346b7eaac6 · ArduPilot/MissionPlanner · GitHub - With a plugin, I was able to draw similar graphics without high CPU usage, I avoided drawing circles that are outside the visible screen area. :
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.
