Author: priabroy

ทดสอบเขียนโปรแกรมไพทอน (Python)  บนเครื่องคิดเลข Casio fx-cg50 Prizm

ทดสอบเขียนโปรแกรมไพทอน (Python) บนเครื่องคิดเลข Casio fx-cg50 Prizm

ไพทอนบนเครื่องคิดเลข

ช่วงนี้ผมมีโอกาสทำงานใกล้ชิดกับภาคสนาม ทำให้มีโอกาสได้จับและใช้เครื่องคิดเลขมากกว่าปกติ ในเวลาที่ผ่านมาไม่ถึงเดือนผมได้ซื้อเครื่องคิดเลข Casio fx-CG50 Prizm เคสสีขาว ที่ซื้อมาเพราะทราบว่าถ้า update OS เป็นรุ่น 3.20 จะสามารถใช้ ไพทอน (Python) ได้ ก็ขอหมายเหตุสักนิดว่าเป็นไมโครไพทอน (Micropython) ที่ทางทีมงาน Micropython ได้พอร์ตออกมาให้มีขนาดเล็กเพื่อเอาไปรันในบอร์ด iOT ได้ หรือบอร์ดที่เป็นไมโครคอนโทรลเลอร์ทั้งหลาย เน้นขนาดเล็ก หน่วยความจำต่ำ กินไฟน้อย ต่ออินเทอร์เน็ตได้ในตัว ผมจะไม่มุ่งไปทางนี้หรอกครับ ในบทความนี้ แต่จะพูดถึงเครื่องคิดเลขคาสิโอ ที่นำเอาไมโครไพทอนมาลงเครื่องคิดเลขรุ่นนี้ เพราะว่าไมโครไพทอนกินหน่วยความจำต่ำ ก็เลยเหมาะสมที่จะเอามารันในเครื่องคิดเลขที่มีทรัพยากรต่ำอยู่แล้ว ให้เกิดประสิทธิภาพมากยิ่งขึ้นไป

เป็นที่ทราบกันว่าไพทอนในปัจจุบันมีความนิยมมากยิ่งขึ้น เนื่องจากเรียนรู้ได้ง่าย เขียนง่าย อ่านง่าย ทรงพลัง แต่สำหรับไมโครไพทอน เนื่องจากออกแบบให้มีขนาดเล็ก ดังนั้นไลบรารีต่างๆที่ใช้ได้ในไพทอนรุ่นใหญ่ จะสามารถนำมาใช้กับไมโครไพทอนได้ต้องมีการพอร์ตใหม่ อาจจะลดฟังก์ชั่นหรือลดสิ่งไม่จำเป็นออก ทำให้มีขนาดเล็กลง ดังนั้นผมทำใจในจุดนี้อยู่แล้ว ว่าไม่สามารถเอาไลบรารีรุ่นใหญ่มารันได้แน่นอนเช่น pyproj, mathplotlib

สำหรับเครื่องคิดเลขที่ใช้ในแวดวงวิศวกรรม โปรแกรมที่เขียนด้วยไมโครไพทอนที่มีไลบรารี math หรืออาจจะเสริมด้วยไลบรารีพวกเมตริก (matrix) น่าจะพอนำมาเขียนใช้งานกันได้

 การพัฒนาโปรแกรมด้วยชุดพัฒนาโปรแกรมภาษาซี (Software Development Kit)

นี่เป็นความข้องใจของผมในฐานะแฟนเครื่องคิดเลขคาสิโอ รุ่น fx-9860G ทางคาสิโอจัดทำ SDK ให้สามารถเขียนโปรแกรมด้วยภาษาซี ที่ผมเขียนโปรแกรมมาแจกใช้ในแวดวงงานสำรวจแล้วหลายโปรแกรม แต่รุ่นนี้กลับไม่ทำมาให้  (ที่จริงไม่ทำมาให้ตั้งแต่ fx-CG10/fx-CG20)ไม่ทราบว่าเพราะเหตุใด เครื่องคิดเลขรุ่นนี้ไม่มี SD Card แต่ทดแทนด้วยการใส่ Flash memory มา 16 MB  ซึ่งก็พอจะใส่โปรแกรมใช้งานได้มากโขอยู่ หรือคิดว่ามีไมโครไพทอน มาให้แล้วน่าจะตอบโจทย์ได้หมด แต่ผมก็ไม่คิดอย่างนั้น ยังมีโปรแกรมเมอร์ภาษาซีอีกพอสมควร และในสภาพแวดล้อมของเครื่องคิดเลขจริงๆ โปรแกรมที่เขียนด้วยภาษาซีจะเร็วกว่าไพทอนอยู่แล้ว แต่ไพทอนได้เปรียบในด้านความง่าย

 เครื่องมือพัฒนาโปรแกรมของชุมชน

ยังมีชุมชนของนักพัฒนาที่สร้าง SDK  ขึ้นมาใช้งานเอง มีประมาณ 2-3 กลุ่มแต่สุดท้ายดูเหมือนไม่มีความเคลื่อนไหวกันมาหลายปีแล้ว เครื่องมือที่มีชื่อเสียงมากที่สุดคือ PrizmSDK และอีกอันคือ mini-SDK ผมเองใช้ไลบรารี MyLib แต่เผอิญผู้พัฒนาได้ทำไว้สำหรับเครื่อง fx-9860G เท่านั้น ไม่เป็นไรขอมุ่งลองไพทอนบนเครื่องคิดเลขรุ่น fx-CG50 นี้ก่อน ถ้าพัฒนาโปรแกรมด้วยภาษาซี ผมก็ยังมุ่งไปที่เครื่องคิดเลข fx-9860G เหมือนเดิม 

ผมลองเขียนโปรแกรมทดสอบเล็กๆลองดูด้วยเครื่องมือ PrizmSDK ก็ได้ดังรูปข้างล่าง (โปรแกรมไม่มีอะไรมีแต่เมนู) เทียบกับโปรแกรม System Manager ที่มากับเครื่อง

คุณสมบัติของเครื่องคิดเลข

โดยรวมรวมแล้วเครื่องคิดเลขนั้นเหมาะสำหรับนักศึกษามาก เพราะมีฟังก์ชั่นคณิตศาสตร์ การเงิน สถิติ มีกราฟมากมายให้ใช้ แต่สำหรับผมแล้วไม่มีอะไรต้องใช้เลย ยกเว้นเรื่องโปรแกรมบนเครื่องคิดเลขอย่างเดียว ถ้าไม่มีสิ่งนี้ก็ใช้เป็นที่ทับกระดาษได้เลย เครื่องรุ่นนี้ใช้โปรเซสเซอร์ตระกูล SH4 ขนาดหน้าจอ 384 x 216 จอ LCD จำนวนสี 65000 สี มีความสว่างพอสมควรและปรับได้ ความกว้างหน้าจอแบบทะแยง 3.17 นิ้ว หน่วยความจำของเครื่อง 60 KB มี Flash memory ที่สามารถเขียนอ่านได้ 16  MB ซึ่งจะเป็นที่เอาไว้เก็บโปรแกรมหรือข้อมูล ใช้ถ่าน AAA 4 ก้อน  เท่าที่ผมเปิดเครื่องใช้บ้างในแต่ละวันมาประมาณสองสัปดาห์ พบว่าแบตเตอรี่ลดลงมานิดหนึ่ง อนาคตอาจจะหาถ่านชาร์จมาใช้ ตอนนี้ใส่อัลคาไลน์ไปก่อน

ประเดิมโปรแกรมด้วยไพทอน

จะลองโปรแกรมทั้งทีผมพยายามให้โปรแกรมมีขนาดซับซ้อนมานิดหนึ่ง  และเรียกใช้โมดูลด้วย คิดไปคิดมาก็เลยจะลองโปรแกรมแปลงค่าพิกัดระหว่างค่าพิกัดภูมิศาสตร์กับค่าพิกัดยูทีเอ็ม เนื่องจากไม่ค่อยมีเวลาเขียน เลยลองหาไลบรารีที่ท่านอื่นได้ทำไว้ ผมเคยเกริ่นไปแล้วข้างต้นว่าไลบรารีรุ่นใหญ่เช่น pyproj ไม่สามารถเอามาใช้ได้ ลองค้นดูพบว่ามีไลบรารีไพทอนเล็กๆ ชื่อ utm มีสัญญาอนุญาตเป็น MIT-License ผมเอาโค้ดมาดัดแปลงนิดหน่อยให้เหมาะสมกับเครื่องคิดเลข แล้วเขียนไปอยู่ในไฟล์ utm.py เพื่อให้สะดวกเวลาเรียกใช้

การเขียนโปรแกรมไพทอน ถ้าไปเขียนบนเครื่องคิดเลข จะชักช้าเสียเวลาครับ เนื่องจากไมโครไพทอน พอร์ตไลบรารีเช่น math แล้ว ดังนั้นถ้าโปรแกรมของเราไม่ได้ใช้อะไรพิศดารมาก ก็สามารถมาเขียนโค้ดบน PyCharm หรือ Idle ได้ ผมเลือก PyCharm เมื่อทดสอบโปรแกรมเสร็จสามารถ โอนโปรแกรมเข้าไปไว้ในเครื่องด้วยการต่อเครื่องคิดเลขด้วยสาย USB เข้ากับคอมพิวเตอร์ที่รันวินโดส์ตามผังด้านล่าง

เมื่อรันโปรแกรมได้ตามความต้องการแล้วจากนั้นก็เอาเครื่องคิดเลขมาต่อกับคอมพิวเตอร์ วินโดส์จะมองเห็นเป็นไดรว์ สามารถใช้ File Explorer ก๊อปปี้โปรแกรมจากคอมพิวเตอร์ไปยังเครื่องคิดเลขได้ ตัวโค้ดโปรแกรมไลบรารีดูได้ด้านล่างครับ


import math
K0 = 0.9996

E = 0.00669438
E2 = E * E
E3 = E2 * E
E_P2 = E / (1.0 - E)

SQRT_E = math.sqrt(1 - E)
_E = (1 - SQRT_E) / (1 + SQRT_E)
_E2 = _E * _E
_E3 = _E2 * _E
_E4 = _E3 * _E
_E5 = _E4 * _E

M1 = (1 - E / 4 - 3 * E2 / 64 - 5 * E3 / 256)
M2 = (3 * E / 8 + 3 * E2 / 32 + 45 * E3 / 1024)
M3 = (15 * E2 / 256 + 45 * E3 / 1024)
M4 = (35 * E3 / 3072)

P2 = (3. / 2 * _E - 27. / 32 * _E3 + 269. / 512 * _E5)
P3 = (21. / 16 * _E2 - 55. / 32 * _E4)
P4 = (151. / 96 * _E3 - 417. / 128 * _E5)
P5 = (1097. / 512 * _E4)

R = 6378137

ZONE_LETTERS = "CDEFGHJKLMNPQRSTUVWXX"

class OutOfRangeError(ValueError):
    pass

def to_latlon(easting, northing, zone_number, hemi):

    northern = (hemi == 'N')

    x = easting - 500000
    y = northing

    if not northern:
        y -= 10000000

    m = y / K0
    mu = m / (R * M1)

    p_rad = (mu +
             P2 * math.sin(2 * mu) +
             P3 * math.sin(4 * mu) +
             P4 * math.sin(6 * mu) +
             P5 * math.sin(8 * mu))

    p_sin = math.sin(p_rad)
    p_sin2 = p_sin * p_sin

    p_cos = math.cos(p_rad)

    p_tan = p_sin / p_cos
    p_tan2 = p_tan * p_tan
    p_tan4 = p_tan2 * p_tan2

    ep_sin = 1 - E * p_sin2
    ep_sin_sqrt = math.sqrt(1 - E * p_sin2)

    n = R / ep_sin_sqrt
    r = (1 - E) / ep_sin

    c = _E * p_cos**2
    c2 = c * c

    d = x / (n * K0)
    d2 = d * d
    d3 = d2 * d
    d4 = d3 * d
    d5 = d4 * d
    d6 = d5 * d

    latitude = (p_rad - (p_tan / r) *
                (d2 / 2 -
                 d4 / 24 * (5 + 3 * p_tan2 + 10 * c - 4 * c2 - 9 * E_P2)) +
                 d6 / 720 * (61 + 90 * p_tan2 + 298 * c + 45 * p_tan4 - 252 * E_P2 - 3 * c2))

    longitude = (d -
                 d3 / 6 * (1 + 2 * p_tan2 + c) +
                 d5 / 120 * (5 - 2 * c + 28 * p_tan2 - 3 * c2 + 8 * E_P2 + 24 * p_tan4)) / p_cos

    return (180/math.pi*(latitude),
            180/math.pi*(longitude) + zone_number_to_central_longitude(zone_number))


def from_latlon(latitude, longitude, force_zone_number=None):
    if not -80.0 <= latitude <= 84.0:
        raise OutOfRangeError('latitude out of range (must be between 80 deg S and 84 deg N)')
    if not -180.0 <= longitude <= 180.0: raise OutOfRangeError('longitude out of range (must be between 180 deg W and 180 deg E)') lat_rad = math.pi/180*(latitude) lat_sin = math.sin(lat_rad) lat_cos = math.cos(lat_rad) lat_tan = lat_sin / lat_cos lat_tan2 = lat_tan * lat_tan lat_tan4 = lat_tan2 * lat_tan2 if force_zone_number is None: zone_number = latlon_to_zone_number(latitude, longitude) else: zone_number = force_zone_number #zone_letter = latitude_to_zone_letter(latitude) if (latitude >= 0):
      hemi = 'N'
    else:
      hemi = 'S'

    lon_rad = math.pi/180*(longitude)
    central_lon = zone_number_to_central_longitude(zone_number)
    central_lon_rad = math.pi/180*(central_lon)

    n = R / math.sqrt(1 - E * lat_sin**2)
    c = E_P2 * lat_cos**2

    a = lat_cos * (lon_rad - central_lon_rad)
    a2 = a * a
    a3 = a2 * a
    a4 = a3 * a
    a5 = a4 * a
    a6 = a5 * a

    m = R * (M1 * lat_rad -
             M2 * math.sin(2 * lat_rad) +
             M3 * math.sin(4 * lat_rad) -
             M4 * math.sin(6 * lat_rad))

    easting = K0 * n * (a +
                        a3 / 6 * (1 - lat_tan2 + c) +
                        a5 / 120 * (5 - 18 * lat_tan2 + lat_tan4 + 72 * c - 58 * E_P2)) + 500000

    northing = K0 * (m + n * lat_tan * (a2 / 2 +
                                        a4 / 24 * (5 - lat_tan2 + 9 * c + 4 * c**2) +
                                        a6 / 720 * (61 - 58 * lat_tan2 + lat_tan4 + 600 * c - 330 * E_P2)))

    if latitude < 0:
        northing += 10000000

    return easting, northing, zone_number, hemi


def latitude_to_zone_letter(latitude):
    if -80 <= latitude <= 84: return ZONE_LETTERS[int(latitude + 80) >> 3]
    else:
        return None


def latlon_to_zone_number(latitude, longitude):
    if 56 <= latitude < 64 and 3 <= longitude < 12:
        return 32

    if 72 <= latitude <= 84 and longitude >= 0:
        if longitude <= 9:
            return 31
        elif longitude <= 21:
            return 33
        elif longitude <= 33:
            return 35
        elif longitude <= 42:
            return 37

    return int((longitude + 180) / 6) + 1


def zone_number_to_central_longitude(zone_number):
    return (zone_number - 1) * 6 - 180 + 3


โปรแกรมแปลงพิกัดภูมิศาสตร์ในภาคไพทอน

ผมเขียนไพทอนเป็นโมดูลอีกโมดูลเพื่อเรียกใช้ไลบรารี ตั้งชื่อว่า UTM2GEO.py โดยที่เขียนเมนูติดต่อการใช้งานง่ายๆ

from utm import *
   
def print_menu():
  print(5*'-',"MENU",5*'-')
  print('1: UTM to GEO')
  print('2: GEO to UTM')
  print('0: Exit')

def geo2utm(lon,lat):
  east,north,zn,hem=from_latlon(lat,lon)
  print("North={0:11.3f}".format(north))
  print("East={0:10.3f}".format(east))  
  print("UTM Zone No={0:0d}{1}".format(zn,hem))
    
def utm2geo(e,n,zoneno,hemi):
  lat,lon=to_latlon(e,n,zoneno,hemi)
  print("Latitude={0:11.7f}".format(lat))
  print("Longitude={0:10.7f}".format(lon))   
    
loop=True
while loop:   
  print_menu()
  choice=int(input('Selection[0-2]'))
  if (choice==0):
    loop=False
  elif (choice==1):
    loop=True
    y=float(input("Northing="))
    x=float(input("Easting="))
    zn=int(input("Zone No="))
    hem=input("Hemi (N/S)=")
    utm2geo(x,y,zn,hem)
  elif (choice==2):
    loop=True
    y=float(input("Latitude="))
    x=float(input("Longitude="))
    geo2utm(x,y)   

วิธีก๊อปปี้โปรแกรม

จากนั้นผมก๊อปปี้สองไฟล์คือ utm.py  และ UTM2GEO.py ลงบนไดรว์เครื่องคิดเลขดังนี้

ผมเก็บไว้ที่ไดเรคทอรี \SAVE-F\PROGRAM เวลาจะถอดสาย USB เพื่อเลิกการเชื่อมต่อต้อง Safely removal โดยการคลิกเมาส์ขวา “Eject” ที่ File Explorer จากนั้นมาที่เครื่องคิดเลขจากให้กดคีย์ “EXE” และ “EXIT” ตามลำดับ ถ้าไม่ทำไฟล์อาจจะไม่ได้ซิงค์กันอาจจะหายหรือไม่สมบูรณ์ได้ ที่เครื่องคิดเลขกดคีย์ “MENU” เลือก “Python

แปลงพิกัดจากค่าพิกัดภูมิศาสตร์เป็นค่าพิกัดยูทีเอ็ม

จากรูปด้านบนกดคีย์ F1-Run จะเห็นหน้าจอขึ้นเมนูติดต่อมาง่ายๆ

เราจะเลือกแปลงพิกัดจากค่าพิกัดภูมิศาสตร์ไปเป็นค่าพิกัดยูทีเอ็มเลือกกดคีย์ “2” ที่เครื่องคิดเลขแล้วกดคีย์ “EXE” ป้อนค่าพิกัด Latitude = 39.95259668 Longitude  = -75.15132081 (ป้อนเป็นหน่วยดีกรี ในตอนนี้ยังไม่รับค่าแบบอื่น) จะได้ผลการคำนวณออกมา เนื่องจากในตอนนี้ไม่มีคำสั่งเบรคการแสดงผลเมื่อเขียนด้วยไพทอน (เอาละจะมาบ่นทีหลัง ว่าใส่ไพทอนมาแล้วทางคาสิโอไม่ให้เครื่องมืออะไรมาเลย) การจะดูผลลัพธ์ ผู้ใช้ต้องกดคีย์ “0” เพื่อออกจากโปรแกรมและใช้ลูกศรกดขึ้นไปทางด้านบนเพื่อไปดูผลลัพธ์

จะได้ค่า Northing = 4422506.896 Easting = 487074.371 อยู่ในโซน 18N

แปลงพิกัดจากค่าพิกัดยูทีเอ็มเป็นค่าพิกัดภูมิศาสตร์

ทำการรันโปรแกรมใหม่อีกครั้ง ที่เมนูเลือกกดเลข “1” ป้อนค่าพิกัด Northing = 2642783.110 Easting =232030.949 UTM Zone No = 46 Hemi = N

ดูค่าผลลัพธ์ได้ (กดคีย์ “0” ออกจากเมนูก่อนแล้วเลื่อนขึ้นไปดู)

สรุปการใช้งาน

ตอนแรกผมคาดหวังจากที่ทางคาสิโอเอาไมโครไพทอนมาลงเครื่องคิดเลขรุ่นนี้ ยังไงการเขียนโปรแกรมใช้งานยังไงๆผลลัพธ์ที่ออกมาก็ต้องระดับเทพ เพราะไพทอนมันทรงพลังด้วยตัวของมัน แต่เมื่อลองแล้วผิดหวังมาก จนบัดนี้คาสิโอ้ยังไม่ได้ออกคู่มือแสดงฟังก์ชั่นที่ไพทอนสามารถเรียกมาใช้ได้ มีฟังก์ชั่น input กับ print สองฟังก์ชั่นนี้เท่านั้น เพียงแค่ผมค้นหาฟังก์ชั่น clear screen หน้าจอยังทำไม่ได้ ฟังก์ชั่นที่ต้องการสนับสนุนได้แก่การเขียนเมนูที่เรียกใช้ด้วยคีย์ F1 ถึง F6 การปริ๊นท์แสดงสีต่างๆ การเรียกใช้ฟังก์ชั่นกราฟต่างๆหรือพล็อทกราฟ หรือใช้งานเมตริก เป็นต้น

เอาละตอนนี้ไพทอนที่ปรากฎบน OS รุ่น 3.20 เพิ่งออกมาเตือนตุลาคม 2018 (ขณะที่เขียนบทความนี้เดือนพฤศจิกายน 2018) คงต้องให้เวลาสักพักว่าจะเป็นอย่างไร บอกตามตรงว่าคงต้องเอาเครื่องคิดเลขรุ่นนี้มาทับกระดาษอีกสักพักใหญ่ๆ

การเล็งสกัดย้อน (Resection) ด้วยการวัดมุมภายใน ระยะทางและและมุมแบริ่งด้วยวิธีการคำนวณแบบ Least Squares (ตอนที่ 2)

 ตั้งสมการ Observation Equation

ขอทบทวน ค่า aik, bik  เรียกว่า  direction coefficients และ  cik, dik เรียกว่า distance coefficients

ในกรณีวัดมุมเล็งสกัดย้อนจากสมการด้านบนและเอาแทนที่ในสมการด้านล่าง

เขียนให้ดูง่ายดังนี้  zi  คือค่าอะซิมัทเริ่มต้น

เราจะมาคำนวณหาค่า aik, bik กันก่อน มาคำนวณที่จุด P ค่าพิกัด N = 193939.897 E = 110879.464 ไปสถานีหลักฐานจุดที่ 1  ที่มีค่าพิกัด N = 192315.290 E = 120383.500 คำนวณระยะทางได้ 9641.890 เมตร คำนวณหาอะซิมัทได้ 99°42’1.1″ ดังนั้น aik = aP1 = -sin( 99°42’1.1″) / (9641.890 * 100) * 3600 * 180/3.141592654 = -0.2109 second (มุมแปลงเป็นหน่วยฟิลิปดา ระยะทางแปลงหน่วยเป็น ซม.)

bik = bP1 = cos(99°42’1.1″) / (9641.890 * 100) * 3600 * 180/3.141592654 = -0.0360 second

เราจะฟอร์มสมการในรูปแบบ v + Bx = f โดยที่

v คือเมตริกเวคเตอร์ของ residual

B คือเมตริกของค่า coefficient ของมุม ระยะทาง

f คือเมตริกความต่างของค่าที่คำนวณและค่าที่รังวัด

ผมคำนวณหาค่าaik, bik ทุกๆการรังวัดมุมมาดังนี้

มาทบทวนดูสมการระยะทางดังนี้้

คำนวณหา cik = cP1 = cos(99°42’1.1″) = -0.1685

dik= dP1 = sin(99°42’1.1″) = 0.9857

คำนวณทุกการรังวัดระยะทางมาได้ดังตาราง

สมการสุดท้ายคือการวัดเล็งสกัด (Bearing intersection)

จากสมการ v + Bx = f มาพิจารณาฝั่งซ้าย v + Bx ก่อน ผมฟอร์มเป็นเมตริกดังนี้

มาดูเมตริก เป็นเมตริกแสดงความต่างระหว่างค่าที่คำนวณกับค่ารังวัด f = Computed – Observation มาดูตามตาราง น่าจะเข้าใจได้ง่าย ค่า diff ในตารางก็คือค่า f นั่นเอง โปรดระวังหน่วยมุมจะเป็นฟิลิปดา (second) หน่วยระยะทางใช้เป็นซม.

ยกตัวอย่างค่าของเมตริก f เริ่มจากการวัดเล็งสกัดย้อน จะใช้มุมอะซิมัทที่ได้จากการคำนวณมาเป็นตัวเริ่มต้น ค่าจากจุด P ไปสถานีหลักฐานที่ 1 จะได้ค่าความต่างเท่ากับ 0.0 ต่อไปจากจุด P ไปสถานีหลักฐานที่ 2 คำนวณได้ 119.5116959 จากมุมที่วัดมา 99° 42′ 1.1″ + 19° 48′ 41″ = 119.5116957 ได้ค่าความต่าง = (119.5116959 – 119.5116957) * 3600 =  0.0008 second

ที่ง่ายที่สุดคือวัดระยะทางจากจุด P ไปสถานีหลักฐานจุดที่ 1 ได้ 9641.795 เมตร ส่วนการคำนวณจากค่าพิกัด P เริ่มต้นมายังค่าพิกัดสถานีหลักฐาน 1 ได้ค่าคำนวณ = 9641.890 เมตร ความต่าง = (9641.890 – 9641.795) * 100 = 9.5 ซม.

สุดท้ายสามารถนำค่ามาเขียนเป็นเมตริก ดังนี้

v + Bx = f

จะเห็นว่าสมการนี้ติดค่า residual ของเมตริก v และเมตริก x ไม่สามารถคำนวณต่อไป แต่หัวใจของ least squares ตามชื่อเลยครับคือผลรวมค่ายกกำลังสองของ  residual ที่ได้ค่าน้อยที่สุด

ถ้าค่า weight หรือน้ำหนักของการรังวัดไม่เท่ากันจะต้องคูณน้ำหนักเข้าไปด้วย

จากสมการ v + Bx = f แทนค่า v = f – Bx ในสมการ

ค่า Φ จะมีค่าน้อยที่สุด ดังนั้นจะหาอนุพันธ์ (ดิฟ) โดยที่ให้ x มีค่าเท่ากับศูนย์

ที่นี้ก็จำง่าย Nx = t โดยที่ N = BTWB และ f = BTW

สุดท้ายสามารถหาค่าเมตริก x = N-1เมื่อได้ค่า x แล้วก็สามารถย้อนไปหาเมตริก residual (v) ได้ ตามสมการ v + Bx = f

ผลลัพธ์การคำนวณรอบที่ 1

ผมใช้ฟังก์ชั่นของ excel หาเมตริกได้ดังนี้


ได้เมตริก x คือค่าปรับแก้หน่วยเป็นซม. เอาพิกัดจุด P และมุมอะซิมัท เริ่มต้นมาปรับได้ดังนี้ N = 193939.897 – 0.090829= 193939.806 ค่า E = 110879.464 + 0.04695 =  110879.511 และค่ามุมอะซิมัท = 99°42’1.1″ – 2.1156″ = 99° 41′ 58.99″ (99.6997191)

ผลลัพธ์การคำนวณรอบที่ 2

เอาค่าพิกัดของจุด P ที่ได้จากรอบที่ 1 มาเป็นตัวเริ่มต้น พร้อมทั้งมุมอะซิมัทด้วย

ตั้งสมการเมตริก v + Bx = f ได้ดังนี้

แก้สมการ Nx = t ได้ดังนี้

จะได้เมตริก x ค่าใหม่ เอาพิกัดจุด P และค่าอะซิมัทมาปรับได้ดังนี้ N =193939.806  – 0.0016 = 193939.790  และ E = 110879.511 + 0.0085 = 110879.519  ค่าอะซิมัท = 99° 41′ 58.99″ + 0.137″ = 99°41′ 59.13″ (99.6997572)

ผลลัพธ์การคำนวณรอบที่ 3

ต่อไปฟอร์มรูปเมตริก v + Bx = f สังเกตว่าเมตริก B ค่าเปลี่ยนไปเล็กน้อยมาก

คำนวณหาเมตริก x จากสมการ Nx = t => x = N-1t

จะได้เมตริก x ค่าใหม่ เอาพิกัดจุด P และค่าอะซิมัทมาปรับได้ดังนี้ N = 193939.790- 0.0003 = 193939.787  และ E = 110879.519 + 0.0001 = 110879.521 ค่าอะซิมัท = 99° 41′ 58.99″ + 0.024″ = 99°41′ 59.15″ (99.6997639)

มาถึงตอนนี้จะเห็นว่าค่าปรับแก้ ในเมตริก x  น้อยมากอยู่ในระดับเศษส่วนของมิลลิเมตร ΔN = -0.285 cm ΔE = 0.152 cm ดังนั้นแสดงว่าค่าที่คำนวณมานั้น convergence แล้ว ดังนั้นผมสรุปว่าผลลัพธ์ดังนี้

ค่าพิกัดจุด P (Free Station)

N = 193939.787 E = 110879.521 ค่าอะซิมัทจากจุด P ไปสถานีหลักฐานที 1 = 99°41′ 59.15″

 ตรวจสอบผลลัพธ์การคำนวณด้วย Microsurvey StarNet

เพื่อให้มั่นใจว่าผลลัพธ์ที่ได้จะถูกต้อง ผมใช้ Microsurvey StarNet  มาเป็นตัวช่วย ข้อมูลสถานีรังวัดไม่เกิน ดังนั้นผมยังใช้เวอร์ชั่นทดลองใช้ได้อยู่ เมื่อเปิดโปรแกรมมาผมใช้เมนู Options -> Project ตั้งค่าดังนี้ เปลี่ยนหน่วยเป็นเมตรให้เรียบร้อยก่อนที่ Adjustment > Units > Linear > Meters

จากนั้นปรับ  standard error  ของกล้องวัดมุมและระยะทางให้สอดคล้อง ผมปรับระยะทาง Distance constant 4mm ปรับ Distance PPM = 20 ความหมายตัวนี้คือ 4mm ± 20mm/1,000,000 x L (m) ถ้าวัดระยะทาง 1000 เมตร error จะอยู่ประมาณ 24 mm (กล้อง Total Station สมัยปัจจุบันเรื่องระยะทางทำได้ดีกว่านี้มาก)

จากนั้นป้อนข้อมูลไปดังนี้ หมายเหตุว่า C = Control Point ไม่มีเครื่องหมาย ! !  ตามหลังแสดงว่าเป็นค่าเริ่มต้นหรือประมาณการ A = Angle, D = Distance และ B = Bearing ถ้าสนใจก็ไปดาวน์โหลดโปรแกรมของ Microsurvey StarNet  มาทดลองได้

แล้วคัดลอกข้อมูลด้านล่างแล้วไปวางลงในหน้า  input เพื่อลองคำนวณดูผลลัพธ์กันได้

# Resection 2D combined resection, distance and bearing intersection.

# Approximate coordinates for the unknown free station
#
C P 193939.897 110879.464

# Coordinates for the known stations
C 1 192315.290 120383.500 ! !
C 2 189545.730 118642.430 ! !
C 3 188084.770 112278.210 ! !
C 4 190640.940 109654.540 ! !
C 5 190044.860 108065.980 ! !
C 6 194455.370 110632.930 ! !
A P-1-2 19-48-41
A P-1-4 100-40-19
A P-1-5 116-8-36
A P-1-6 234-44-22

#Distance measurements
D P-1 9641.795
D P-3 6019.802
D P-5 4804.793

#Bearing measurements
B 1-P 279-41-59.5
B 3-P 346-33-52
B 5-P 35-50-34

จากนั้นใช้เมนู Run > Adjustment

สรุปสถิติการคำนวณดังนี้ จะเห็นว่ามีจำนวนข้อมูลรังวัดมา 10 (วัดมุมเล็งสกัดย้อน 4 มุม ระยะทาง 3 ระยะ วัดมุมเล็งสกัด 3 มุม จำนวนสิ่งที่ไม่รู้ค่า 2 ค่า คือค่าพิกัด  x,y ของจุด P

Adjustment Statistical Summary
==============================

Iterations = 2

Number of Stations = 7

Number of Observations = 10
Number of Unknowns = 2
Number of Redundant Obs = 8

 

Adjusted Coordinates (Meters)

Station N E Description
P 193939.788830 110879.521213
1 192315.290000 120383.500000
2 189545.730000 118642.430000
3 188084.770000 112278.210000
4 190640.940000 109654.540000
5 190044.860000 108065.980000
6 194455.370000 110632.930000

จะได้ค่าพิกัดจุด  P ดังนี้ N = 193939.789 E = 110879.521 ต่างจากที่ผมคำนวณมาเล็กน้อย อย่างแรกคือผมไม่ได้ใช้น้ำหนัก  weight  แต่ของ MicroSurvey Starnet บังคับใช้ โปรแกรมไม่ได้แสดงค่าสมการให้ดู จึงตรวจสอบไม่ได้ว่าเมตริกของ W เป็นอย่างไร อย่างที่สองคือการคำนวณวนลูปสองรอบเท่านั้น แสดงว่าอัลกอริทึ่มอาจจะใช้อนุกรมเทเลอร์ลำดับที่ 2 ด้วย ซึ่งผมใช้ลำดับเดียวจึงต้องวนลูปมากกว่า

เป็นอย่างไรบ้างครับ เรื่องคำนวณ  least squares adjustment ตอนสมัยเรียนมหาวิทยาลัยถือว่าเป็นวิชาที่ยากสำหรับนักศีกษา แต่ถ้ามีโอกาสได้ลองคำนวณดูไปทีละขั้นตอน สำคัญคือต้องลงมือเองด้วย จึงจะเข้าใจ บางทีรายละเอียดเช่นอนุกรมเทเลอร์ การหาค่าอนุพันธ์ อาจจะยาก ผมไม่ได้จำหรอกครับ เพียงแต่ติดก็กลับมาเปิดตำรา หลงๆลืมๆไปบ้างตามวัยของผม แต่ปัจจุบันความได้เปรียบคือตำราหาอ่านได้ง่ายในอินเทอร์เน็ต โปรแกรมช่วยคำนวณแบบ  Microsurvey Starnet หรือโปรแกรมค่ายอื่นๆก็มีมากมาย ที่จะมาช่วยทำให้การคำนวณง่าย แต่ถ้ามีพื้นฐานบ้างก็จะได้เปรียบ  ติดตามกันต่อไปครับ

การเล็งสกัดย้อน (Resection) ด้วยการวัดมุมภายใน ระยะทางและและมุมแบริ่งด้วยวิธีการคำนวณแบบ Least Squares (ตอนที่ 1)

จากที่เขียนโปรแกรมสำหรับเครื่องคิดเลขคำนวณเล็งสกัดย้อนสำหรับเครื่องคิดเลข Casio fx-9860G II SD ทำให้นึกถึงวิธีการคำนวณแบบ least squares ที่เป็นพื้นฐานเคยร่ำเรียนมา โดยเฉพาะการรังวัดในปัจจุบันที่การรังวัดระยะทางด้วยกล้องประมวลผลรวมทำได้ง่าย เมื่อรวมกับการรังวัดมุม จะทำให้มีค่าเกินหรือ redundant มาคำนวณในวิธีแบบ least square ได้ การรังวัดแบบเล็งสกัดย้อนบางตำราเรียกว่า free station

การวัดเล็งสกัดย้อนในยุคแรกจะวัดมุมจากหมุดสถานีหลักฐานกันเป็นหลัก และหมุดสถานีหลักฐานต้องมีค่าพิกัดและมีจำนวนอย่างน้อยสามหมุด ดังนั้นการวัดมุมอย่างน้อยสองมุมจะเพียงพอต่อการมาคำนวณ ในบทความนี้ผมจะพาไปทัวร์การคำนวณวิธี least squares ด้วยการใช้การรังวัดผสมประกอบด้วยการวัดมุมภายใน วัดระยะทาง และการวัดมุมแบริ่งหรือการวัดภาคทิศ จากนั้นจะยกตัวอย่างพร้อมทั้งวิธีการคำนวณ ปิดท้ายทดสอบผลลัพธ์การคำนวณด้วยโปรแกรม Microsurvey StarNet

การวัดแบบ 2D

การวัดแบบนี้จะวัดมุมราบและระยะราบก็พอนำมาคำนวณหาค่าพิกัดของ free station ได้ ตัวอย่างที่ผมจะแสดงการคำนวณในลำดับต่อไปจะเป็นการวัดแบบ 2D เพื่อลดความซับซ้อน

การวัดแบบ 3D

การวัดระยะทางจะวัดแบบ Slope distance วัดมุมดิ่ง ถ้าทราบค่าระดับของหมุดสถานีหลักฐานและวัดความสูงของเป้าที่ตั้งบนสถานีหมุดหลักฐาน จากนั้นวัดความสูงกล้อง เมื่อนำมาคำนวณร่วมกับมุมราบแล้วจะได้ค่าพิกัดของ free station รวมทั้งค่าระดับด้วย

แนะนำตำรา

เมื่อผมกลับไปดูวิธีการคำนวณด้วย least square แต่กลับพบกับความนะจังงัง ว่าความรู้ที่รับการประสิทธิประสาทมาบัดนี้ได้คืนท่านอาจารย์ที่มหาวิทยาลัยไปจนหมดแล้วสิ้นเชิง นั่งงงกับการตั้งสมการ Observation Equation อยู่นานพอสมควร เมื่อไม่เป็นผลก็ต้องกลับไปหาตำราค่อยๆพลิกความทรงจำกลับมาใหม่

ตำราที่จะแนะนำให้อ่านเป็นของ Mr.Rod Deakin (Rodney Edwin Deakin) ถ้าดูตามโปรไฟล์ก่อนจะเกษียณเป็นอาจารย์ให้มหาวิทยาลัยสอนเรื่อง Engineering Survey มาก่อน ตำราหรือบทความที่แต่งนั้นมีความหลากหลายมากในเว็บไซต์ส่วนตัวนี้ อ่านง่าย เพลินจนลืมไปว่าเรื่องที่อ่านนั้นยาก

ตามไปดูหน้า least squares ลองเลื่อนไปด้านล่างดูเรื่อง “Notes on Least Squares” คือตำราที่จะมาแนะนำกันมีทั้งหมด 10 บท เนื่องจากผมพอมีพื้นฐานมาบ้างเล็กน้อย จึงไม่ได้อ่านเรียงหน้าตั้งแต่บทที่ 1 แต่อาศัยข้ามไปอ่านบทที่ 7 ก่อน พอเจอเมตริกผมงงก็ข้ามไปอ่าน “Appendix A” เฉพาะเรื่องเมตริก บวก ลบ คูณ อินเวอร์ส แล้วค่อยกลับมาอ่านบทอื่นๆอีกที ดังนั้นคนที่ห่างเรื่องนี้นานๆแนะนำให้ไปดูเรื่องเมตริกอันดับแรก

บทที่ 7 อนุกรมเทเลอร์

สำหรับการคำนวณเล็งสกัดย้อนด้วยวิธี least square ปฐมบทจะอยู่ที่บทที่ 7 เริ่มต้นจากอนุกรมเทเลอร์ เหตุที่เราต้องใช้เพราะว่าสมการที่จะนำมาคิด  resection นั้นไม่ใช่สมการแบบเชิงเส้นหรือ linear equation ดังนั้นจะต้องมีการถอดสมการเชิงเส้นออกมาและอยู่ในรูปอนุกรม เพื่อให้สามารถนำมาคำนวณได้ จะมีตัวอย่างสมการ Observation Equation 2 ตัวอย่างคือ

  • วัดมุม (Measure direction)
  • วัดระยะทาง (Measure distance)

บทที่ 9 คำนวณเล็งสกัดย้อน (Least Squares Resection)

บทนี้จะเริ่มตั้งแต่ตั้งสมการ  Observation Equation (ไม่เชิงเส้น) ของการวัดมุม จาก free station ไปยังหมุดสถานีหลักฐาน จากนั้นจะถอดสมการไม่เชิงเส้นด้วยอนุกรมเทเลอร์ แล้วก็มีตัวอย่างแสดงวิธีการคำนวณ

บทที่ 10 คำนวณเล็งสกัด (Least Squares Bearing Intersection)

ผู้อ่านอาจจะสังเกตสองคำคือเล็งสกัดกับเล็งสกัดย้อน

  • เล็งสกัดย้อน (Resection) คือไปตั้งกล้องที่  free station แล้ววัดมุมภายในไปหาสถานีหมุดหลักฐาน

  • เล็งสกัด (Bearing Intersection) จะเป็นการวัดมุมแบริ่ง ตัวอย่างได้แก่การวัดดาวเหนือในสมัยก่อน คือเราจะมีหมุดคู่เป็น base line ต้องการทราบมุมแบริ่งของ base line นี้ก็ตั้งกล้องที่หมุดตัวแรกแล้วอาศัยวัดดาวเหนือกับหมุดอีกตัวบน base line ดังนั้นถ้าวัดแบริ่งสัก 2 base line ไปตัดกันก็จะได้ค่าพิกัด

การถอดสมการเล็งสกัดย้อนด้วยอนุกรมเทเลอร์

ต่อไปมาลองดูสมการที่เราใช้คำนวณหามุมและระยะทาง โดยที่ทราบค่าพิกัด ซึ่งเป็นสมการพื้นฐานของงานสำรวจ ในที่นี้เป็นสมการไม่เชิงเส้น เราจะมาถอดสมการออกมาเป็นเชิงเส้นด้วยอนุกรมเทเลอร์ แผนผังด้านล่างเป็นงานเล็งสกัดย้อน ตั้งกล้องที่จุด Pi วัดมุมไปหาสถานีหลักฐานที่ทราบค่าพิกัดคือจุด  P1, P2, P3, … Pk