การเขียนโปรแกรมต่อ GPS ด้วยคอมโพเน็นต์ OpenGPSX (ภาค 5)

ทดสอบ OpenGPSX บน Ubuntu

  • มาลองทดสอบกันบน Ubuntu Lucid ก็เริ่มจากดาวน์โหลดคอมโพเน็นต์ มาก่อน ทำการติดตั้งเหมือนในวินโดส์ ที่ผมกล่าวไปแล้ว เนื่องจากโค้ดของ Lazarus เป็น cross-platform โค้ดที่ใช้ใน Windows ก็สามารถนำมาใช้ได้เลยใน Linux แต่ติดขัดตรงโปรแกรมที่จะใช้ทดสอบ ผมจะแยกเวอร์ชั่นวินโดส์และเวอร์ชั่น Linux เพราะฟอร์มที่สร้างในวินโดส์ ถ้านำมาใช้ใน Linux ตัวหนังสือ object ที่เราแปะลงฟอร์มเช่น Label, Edit จะใหญ่มากเพราะปัญหาเรื่อง Font ที่ไม่ตรงกันของสอง OS

ดาวน์โหลดและติดตั้ง

  • สนใจโปรแกรมทดสอบดาวน์โหลดได้ตามลิงค์นี้ OpenGPSProject.zip
  • เปิด Lazarus ติดตั้งคอมโพเน็นต์ OpenGPSX ก่อน แล้วค่อย unzip ไฟล์ทดสอบ OpenGPSProject.zip ของผมเองเก็บไว้ที่ /home/priabroy/Lazarus/OpenGPSProject
หน้าตาของ Lazarus ที่ติดตั้ง component OpenGPSX แล้ว
  • เปิดโปรแกรมทดสอบ OpenGPSProject เปิด project ไฟล์ opengpstest.lpi แล้วกด F9 เพื่อรันได้เลย สังเกตว่าการ compile & build ใน Linux จะเร็วมากกว่าบนวินโดส์เทียบกันไม่ติด แต่ตอนรันโปรแกรมดูเหมือนในวินโดส์ทำงานได้เร็วกว่า
  • เปิดไฟล์ NMEA ที่อยู่ในโฟลเดอร์ Data ชื่อไฟล์ gpslog-mod.txt แล้วคลิกปุ่ม “Play NMEA >>”
เปิดไฟล์ NMEA คือไฟล์ gpslog-mod.txt
  • ลองทดสอบกันอีกไฟล์คือไฟล์ griffith-park.nmea จะเห็นหน้าตาตอนรันโปรแกรมดังนี้
ทดสอบด้วยไฟล์ griffith-park.nmea

ปัญหาของโค้ด Cross-platform

  • ผมมีเกร็ดจะเล่าคือเรื่องปํญหาโค้ด cross-platform จากสโลแกนของ Lazarus ที่ว่า Write Once Compile Anywhere ผมเห็นว่าไม่ร้อยเปอร์เซ็นต์ อย่างเช่น Class TGPSSkyplot โค้ดที่ใช้ได้ในวินโดส์กลับไม่ work ใน Linux  TGPSSkyplot เป็น class ที่ผมใช้เขียนสัญลักษณ์ GPS บนท้องฟ้า ในวินโดส์ใช้การเขียน Sprite ได้ แต่กลับใช้ไม่ได้ใน Linux ต้องหันมาใช้วิธีอื่น ลองดูโค้ดกันครับ
      [sourcecode language=”delphi”]

 

      procedure TGPSSkyPlot.DrawGPSSkyPlot(ASatInfos : TGSVInfos);

 

      var

 

      rSat, rFull : TRect;

 

      r : TRect;

 

      sk1, img1 : TPoint;

 

      x, y : integer;

 

      i : integer;

 

      dDist : double;

 

      Sat : TGSVInfo;

 

      ts : TSize;

 

      begin

 

      if Assigned(ASatInfos) then

 

      begin

 

      FGSVInfos := ASatInfos;

rSat := Rect(0, 0, FSatSize, FSatSize);
rFull := Rect(0, 0, FBmpBackground.Width, FBmpBackground.Height);
//First Sat, Copy FBufferBackgroundImg to FBmpBuffer.
if (TGSVInfo(FGSVInfos.items[0]).FirstSat) then
FBmpBuffer.Canvas.CopyRect(rFull, FBmpBackground.Canvas, rFull);

for i := 0 to FGSVInfos.Count – 1 do
begin
Sat := TGSVInfo(FGSVInfos.Items[i]);
dDist := (90 – Sat.Elevation) * FSkyHalfW / 90;
sk1 := Polar2Cartesian(trunc(dDist),Sat.Azimuth);
img1 := Cartesian2Pixel(sk1, FTransfrm);
//Keep image coordinate system into TSatInfo.
Sat.X := img1.X;
Sat.Y := img1.Y;
{Draw Sprites works very well in WINDOWS, Not in Linux}
{$IFDEF WINDOWS}
BitBlt(FBmpSatDest[i].Canvas.Handle, 0, 0, FBmpSatDest[i].Width, FBmpSatDest[i].Height,
FBmpBuffer.Canvas.Handle, img1.X – FImgShift, img1.Y – FImgShift, SRCCOPY);
BitBlt(FBmpSatDest[i].Canvas.Handle, 0, 0, FBmpSatDest[i].Width, FBmpSatDest[i].Height,
FBmpMaskSat.Canvas.Handle, 0, 0, SRCAND);
if (Sat.SNR = 0) then
BitBlt(FBmpSatDest[i].Canvas.Handle, 0, 0, FBmpSatDest[i].Width, FBmpSatDest[i].Height,
FBmpRedSpriteSat.Canvas.Handle, 0, 0, SRCINVERT)
else
BitBlt(FBmpSatDest[i].Canvas.Handle, 0, 0, FBmpSatDest[i].Width, FBmpSatDest[i].Height,
FBmpGreenSpriteSat.Canvas.Handle, 0, 0, SRCINVERT);
{$ENDIF}
{$IFDEF LINUX}
BitBlt(FBmpSatDest[i].Canvas.Handle, 0, 0, FBmpSatDest[i].Width, FBmpSatDest[i].Height,
FBmpBuffer.Canvas.Handle, img1.X – FImgShift, img1.Y – FImgShift, SRCCOPY);
if (Sat.SNR = 0) then
FBmpSatDest[i].Canvas.Draw(0, 0, FRedSatImg)
else
FBmpSatDest[i].Canvas.Draw(0, 0, FGreenSatImg);
{$ENDIF}
BitBlt(FBmpBuffer.Canvas.Handle, img1.X – FImgShift, img1.Y – FImgShift,
FBmpSatDest[i].Width, FBmpSatDest[i].Height, FBmpSatDest[i].Canvas.Handle, 0, 0, SRCCOPY);

//************* Draw PRN ********************
with FBmpTxtDest[i] do
begin
//Assumed image size to valid for Canvas.Font.
Width := 10;
Height := 10;
Canvas.Font.Color := clBlack;
Canvas.Font.Style := [fsBold];
Canvas.Font.Name := ‘Sans’;
Canvas.Font.Size := trunc(8/20 * FSatSize);
ts := Canvas.TextExtent( Sat.Prn);
//The real size.
Width := ts.cx;
Height := ts.cy;
Canvas.Brush.Style := bsClear;
Canvas.Brush.Color := self.Color;
x := img1.X – Width div 2 – 2;
y := img1.Y + FSatSize div 2 – 2;
r := Rect(0 , 0, Width, Height);
BitBlt(Canvas.Handle, 0, 0, Width, Height,
FBmpBuffer.Canvas.Handle, x, y, SRCCOPY);
Canvas.TextOut(0, 0, Sat.PRN);
BitBlt(FBmpBuffer.Canvas.Handle, x, y, Width, Height, Canvas.Handle, 0, 0, SRCCOPY);
//Last Sat, Copy FBmpBuffer to TGPSSkyplot Canvas.
if (Sat.LastSat) then
BitBlt(self.Canvas.Handle, 0, 0, FBmpBuffer.Width, FBmpBuffer.Height, FBmpBuffer.Canvas.Handle, 0, 0, SRCCOPY);
end;
end; //for
end;
end;

[/sourcecode]

  • จะเห็นว่าผมต้องแยกโค้ดในวินโดส์และ Linux ด้วยการใช้ directive {$IFDEF} ที่ต้องแยกโค้ดแบบนี้ก็ไม่มากมายหรอกครับ บางครั้งก็สถานการณ์ก็บังคับเช่น hardware อย่าง serial port ในวินโดส์จะเริ่มตั้งแต Com1, Com2, Com3,… ส่วนในลินุกส์เริ่มจาก /dev/ttys0, /dev/ttys1, /dev/ttys2,…
  • ก็ขอจบตอนนี้ไว้ก่อน ตอนหน้ามาดูว่าถ้าต่อ GPS ผ่าน serial port ในวินโดส์และลินุกส์ บนวินโดส์ผมทดสอบเรียบร้อยแล้วใช้งานได้ดี แต่ในลินุกส์ยังไม่ได้ทดสอบ ก็มารอดูกันครับ ติดตามตอนหน้าซึ่งจะเป็นตอนสุดท้าย

Leave a Reply

Your email address will not be published. Required fields are marked *