ทดสอบ 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
- เปิดโปรแกรมทดสอบ OpenGPSProject เปิด project ไฟล์ opengpstest.lpi แล้วกด F9 เพื่อรันได้เลย สังเกตว่าการ compile & build ใน Linux จะเร็วมากกว่าบนวินโดส์เทียบกันไม่ติด แต่ตอนรันโปรแกรมดูเหมือนในวินโดส์ทำงานได้เร็วกว่า
- เปิดไฟล์ NMEA ที่อยู่ในโฟลเดอร์ Data ชื่อไฟล์ gpslog-mod.txt แล้วคลิกปุ่ม “Play 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 ในวินโดส์และลินุกส์ บนวินโดส์ผมทดสอบเรียบร้อยแล้วใช้งานได้ดี แต่ในลินุกส์ยังไม่ได้ทดสอบ ก็มารอดูกันครับ ติดตามตอนหน้าซึ่งจะเป็นตอนสุดท้าย