{"id":873,"date":"2025-11-03T10:38:48","date_gmt":"2025-11-03T01:38:48","guid":{"rendered":"http:\/\/practical.kr\/?p=873"},"modified":"2025-11-03T10:40:07","modified_gmt":"2025-11-03T01:40:07","slug":"%ea%b5%ac%ec%a1%b0%eb%ac%bc-%eb%aa%a8%eb%8b%88%ed%84%b0%eb%a7%81%ec%9d%84-%ec%9c%84%ed%95%9c-rtk-gps%ec%9d%98-%ec%95%84%ec%9b%83%eb%9d%bc%ec%9d%b4%ec%96%b4-%ea%b2%80%ec%b6%9c%eb%b0%a9%eb%b2%95","status":"publish","type":"post","link":"http:\/\/practical.kr\/?p=873","title":{"rendered":"\uad6c\uc870\ubb3c \ubaa8\ub2c8\ud130\ub9c1\uc744 \uc704\ud55c RTK GPS\uc758 \uc544\uc6c3\ub77c\uc774\uc5b4 \uac80\ucd9c\ubc29\ubc95"},"content":{"rendered":"\n<p>RTK GPS\ub294 mm \ub2e8\uc704\uc758 \uc815\ubc00\ub3c4\ub85c \uc704\uce58\ub97c \uce21\uc815\ud560 \uc218 \uc788\uc5b4 \uad6c\uc870\ubb3c \ubaa8\ub2c8\ud130\ub9c1, \uc9c0\ubc18 \uce68\ud558 \uce21\uc815, \ub310 \uc548\uc804 \uad00\ub9ac \ub4f1\uc5d0 \ub110\ub9ac \ud65c\uc6a9\ub429\ub2c8\ub2e4. \ud558\uc9c0\ub9cc \uc2e4\uc81c \ud604\uc7a5\uc5d0\uc11c \uc218\uc9d1\ub41c \ub370\uc774\ud130\uc5d0\ub294 \ub2e4\uc591\ud55c \uc6d0\uc778\uc73c\ub85c \uc778\ud55c \uc544\uc6c3\ub77c\uc774\uc5b4(\uc774\uc0c1\uce58)\uac00 \ud3ec\ud568\ub418\uc5b4 \uc788\uc5b4, \uc815\ud655\ud55c \ubcc0\uc704 \ubd84\uc11d\uc744 \uc704\ud574\uc11c\ub294 \uccb4\uacc4\uc801\uc778 \ub370\uc774\ud130 \uc815\uc81c\uac00 \ud544\uc218\uc801\uc785\ub2c8\ub2e4.<\/p>\n\n\n\n<p>\uc774 \uae00\uc5d0\uc11c\ub294 \uace0\uc815\ub41c \ub85c\ubc84\ub97c \uc774\uc6a9\ud55c \uad6c\uc870\ubb3c \ubaa8\ub2c8\ud130\ub9c1\uc5d0 \ud2b9\ud654\ub41c \uc544\uc6c3\ub77c\uc774\uc5b4 \uac80\ucd9c \ubc29\ubc95\uc744 \uc18c\uac1c\ud569\ub2c8\ub2e4.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">RTK GPS \ub370\uc774\ud130\uc758 \ud2b9\uc131\uacfc \uc544\uc6c3\ub77c\uc774\uc5b4 \ubc1c\uc0dd \uc6d0\uc778<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">\uce21\uc815 \ub370\uc774\ud130 \uad6c\uc131<\/h3>\n\n\n\n<p>RTK GPS \ub85c\ubc84\uc5d0\uc11c \uc218\uc9d1\ub418\ub294 \uc8fc\uc694 \ub370\uc774\ud130\ub294 \ub2e4\uc74c\uacfc \uac19\uc2b5\ub2c8\ub2e4:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>\uc704\uce58 \uc815\ubcf4<\/strong>: \uc704\ub3c4(Latitude), \uacbd\ub3c4(Longitude), \uace0\ub3c4(Altitude)<\/li>\n\n\n\n<li><strong>\uc2dc\uac04 \uc815\ubcf4<\/strong>: \ud0c0\uc784\uc2a4\ud0ec\ud504(Timestamp)<\/li>\n\n\n\n<li><strong>\ud488\uc9c8 \uc9c0\ud45c<\/strong>:<\/li>\n\n\n\n<li>Fix \uc0c1\ud0dc (Fixed RTK, Float RTK, Single \ub4f1)<\/li>\n\n\n\n<li>\uc704\uc131 \uac1c\uc218 (Number of Satellites)<\/li>\n\n\n\n<li>HDOP\/PDOP (\uc815\ubc00\ub3c4 \uc800\ud558\uc728)<\/li>\n\n\n\n<li>\uc815\ud655\ub3c4(Accuracy)<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">\uc544\uc6c3\ub77c\uc774\uc5b4 \ubc1c\uc0dd \uc6d0\uc778<\/h3>\n\n\n\n<p>\uad6c\uc870\ubb3c \ubaa8\ub2c8\ud130\ub9c1\uc5d0\uc11c \uc544\uc6c3\ub77c\uc774\uc5b4\uac00 \ubc1c\uc0dd\ud558\ub294 \uc8fc\uc694 \uc6d0\uc778\uc740 \ub2e4\uc74c\uacfc \uac19\uc2b5\ub2c8\ub2e4:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\uc704\uc131 \uc2e0\ud638 \ucc28\ub2e8<\/strong>: \uc8fc\ubcc0 \uac74\ubb3c, \ub098\ubb34, \uc9c0\ud615\uc5d0 \uc758\ud55c \uc77c\uc2dc\uc801 \uc2e0\ud638 \uc190\uc2e4<\/li>\n\n\n\n<li><strong>\ub2e4\uc911\uacbd\ub85c \uc624\ucc28(Multipath)<\/strong>: \uac74\ubb3c\uc774\ub098 \uad6c\uc870\ubb3c \ud45c\uba74\uc5d0\uc11c \ubc18\uc0ac\ub41c \uc2e0\ud638 \uc218\uc2e0<\/li>\n\n\n\n<li><strong>Fix \uc0c1\ud0dc \ubcc0\ud654<\/strong>: Fixed RTK\uc5d0\uc11c Float \ub610\ub294 Single\ub85c \uc800\ud558<\/li>\n\n\n\n<li><strong>\ub300\uae30 \uc870\uac74<\/strong>: \uc804\ub9ac\uce35, \ub300\ub958\uad8c \uc9c0\uc5f0<\/li>\n\n\n\n<li><strong>\uc7a5\ube44 \ubb38\uc81c<\/strong>: \uc218\uc2e0\uae30 \uc624\uc791\ub3d9, \uc548\ud14c\ub098 \uc704\uce58 \ubcc0\ud654<\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">\uace0\uc815 \ub85c\ubc84\uc758 \ud2b9\uc218\uc131<\/h2>\n\n\n\n<p>\uad6c\uc870\ubb3c \ubaa8\ub2c8\ud130\ub9c1\uc6a9 \uace0\uc815 \ub85c\ubc84\ub294 \uc77c\ubc18\uc801\uc778 \uc774\ub3d9 \uce21\ub7c9\uacfc\ub294 \ub2e4\ub978 \ud2b9\uc131\uc744 \uac00\uc9d1\ub2c8\ub2e4:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>\uc774\ub860\uc801 \uc815\uc9c0 \uc0c1\ud0dc<\/strong>: \ub85c\ubc84\uac00 \ubb3c\ub9ac\uc801\uc73c\ub85c \uace0\uc815\ub418\uc5b4 \uc788\uc5b4 \uc704\uce58 \ubcc0\ud654\uac00 \uc5c6\uac70\ub098 \ub9e4\uc6b0 \uc791\uc74c<\/li>\n\n\n\n<li><strong>\ubbf8\uc138 \ubcc0\uc704 \uac10\uc9c0<\/strong>: mm~cm \ub2e8\uc704\uc758 \uc791\uc740 \ubcc0\uc704\ub97c \uac10\uc9c0\ud574\uc57c \ud568<\/li>\n\n\n\n<li><strong>\uc810\uc9c4\uc801 \ubcc0\ud654<\/strong>: \uc2e4\uc81c \uad6c\uc870\ubb3c \ubcc0\uc704\ub294 \uae09\uaca9\ud558\uc9c0 \uc54a\uace0 \uc11c\uc11c\ud788 \ubc1c\uc0dd<\/li>\n\n\n\n<li><strong>\ub178\uc774\uc988 vs \ubcc0\uc704<\/strong>: \uce21\uc815\uac12\uc758 \ub300\ubd80\ubd84\uc740 \ub178\uc774\uc988\uc774\uba70, \uc9c4\uc9dc \ubcc0\uc704\uc640 \uad6c\ubd84\uc774 \uc911\uc694<\/li>\n<\/ul>\n\n\n\n<p>\ub530\ub77c\uc11c <strong>\uae09\uaca9\ud55c \uc810\ud504\ub294 \ub300\ubd80\ubd84 \uc544\uc6c3\ub77c\uc774\uc5b4<\/strong>\ub85c \uac04\uc8fc\ud560 \uc218 \uc788\uc73c\uba70, \uc774\ub97c \uc81c\uac70\ud558\uba74\uc11c\ub3c4 \uc2e4\uc81c \uad6c\uc870\ubb3c\uc758 \uc810\uc9c4\uc801 \ubcc0\ud654\ub294 \ubcf4\uc874\ud574\uc57c \ud569\ub2c8\ub2e4.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\ub2e8\uacc4\ubcc4 \uc544\uc6c3\ub77c\uc774\uc5b4 \uac80\ucd9c \ubc29\ubc95<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">1\ub2e8\uacc4: \ud488\uc9c8 \uae30\ubc18 1\ucc28 \ud544\ud130\ub9c1<\/h3>\n\n\n\n<p>\uac00\uc7a5 \uba3c\uc800 RTK GPS \uc790\uccb4\uc758 \ud488\uc9c8 \uc9c0\ud45c\ub97c \ud65c\uc6a9\ud558\uc5ec \uba85\ubc31\ud788 \ub0ae\uc740 \ud488\uc9c8\uc758 \ub370\uc774\ud130\ub97c \uc81c\uac70\ud569\ub2c8\ub2e4.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Fix \uc0c1\ud0dc \ud544\ud130\ub9c1<\/h4>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">import pandas as pd\nimport numpy as np\n\ndef filter_by_fix_quality(df):\n    \"\"\"\n    RTK Fix \uc0c1\ud0dc\ub85c \ud544\ud130\ub9c1\n    Fix Type: 4(Fixed RTK) \ub610\ub294 5(Float RTK)\ub9cc \uc720\uc9c0\n    \"\"\"\n    # Fixed RTK\ub9cc \uc0ac\uc6a9 (\uac00\uc7a5 \uc5c4\uaca9)\n    df_filtered = df[df['fix_type'] == 4].copy()\n\n    # \ub610\ub294 Float RTK\uae4c\uc9c0 \ud3ec\ud568 (\uc870\uae08 \ub354 \uad00\ub300)\n    # df_filtered = df[df['fix_type'].isin([4, 5])].copy()\n\n    return df_filtered<\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">\uc704\uc131 \ud488\uc9c8 \ud544\ud130\ub9c1<\/h4>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">def filter_by_satellite_quality(df, min_satellites=12, max_hdop=1.5):\n    \"\"\"\n    \uc704\uc131 \uac1c\uc218\uc640 HDOP\ub85c \ud544\ud130\ub9c1\n    \uad6c\uc870\ubb3c \ubaa8\ub2c8\ud130\ub9c1\uc740 \ub192\uc740 \ud488\uc9c8 \uae30\uc900 \uc801\uc6a9\n    \"\"\"\n    df_filtered = df[\n        (df['num_satellites'] >= min_satellites) &amp; \n        (df['hdop'] &lt;= max_hdop)\n    ].copy()\n\n    return df_filtered<\/pre>\n\n\n\n<p><strong>\uad8c\uc7a5 \uae30\uc900\uac12 (\uad6c\uc870\ubb3c \ubaa8\ub2c8\ud130\ub9c1)<\/strong>:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Fix Type: 4 (Fixed RTK)<\/li>\n\n\n\n<li>\uc704\uc131 \uac1c\uc218: 12\uac1c \uc774\uc0c1<\/li>\n\n\n\n<li>HDOP: 1.5 \uc774\ud558<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">2\ub2e8\uacc4: \uae30\uc900 \uc704\uce58 \uc124\uc815 \ubc0f \ubcc0\uc704 \uacc4\uc0b0<\/h3>\n\n\n\n<p>\uace0\uc815 \ub85c\ubc84\uc758 \uacbd\uc6b0, \uc808\ub300 \uc88c\ud45c\ubcf4\ub2e4\ub294 \uae30\uc900\uc810 \ub300\ube44 \uc0c1\ub300 \ubcc0\uc704\ub97c \ubd84\uc11d\ud558\ub294 \uac83\uc774 \ud6a8\uacfc\uc801\uc785\ub2c8\ub2e4.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">def calculate_baseline_position(df):\n    \"\"\"\n    \uae30\uc900 \uc704\uce58 \uc124\uc815\n    \uc911\uc559\uac12\uc744 \uc0ac\uc6a9\ud558\uc5ec \uc544\uc6c3\ub77c\uc774\uc5b4\uc758 \uc601\ud5a5 \ucd5c\uc18c\ud654\n    \"\"\"\n    baseline = {\n        'latitude': df['latitude'].median(),\n        'longitude': df['longitude'].median(),\n        'altitude': df['altitude'].median()\n    }\n\n    return baseline\n\ndef calculate_displacement(df, baseline):\n    \"\"\"\n    \uae30\uc900\uc810 \ub300\ube44 \ubcc0\uc704 \uacc4\uc0b0 (\ubbf8\ud130 \ub2e8\uc704)\n    \"\"\"\n    from geopy.distance import geodesic\n\n    df = df.copy()\n\n    # \uc218\ud3c9 \ubcc0\uc704 \uacc4\uc0b0\n    displacements = []\n    for idx, row in df.iterrows():\n        point = (row['latitude'], row['longitude'])\n        base_point = (baseline['latitude'], baseline['longitude'])\n        horiz_disp = geodesic(base_point, point).meters\n        displacements.append(horiz_disp)\n\n    df['horizontal_displacement'] = displacements\n\n    # \uc218\uc9c1 \ubcc0\uc704\n    df['vertical_displacement'] = df['altitude'] - baseline['altitude']\n\n    # \ub3d9-\uc11c, \ub0a8-\ubd81 \uc131\ubd84 \ubd84\ub9ac\n    earth_radius = 6371000  # \ubbf8\ud130\n    df['east_displacement'] = (df['longitude'] - baseline['longitude']) * \\\n                              np.cos(np.radians(baseline['latitude'])) * \\\n                              np.pi * earth_radius \/ 180\n    df['north_displacement'] = (df['latitude'] - baseline['latitude']) * \\\n                               np.pi * earth_radius \/ 180\n\n    return df<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">3\ub2e8\uacc4: \uae09\uaca9\ud55c \uc810\ud504 \uc81c\uac70<\/h3>\n\n\n\n<p>\uad6c\uc870\ubb3c\uc740 \uae09\uaca9\ud788 \ubcc0\ud558\uc9c0 \uc54a\uc73c\ubbc0\ub85c, \uc5f0\uc18d\ub41c \uce21\uc815\uac12 \uc0ac\uc774\uc758 \ud070 \ucc28\uc774\ub294 \uc544\uc6c3\ub77c\uc774\uc5b4\ub85c \ud310\ub2e8\ud569\ub2c8\ub2e4.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">def remove_sudden_jumps(df, jump_threshold=0.03):\n    \"\"\"\n    \uc5f0\uc18d\ub41c \uc810 \uc0ac\uc774\uc758 \uae09\uaca9\ud55c \ubcc0\ud654 \uc81c\uac70\n    \uad6c\uc870\ubb3c \ubaa8\ub2c8\ud130\ub9c1: 3cm \uc784\uacc4\uac12 \uad8c\uc7a5\n    \"\"\"\n    df = df.sort_values('timestamp').reset_index(drop=True)\n    df_clean = df.copy()\n\n    for col in ['horizontal_displacement', 'vertical_displacement']:\n        if col in df.columns:\n            # \uc5f0\uc18d\ub41c \uac12\uc758 \ucc28\uc774\n            diff = df[col].diff().abs()\n\n            # \uae09\uaca9\ud55c \uc810\ud504 \ub9c8\uc2a4\ud0b9\n            jump_mask = diff > jump_threshold\n            jump_mask.iloc[0] = False  # \uccab \ud589 \uc81c\uc678\n\n            df_clean = df_clean[~jump_mask]\n\n    df_clean = df_clean.reset_index(drop=True)\n    return df_clean<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">4\ub2e8\uacc4: MAD \uae30\ubc18 \uc544\uc6c3\ub77c\uc774\uc5b4 \uc81c\uac70<\/h3>\n\n\n\n<p>MAD(Median Absolute Deviation)\ub294 \uc911\uc559\uac12 \uae30\ubc18 \ubc29\ubc95\uc73c\ub85c, \uadf9\ub2e8\uac12\uc5d0 \ub9e4\uc6b0 \uac15\uac74\ud558\uc5ec \uace0\uc815 \ub85c\ubc84\uc5d0 \uc774\uc0c1\uc801\uc785\ub2c8\ub2e4.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">def remove_outliers_mad(df, mad_threshold=3.5):\n    \"\"\"\n    MAD \uae30\ubc18 \uc544\uc6c3\ub77c\uc774\uc5b4 \uc81c\uac70\n    \uc911\uc559\uac12 \uae30\ubc18\uc774\ubbc0\ub85c \uadf9\ub2e8\uac12\uc5d0 \uac15\uac74\n    \"\"\"\n    df_clean = df.copy()\n\n    outlier_columns = [\n        'horizontal_displacement',\n        'vertical_displacement'\n    ]\n\n    for col in outlier_columns:\n        if col in df.columns:\n            median = df[col].median()\n            mad = np.median(np.abs(df[col] - median))\n\n            # Modified Z-score \uacc4\uc0b0\n            modified_z_scores = 0.6745 * (df_clean[col] - median) \/ mad\n\n            # \uc784\uacc4\uac12 \uc774\ub0b4\uc758 \ub370\uc774\ud130\ub9cc \uc720\uc9c0\n            mask = np.abs(modified_z_scores) &lt;= mad_threshold\n            df_clean = df_clean[mask]\n\n    return df_clean<\/pre>\n\n\n\n<p><strong>MAD vs 3-Sigma \ube44\uad50<\/strong>:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>\ubc29\ubc95<\/th><th>\uae30\uc900<\/th><th>\uc7a5\uc810<\/th><th>\ub2e8\uc810<\/th><\/tr><\/thead><tbody><tr><td>3-Sigma<\/td><td>\ud3c9\uade0, \ud45c\uc900\ud3b8\ucc28<\/td><td>\uc815\uaddc\ubd84\ud3ec\uc5d0\uc11c \ud6a8\uacfc\uc801<\/td><td>\uc544\uc6c3\ub77c\uc774\uc5b4\uc758 \uc601\ud5a5 \ubc1b\uc74c<\/td><\/tr><tr><td>MAD<\/td><td>\uc911\uc559\uac12<\/td><td>\uc544\uc6c3\ub77c\uc774\uc5b4\uc5d0 \uac15\uac74<\/td><td>\uc815\uaddc\ubd84\ud3ec \uc544\ub2d0 \ub54c \ubcf4\uc218\uc801<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>\uace0\uc815 \ub85c\ubc84\ucc98\ub7fc \uc544\uc6c3\ub77c\uc774\uc5b4\uac00 \ub9ce\uc744 \uc218 \uc788\ub294 \uacbd\uc6b0 <strong>MAD \ubc29\ubc95\uc744 \uad8c\uc7a5<\/strong>\ud569\ub2c8\ub2e4.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">5\ub2e8\uacc4: \uc2dc\uacc4\uc5f4 \uc774\ub3d9 \uc911\uc559\uac12 \ud544\ud130<\/h3>\n\n\n\n<p>\uc810\uc9c4\uc801\uc778 \ubcc0\ud654\ub294 \uc720\uc9c0\ud558\uba74\uc11c \uae09\uaca9\ud55c \ub178\uc774\uc988\ub9cc \uc81c\uac70\ud569\ub2c8\ub2e4.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">def remove_outliers_rolling_median(df, window=20, threshold=3):\n    \"\"\"\n    \uc774\ub3d9 \uc911\uc559\uac12 \uae30\ubc18 \uc544\uc6c3\ub77c\uc774\uc5b4 \uc81c\uac70\n    \uad6c\uc870\ubb3c\uc758 \uc810\uc9c4\uc801 \ubcc0\ud654\ub294 \ubcf4\uc874\n    \"\"\"\n    df = df.sort_values('timestamp').reset_index(drop=True)\n    df_clean = df.copy()\n\n    outlier_columns = [\n        'horizontal_displacement',\n        'vertical_displacement'\n    ]\n\n    for col in outlier_columns:\n        if col in df.columns:\n            # \uc774\ub3d9 \uc911\uc559\uac12 \uacc4\uc0b0\n            rolling_median = df[col].rolling(window=window, center=True).median()\n\n            # \uc911\uc559\uac12\uc73c\ub85c\ubd80\ud130\uc758 \ud3b8\ucc28\n            deviation = np.abs(df[col] - rolling_median)\n            rolling_mad = deviation.rolling(window=window, center=True).median()\n\n            # Modified Z-score\n            modified_z = 0.6745 * deviation \/ rolling_mad\n\n            # \uc784\uacc4\uac12 \uc774\ub0b4\ub9cc \uc720\uc9c0\n            mask = modified_z &lt;= threshold\n            mask = mask.fillna(True)  # NaN\uc740 \uc720\uc9c0\n\n            df_clean = df_clean[mask]\n\n    return df_clean<\/pre>\n\n\n\n<p><strong>\uc708\ub3c4\uc6b0 \ud06c\uae30 \uc120\ud0dd<\/strong>:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\uc791\uc740 \uc708\ub3c4\uc6b0(5-10): \ube60\ub978 \ubcc0\ud654 \uac10\uc9c0, \ub178\uc774\uc988\uc5d0 \ubbfc\uac10<\/li>\n\n\n\n<li>\ud070 \uc708\ub3c4\uc6b0(20-50): \uc548\uc815\uc801, \ub290\ub9b0 \ubcc0\ud654\ub9cc \uac10\uc9c0<\/li>\n<\/ul>\n\n\n\n<p>\uad6c\uc870\ubb3c \ubaa8\ub2c8\ud130\ub9c1\uc5d0\uc11c\ub294 <strong>20-30 \uc815\ub3c4\uc758 \ud070 \uc708\ub3c4\uc6b0<\/strong> \uad8c\uc7a5<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\uc885\ud569 \ud30c\uc774\ud504\ub77c\uc778<\/h2>\n\n\n\n<p>\uc704\uc758 \ubaa8\ub4e0 \ub2e8\uacc4\ub97c \ud1b5\ud569\ud55c \uc644\uc804\ud55c \ud30c\uc774\ud504\ub77c\uc778\uc785\ub2c8\ub2e4.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">def clean_fixed_rover_data(df, params=None):\n    \"\"\"\n    \uace0\uc815 \ub85c\ubc84 RTK GPS \ub370\uc774\ud130 \uc815\uc81c \uc885\ud569 \ud30c\uc774\ud504\ub77c\uc778\n    \"\"\"\n    if params is None:\n        # \uad6c\uc870\ubb3c \ubaa8\ub2c8\ud130\ub9c1 \uad8c\uc7a5 \ud30c\ub77c\ubbf8\ud130\n        params = {\n            'min_satellites': 12,\n            'max_hdop': 1.5,\n            'jump_threshold': 0.03,      # 3cm\n            'mad_threshold': 3.5,\n            'rolling_window': 20\n        }\n\n    print(f\"\uc6d0\ubcf8 \ub370\uc774\ud130: {len(df)}\uac1c \uc810\\n\")\n\n    # 1\ub2e8\uacc4: Fix \ud488\uc9c8 \ud544\ud130\ub9c1\n    df = filter_by_fix_quality(df)\n    print(f\"1. Fix \ud488\uc9c8 \ud544\ud130\ub9c1: {len(df)}\uac1c \uc810\")\n\n    # 2\ub2e8\uacc4: \uc704\uc131 \ud488\uc9c8 \ud544\ud130\ub9c1\n    df = filter_by_satellite_quality(\n        df,\n        min_satellites=params['min_satellites'],\n        max_hdop=params['max_hdop']\n    )\n    print(f\"2. \uc704\uc131 \ud488\uc9c8 \ud544\ud130\ub9c1: {len(df)}\uac1c \uc810\")\n\n    # 3\ub2e8\uacc4: \uae30\uc900 \uc704\uce58 \uc124\uc815 \ubc0f \ubcc0\uc704 \uacc4\uc0b0\n    baseline = calculate_baseline_position(df)\n    df = calculate_displacement(df, baseline)\n    print(f\"3. \uae30\uc900 \uc704\uce58 \uc124\uc815 \uc644\ub8cc\")\n    print(f\"   Lat: {baseline['latitude']:.8f}\")\n    print(f\"   Lon: {baseline['longitude']:.8f}\")\n    print(f\"   Alt: {baseline['altitude']:.3f}m\")\n\n    # 4\ub2e8\uacc4: \uae09\uaca9\ud55c \uc810\ud504 \uc81c\uac70\n    df = remove_sudden_jumps(df, jump_threshold=params['jump_threshold'])\n    print(f\"4. \uae09\uaca9\ud55c \uc810\ud504 \uc81c\uac70: {len(df)}\uac1c \uc810\")\n\n    # 5\ub2e8\uacc4: MAD \uae30\ubc18 \uc544\uc6c3\ub77c\uc774\uc5b4 \uc81c\uac70\n    df = remove_outliers_mad(df, mad_threshold=params['mad_threshold'])\n    print(f\"5. MAD \ud544\ud130\ub9c1: {len(df)}\uac1c \uc810\")\n\n    # 6\ub2e8\uacc4: \uc2dc\uacc4\uc5f4 \uc774\ub3d9 \uc911\uc559\uac12 \ud544\ud130\n    df = remove_outliers_rolling_median(\n        df,\n        window=params['rolling_window'],\n        threshold=3\n    )\n    print(f\"6. \uc774\ub3d9 \uc911\uc559\uac12 \ud544\ud130\ub9c1: {len(df)}\uac1c \uc810\")\n\n    print(f\"\\n\ucd5c\uc885 \uc815\uc81c \ub370\uc774\ud130: {len(df)}\uac1c \uc810\")\n\n    return df, baseline\n\n# \uc0ac\uc6a9 \uc608\uc2dc\ndf_clean, baseline = clean_fixed_rover_data(df_raw)<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">\uacb0\uacfc \ubd84\uc11d \ubc0f \uc2dc\uac01\ud654<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">\ubcc0\uc704 \ud1b5\uacc4 \ubd84\uc11d<\/h3>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">def analyze_displacement_statistics(df):\n    \"\"\"\n    \ubcc0\uc704 \ud1b5\uacc4 \ubd84\uc11d \ubc0f \ub9ac\ud3ec\ud2b8\n    \"\"\"\n    print(\"\\n=== \ubcc0\uc704 \ud1b5\uacc4 \ubd84\uc11d ===\\n\")\n\n    # \uc218\ud3c9 \ubcc0\uc704 \ud1b5\uacc4\n    print(\"\uc218\ud3c9 \ubcc0\uc704:\")\n    print(f\"  \ud3c9\uade0: {df['horizontal_displacement'].mean()*1000:.2f} mm\")\n    print(f\"  \ud45c\uc900\ud3b8\ucc28: {df['horizontal_displacement'].std()*1000:.2f} mm\")\n    print(f\"  \ucd5c\ub300: {df['horizontal_displacement'].max()*1000:.2f} mm\")\n    print(f\"  95% \uc2e0\ub8b0\uad6c\uac04: {df['horizontal_displacement'].quantile(0.95)*1000:.2f} mm\")\n\n    # \uc218\uc9c1 \ubcc0\uc704 \ud1b5\uacc4\n    print(f\"\\n\uc218\uc9c1 \ubcc0\uc704:\")\n    print(f\"  \ud3c9\uade0: {df['vertical_displacement'].mean()*1000:.2f} mm\")\n    print(f\"  \ud45c\uc900\ud3b8\ucc28: {df['vertical_displacement'].std()*1000:.2f} mm\")\n    print(f\"  \ucd5c\ub300: {df['vertical_displacement'].max()*1000:.2f} mm\")\n    print(f\"  \ucd5c\uc18c: {df['vertical_displacement'].min()*1000:.2f} mm\")\n\n    # \ucd1d \ubcc0\uc704\ub7c9\n    total_displacement = df['vertical_displacement'].iloc[-1] - df['vertical_displacement'].iloc[0]\n    print(f\"  \ucd1d \uce68\ud558\/\uc735\uae30: {total_displacement*1000:.2f} mm\")\n\n    # \uc815\ud655\ub3c4 \ud3c9\uac00 (2\u03c3)\n    print(f\"\\n\uce21\uc815 \uc815\ubc00\ub3c4 (2\u03c3):\")\n    print(f\"  \uc218\ud3c9: {df['horizontal_displacement'].std()*2*1000:.2f} mm\")\n    print(f\"  \uc218\uc9c1: {df['vertical_displacement'].std()*2*1000:.2f} mm\")\n\nanalyze_displacement_statistics(df_clean)<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">\uc2dc\uac01\ud654<\/h3>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">import matplotlib.pyplot as plt\nfrom matplotlib.dates import DateFormatter\n\ndef visualize_fixed_rover(df, baseline):\n    \"\"\"\n    \uace0\uc815 \ub85c\ubc84 \ub370\uc774\ud130 \uc885\ud569 \uc2dc\uac01\ud654\n    \"\"\"\n    fig = plt.figure(figsize=(16, 10))\n\n    # 1. \uc218\ud3c9 \ubcc0\uc704 \uc2dc\uacc4\uc5f4\n    ax1 = plt.subplot(2, 3, 1)\n    ax1.plot(df['timestamp'], df['horizontal_displacement']*1000, \n             'b-', linewidth=0.5)\n    ax1.set_ylabel('\uc218\ud3c9 \ubcc0\uc704 (mm)')\n    ax1.set_title('\uc218\ud3c9 \ubcc0\uc704 \uc2dc\uacc4\uc5f4')\n    ax1.grid(True, alpha=0.3)\n    ax1.xaxis.set_major_formatter(DateFormatter('%H:%M'))\n\n    # 2. \uc218\uc9c1 \ubcc0\uc704 \uc2dc\uacc4\uc5f4\n    ax2 = plt.subplot(2, 3, 2)\n    ax2.plot(df['timestamp'], df['vertical_displacement']*1000, \n             'r-', linewidth=0.5)\n    ax2.set_ylabel('\uc218\uc9c1 \ubcc0\uc704 (mm)')\n    ax2.set_title('\uc218\uc9c1 \ubcc0\uc704 \uc2dc\uacc4\uc5f4')\n    ax2.grid(True, alpha=0.3)\n    ax2.xaxis.set_major_formatter(DateFormatter('%H:%M'))\n\n    # 3. \uc218\ud3c9\uba74 \uada4\uc801\n    ax3 = plt.subplot(2, 3, 3)\n    scatter = ax3.scatter(df['east_displacement']*1000, \n                         df['north_displacement']*1000,\n                         c=range(len(df)), cmap='viridis', s=1)\n    ax3.plot(0, 0, 'r*', markersize=15, label='\uae30\uc900\uc810')\n    ax3.set_xlabel('\ub3d9-\uc11c \ubcc0\uc704 (mm)')\n    ax3.set_ylabel('\ub0a8-\ubd81 \ubcc0\uc704 (mm)')\n    ax3.set_title('\uc218\ud3c9\uba74 \uada4\uc801')\n    ax3.axis('equal')\n    ax3.grid(True, alpha=0.3)\n    ax3.legend()\n\n    # 4. \ubcc0\uc704 \ubd84\ud3ec\n    ax4 = plt.subplot(2, 3, 4)\n    ax4.hist(df['horizontal_displacement']*1000, bins=50, \n            alpha=0.7, label='\uc218\ud3c9', edgecolor='black')\n    ax4.hist(df['vertical_displacement']*1000, bins=50, \n            alpha=0.7, label='\uc218\uc9c1', edgecolor='black')\n    ax4.set_xlabel('\ubcc0\uc704 (mm)')\n    ax4.set_ylabel('\ube48\ub3c4')\n    ax4.set_title('\ubcc0\uc704 \ubd84\ud3ec')\n    ax4.legend()\n\n    # 5. \uc704\uc131 \uac1c\uc218\n    ax5 = plt.subplot(2, 3, 5)\n    ax5.plot(df['timestamp'], df['num_satellites'], 'g-', linewidth=0.5)\n    ax5.set_ylabel('\uc704\uc131 \uac1c\uc218')\n    ax5.set_title('\uc704\uc131 \uac1c\uc218 \ubcc0\ud654')\n    ax5.grid(True, alpha=0.3)\n    ax5.xaxis.set_major_formatter(DateFormatter('%H:%M'))\n\n    # 6. HDOP\n    ax6 = plt.subplot(2, 3, 6)\n    ax6.plot(df['timestamp'], df['hdop'], 'orange', linewidth=0.5)\n    ax6.set_ylabel('HDOP')\n    ax6.set_title('HDOP \ubcc0\ud654')\n    ax6.grid(True, alpha=0.3)\n    ax6.xaxis.set_major_formatter(DateFormatter('%H:%M'))\n\n    plt.tight_layout()\n    plt.show()\n\nvisualize_fixed_rover(df_clean, baseline)<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">\uc2e4\uc804 \uc801\uc6a9 \uac00\uc774\ub4dc<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">\ud30c\ub77c\ubbf8\ud130 \uc870\uc815 \uac00\uc774\ub4dc<\/h3>\n\n\n\n<p>\uc6a9\ub3c4\uc5d0 \ub530\ub77c \ud30c\ub77c\ubbf8\ud130\ub97c \uc870\uc815\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"># \ucd08\uc815\ubc00 \uad6c\uc870\ubb3c \ubaa8\ub2c8\ud130\ub9c1 (\ub310, \uad50\ub7c9 \ub4f1)\nparams_precision = {\n    'min_satellites': 14,\n    'max_hdop': 1.2,\n    'jump_threshold': 0.02,    # 2cm\n    'mad_threshold': 3.0,      # \ub354 \uc5c4\uaca9\n    'rolling_window': 30\n}\n\n# \uc77c\ubc18 \uad6c\uc870\ubb3c \ubaa8\ub2c8\ud130\ub9c1\nparams_standard = {\n    'min_satellites': 12,\n    'max_hdop': 1.5,\n    'jump_threshold': 0.03,    # 3cm\n    'mad_threshold': 3.5,\n    'rolling_window': 20\n}\n\n# \uae34\uae09 \uc0c1\ud669 (\ub370\uc774\ud130 \ubd80\uc871 \uc2dc)\nparams_relaxed = {\n    'min_satellites': 10,\n    'max_hdop': 2.0,\n    'jump_threshold': 0.05,    # 5cm\n    'mad_threshold': 4.0,      # \ub354 \uad00\ub300\n    'rolling_window': 15\n}<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">\ub370\uc774\ud130 \uc218\uc9d1 \uad8c\uc7a5\uc0ac\ud56d<\/h3>\n\n\n\n<p><strong>1. \uc0d8\ud50c\ub9c1 \uc8fc\ud30c\uc218<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>1Hz (1\ucd08\ub9c8\ub2e4): \ud45c\uc900, \ub300\ubd80\ubd84\uc758 \uacbd\uc6b0 \ucda9\ubd84<\/li>\n\n\n\n<li>5Hz \uc774\uc0c1: \ub3d9\uc801 \uad6c\uc870\ubb3c, \ub354 \uc815\ubc00\ud55c \ubd84\uc11d \ud544\uc694 \uc2dc<\/li>\n<\/ul>\n\n\n\n<p><strong>2. \uad00\uce21 \uae30\uac04<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\ucd5c\uc18c 24\uc2dc\uac04: \uc77c\uc77c \ubcc0\ud654 \ud328\ud134 \ud30c\uc545<\/li>\n\n\n\n<li>7\uc77c \uc774\uc0c1: \uc8fc\uac04 \ud328\ud134, \ud658\uacbd \uc601\ud5a5 \ubd84\uc11d<\/li>\n\n\n\n<li>\uc7a5\uae30 \ubaa8\ub2c8\ud130\ub9c1: \uc218\uac1c\uc6d4~\uc218\ub144<\/li>\n<\/ul>\n\n\n\n<p><strong>3. \ud658\uacbd \uc870\uac74<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\uc548\ud14c\ub098 \uc704\uce58: \ud558\ub298\uc774 \ucd5c\ub300\ud55c \uc5f4\ub9b0 \uacf3<\/li>\n\n\n\n<li>\uc8fc\ubcc0 \uc7a5\uc560\ubb3c: \uac74\ubb3c, \ub098\ubb34 \ub4f1\uc73c\ub85c\ubd80\ud130 \ucda9\ubd84\ud55c \uac70\ub9ac<\/li>\n\n\n\n<li>\uc804\uc6d0 \uc548\uc815\uc131: UPS \ub4f1\uc73c\ub85c \uc5f0\uc18d \uce21\uc815 \ubcf4\uc7a5<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">\uacbd\ubcf4 \uc2dc\uc2a4\ud15c \uad6c\ucd95<\/h3>\n\n\n\n<p>\uc2e4\uc2dc\uac04 \ubaa8\ub2c8\ud130\ub9c1\uc744 \uc704\ud55c \uacbd\ubcf4 \uc2dc\uc2a4\ud15c:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">def check_displacement_alarm(df, thresholds):\n    \"\"\"\n    \ubcc0\uc704 \uc784\uacc4\uac12 \ucd08\uacfc \uc2dc \uacbd\ubcf4\n    \"\"\"\n    # \ucd5c\uadfc 10\uac1c \ub370\uc774\ud130\uc758 \ud3c9\uade0\uc73c\ub85c \ud310\ub2e8 (\uc21c\uac04\uc801 \ub178\uc774\uc988 \ubc29\uc9c0)\n    recent_data = df.iloc[-10:]\n\n    current_horizontal = recent_data['horizontal_displacement'].mean()\n    current_vertical = recent_data['vertical_displacement'].mean()\n\n    alerts = []\n\n    if abs(current_horizontal) > thresholds['horizontal']:\n        alert_msg = f\"\u26a0\ufe0f \uc218\ud3c9 \ubcc0\uc704 \uacbd\uace0: {current_horizontal*1000:.1f}mm\"\n        alerts.append(alert_msg)\n        print(alert_msg)\n\n    if current_vertical &lt; -thresholds['vertical_subsidence']:\n        alert_msg = f\"\u26a0\ufe0f \uce68\ud558 \uacbd\uace0: {current_vertical*1000:.1f}mm\"\n        alerts.append(alert_msg)\n        print(alert_msg)\n\n    if current_vertical > thresholds['vertical_uplift']:\n        alert_msg = f\"\u26a0\ufe0f \uc735\uae30 \uacbd\uace0: {current_vertical*1000:.1f}mm\"\n        alerts.append(alert_msg)\n        print(alert_msg)\n\n    return alerts\n\n# \uc784\uacc4\uac12 \uc124\uc815 (\uad6c\uc870\ubb3c \uc885\ub958\uc5d0 \ub530\ub77c \uc870\uc815)\nthresholds = {\n    'horizontal': 0.05,           # \uc218\ud3c9 5cm\n    'vertical_subsidence': 0.10,  # \uce68\ud558 10cm\n    'vertical_uplift': 0.05       # \uc735\uae30 5cm\n}\n\nalerts = check_displacement_alarm(df_clean, thresholds)<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">\uace0\uae09 \uae30\ubc95: Kalman \ud544\ud130<\/h2>\n\n\n\n<p>\ub354 \uc815\ubc00\ud55c \ubd84\uc11d\uc774 \ud544\uc694\ud55c \uacbd\uc6b0, Kalman \ud544\ud130\ub97c \ucd94\uac00\ub85c \uc801\uc6a9\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">from filterpy.kalman import KalmanFilter\nfrom filterpy.common import Q_discrete_white_noise\n\ndef apply_kalman_filter(df):\n    \"\"\"\n    Kalman \ud544\ud130\ub85c \ub178\uc774\uc988 \uc81c\uac70 \ubc0f \uc544\uc6c3\ub77c\uc774\uc5b4 \uac10\uc9c0\n    \"\"\"\n    df = df.sort_values('timestamp').reset_index(drop=True)\n\n    # 3\ucc28\uc6d0 \uc704\uce58\uc5d0 \ub300\ud55c Kalman \ud544\ud130\n    kf = KalmanFilter(dim_x=3, dim_z=3)\n\n    # \ucd08\uae30 \uc0c1\ud0dc\n    kf.x = np.array([\n        df['east_displacement'].iloc[0],\n        df['north_displacement'].iloc[0],\n        df['vertical_displacement'].iloc[0]\n    ])\n\n    # \uc0c1\ud0dc \uc804\uc774 \ud589\ub82c (\uc704\uce58\ub9cc, \uc18d\ub3c4 \uc5c6\uc74c)\n    kf.F = np.eye(3)\n\n    # \uad00\uce21 \ud589\ub82c\n    kf.H = np.eye(3)\n\n    # \ud504\ub85c\uc138\uc2a4 \ub178\uc774\uc988 (\uad6c\uc870\ubb3c\uc740 \ucc9c\ucc9c\ud788 \ubcc0\ud568)\n    kf.Q = Q_discrete_white_noise(dim=3, dt=1.0, var=0.0001)\n\n    # \uce21\uc815 \ub178\uc774\uc988 (RTK GPS \uc815\ud655\ub3c4: ~1cm)\n    kf.R = np.eye(3) * 0.01**2\n\n    # \ud544\ud130\ub9c1 \uc2e4\ud589\n    filtered_positions = []\n    innovations = []\n\n    for idx, row in df.iterrows():\n        kf.predict()\n\n        z = np.array([\n            row['east_displacement'],\n            row['north_displacement'],\n            row['vertical_displacement']\n        ])\n\n        kf.update(z)\n\n        # Innovation (\uce21\uc815\uac12 - \uc608\uce21\uac12)\n        innovation = z - kf.x\n        innovations.append(np.linalg.norm(innovation))\n\n        filtered_positions.append(kf.x.copy())\n\n    # Innovation\uc774 \ud070 \uc810\uc744 \uc544\uc6c3\ub77c\uc774\uc5b4\ub85c \ud310\uc815\n    innovations = np.array(innovations)\n    threshold = np.median(innovations) + 3 * np.std(innovations)\n\n    outlier_mask = innovations > threshold\n    df_clean = df[~outlier_mask].copy()\n\n    # \ud544\ud130\ub9c1\ub41c \uc704\uce58 \uc800\uc7a5\n    filtered_positions = np.array(filtered_positions)\n    df_clean['filtered_east'] = filtered_positions[~outlier_mask, 0]\n    df_clean['filtered_north'] = filtered_positions[~outlier_mask, 1]\n    df_clean['filtered_vertical'] = filtered_positions[~outlier_mask, 2]\n\n    return df_clean\n\n# Kalman \ud544\ud130\ub97c \ud30c\uc774\ud504\ub77c\uc778\uc5d0 \ucd94\uac00\ndf_kalman = apply_kalman_filter(df_clean)<\/pre>\n\n\n\n<p><strong>Kalman \ud544\ud130\uc758 \uc7a5\uc810<\/strong>:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\uce21\uc815 \ub178\uc774\uc988\uc640 \uc2e4\uc81c \ubcc0\uc704\ub97c \ud1b5\uacc4\uc801\uc73c\ub85c \ubd84\ub9ac<\/li>\n\n\n\n<li>\uc810\uc9c4\uc801 \ubcc0\ud654\ub97c \ub354\uc6b1 \ubd80\ub4dc\ub7fd\uac8c \ucd94\uc815<\/li>\n\n\n\n<li>\uc608\uce21 \uae30\ub2a5\uc73c\ub85c \ub2e4\uc74c \uce21\uc815\uac12 \uc608\uc0c1 \uac00\ub2a5<\/li>\n<\/ul>\n\n\n\n<p><strong>\uc8fc\uc758\uc0ac\ud56d<\/strong>:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\ud30c\ub77c\ubbf8\ud130 \ud29c\ub2dd\uc774 \uc911\uc694 (Q, R \ud589\ub82c)<\/li>\n\n\n\n<li>\uacc4\uc0b0\ub7c9\uc774 \ub9ce\uc544 \uc2e4\uc2dc\uac04 \ucc98\ub9ac \uc2dc \uace0\ub824 \ud544\uc694<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">\ubc29\ubc95\ub860 \ube44\uad50 \ubc0f \uc120\ud0dd \uac00\uc774\ub4dc<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">\uac01 \ubc29\ubc95\uc758 \ud2b9\uc131<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>\ubc29\ubc95<\/th><th>\uac15\uc810<\/th><th>\uc57d\uc810<\/th><th>\uc801\uc6a9 \uc2dc\uc810<\/th><\/tr><\/thead><tbody><tr><td>Fix\/\uc704\uc131 \ud544\ud130<\/td><td>\uba85\ud655\ud55c \uae30\uc900, \ube60\ub984<\/td><td>\ud488\uc9c8 \uc88b\uc740 \ub370\uc774\ud130\ub3c4 \uc190\uc2e4 \uac00\ub2a5<\/td><td>1\ucc28 \ud544\ud130\ub9c1<\/td><\/tr><tr><td>\uae09\uaca9\ud55c \uc810\ud504 \uc81c\uac70<\/td><td>\uba85\ubc31\ud55c \uc624\ub958 \uc81c\uac70<\/td><td>\uc2e4\uc81c \uae09\uaca9\ud55c \ubcc0\ud654 \uc2dc \ubb38\uc81c<\/td><td>2\ucc28 \ud544\ud130\ub9c1<\/td><\/tr><tr><td>MAD<\/td><td>\uc544\uc6c3\ub77c\uc774\uc5b4\uc5d0 \uac15\uac74<\/td><td>\uc815\uaddc\ubd84\ud3ec \uc544\ub2d0 \ub54c \ubcf4\uc218\uc801<\/td><td>\ud575\uc2ec \ubc29\ubc95<\/td><\/tr><tr><td>\uc774\ub3d9 \uc911\uc559\uac12<\/td><td>\uc810\uc9c4\uc801 \ubcc0\ud654 \ubcf4\uc874<\/td><td>\uc708\ub3c4\uc6b0 \ud06c\uae30 \uc120\ud0dd \uc911\uc694<\/td><td>\uc2dc\uacc4\uc5f4 \ud2b9\ud654<\/td><\/tr><tr><td>Kalman \ud544\ud130<\/td><td>\uc815\ubc00\ub3c4 \ucd5c\uace0<\/td><td>\ubcf5\uc7a1, \ud30c\ub77c\ubbf8\ud130 \uc870\uc815 \ud544\uc694<\/td><td>\uace0\uae09 \ubd84\uc11d<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">\uad8c\uc7a5 \uc870\ud569<\/h3>\n\n\n\n<p><strong>\uae30\ubcf8 \uc870\ud569<\/strong> (\ub300\ubd80\ubd84\uc758 \uacbd\uc6b0):<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Fix\/\uc704\uc131 \ud544\ud130<\/li>\n\n\n\n<li>\uae09\uaca9\ud55c \uc810\ud504 \uc81c\uac70<\/li>\n\n\n\n<li>MAD \ud544\ud130<\/li>\n<\/ol>\n\n\n\n<p><strong>\uc815\ubc00 \uc870\ud569<\/strong> (\uace0\uc815\ubc00\ub3c4 \uc694\uad6c \uc2dc):<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Fix\/\uc704\uc131 \ud544\ud130 (\uc5c4\uaca9)<\/li>\n\n\n\n<li>\uae09\uaca9\ud55c \uc810\ud504 \uc81c\uac70<\/li>\n\n\n\n<li>MAD \ud544\ud130<\/li>\n\n\n\n<li>\uc774\ub3d9 \uc911\uc559\uac12 \ud544\ud130<\/li>\n\n\n\n<li>Kalman \ud544\ud130<\/li>\n<\/ol>\n\n\n\n<p><strong>\ube60\ub978 \uc870\ud569<\/strong> (\uc2e4\uc2dc\uac04 \ucc98\ub9ac):<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Fix\/\uc704\uc131 \ud544\ud130<\/li>\n\n\n\n<li>\uae09\uaca9\ud55c \uc810\ud504 \uc81c\uac70<\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">\uc2e4\uc81c \uc801\uc6a9 \uc0ac\ub840<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Case 1: \uad50\ub7c9 \ubaa8\ub2c8\ud130\ub9c1<\/h3>\n\n\n\n<p><strong>\uc0c1\ud669<\/strong>: \ub300\ud615 \uad50\ub7c9\uc758 \ucc98\uc9d0 \uce21\uc815<br><strong>\uc694\uad6c\uc0ac\ud56d<\/strong>: mm \ub2e8\uc704 \uc815\ubc00\ub3c4<br><strong>\uc801\uc6a9 \ubc29\ubc95<\/strong>:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>1Hz \uc0d8\ud50c\ub9c1, 24\uc2dc\uac04 \uc5f0\uc18d \uce21\uc815<\/li>\n\n\n\n<li>\uc5c4\uaca9\ud55c Fix \ud544\ud130 (Fixed RTK only)<\/li>\n\n\n\n<li>MAD \ud544\ud130 + \uc774\ub3d9 \uc911\uc559\uac12<\/li>\n\n\n\n<li>Kalman \ud544\ud130 \ucd94\uac00<\/li>\n<\/ul>\n\n\n\n<p><strong>\uacb0\uacfc<\/strong>:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\uc218\uc9c1 \uc815\ubc00\ub3c4: \u00b12mm (2\u03c3)<\/li>\n\n\n\n<li>\uc77c\uc77c \uc628\ub3c4 \ubcc0\ud654\uc5d0 \ub530\ub978 3-5mm \ucc98\uc9d0 \uac10\uc9c0 \uc131\uacf5<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Case 2: \ub310 \uc548\uc804 \ubaa8\ub2c8\ud130\ub9c1<\/h3>\n\n\n\n<p><strong>\uc0c1\ud669<\/strong>: \ub310 \uc81c\uccb4\uc758 \uc218\ud3c9\/\uc218\uc9c1 \ubcc0\uc704 \uc7a5\uae30 \ubaa8\ub2c8\ud130\ub9c1<br><strong>\uc694\uad6c\uc0ac\ud56d<\/strong>: \uc7a5\uae30 \ucd94\uc138 \ubd84\uc11d<br><strong>\uc801\uc6a9 \ubc29\ubc95<\/strong>:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>1Hz \uc0d8\ud50c\ub9c1, \uc5f0\uc18d \uce21\uc815<\/li>\n\n\n\n<li>\ud45c\uc900 \ud30c\ub77c\ubbf8\ud130 \uc138\ud2b8<\/li>\n\n\n\n<li>\uc8fc\uac04 \ub2e8\uc704 \ub370\uc774\ud130 \uac80\ud1a0<\/li>\n<\/ul>\n\n\n\n<p><strong>\uacb0\uacfc<\/strong>:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\uc5f0\uac04 2mm \uce68\ud558 \ucd94\uc138 \ud655\uc778<\/li>\n\n\n\n<li>\uac15\uc6b0 \uc2dc \uc77c\uc2dc\uc801 \ubcc0\uc704 \ud328\ud134 \ubc1c\uacac<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Case 3: \uc9c0\ubc18 \uce68\ud558 \ubaa8\ub2c8\ud130\ub9c1<\/h3>\n\n\n\n<p><strong>\uc0c1\ud669<\/strong>: \ub3c4\uc2ec\uc9c0 \ud130\ub110 \uacf5\uc0ac \uc8fc\ubcc0 \uc9c0\ubc18 \uce68\ud558<br><strong>\uc694\uad6c\uc0ac\ud56d<\/strong>: \uc2e4\uc2dc\uac04 \uacbd\ubcf4<br><strong>\uc801\uc6a9 \ubc29\ubc95<\/strong>:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>5Hz \uc0d8\ud50c\ub9c1<\/li>\n\n\n\n<li>\ube60\ub978 \uc870\ud569 (\uc2e4\uc2dc\uac04 \ucc98\ub9ac)<\/li>\n\n\n\n<li>\uc790\ub3d9 \uacbd\ubcf4 \uc2dc\uc2a4\ud15c \uc5f0\ub3d9<\/li>\n<\/ul>\n\n\n\n<p><strong>\uacb0\uacfc<\/strong>:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\uc77c\uc77c 1mm \uce68\ud558 \uac10\uc9c0 \ubc0f \uacbd\ubcf4<\/li>\n\n\n\n<li>\uacf5\uc0ac \uc548\uc804 \uad00\ub9ac \uac15\ud654<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">\uacb0\ub860<\/h2>\n\n\n\n<p>RTK GPS\ub97c \uc774\uc6a9\ud55c \uad6c\uc870\ubb3c \ubaa8\ub2c8\ud130\ub9c1\uc5d0\uc11c \uc815\ud655\ud55c \ubcc0\uc704 \uce21\uc815\uc744 \uc704\ud574\uc11c\ub294 \uccb4\uacc4\uc801\uc778 \uc544\uc6c3\ub77c\uc774\uc5b4 \uac80\ucd9c\uc774 \ud544\uc218\uc801\uc785\ub2c8\ub2e4. \ubcf8 \uae00\uc5d0\uc11c \uc18c\uac1c\ud55c \ubc29\ubc95\ub4e4\uc740 \ub2e4\uc74c\uacfc \uac19\uc740 \uc21c\uc11c\ub85c \uc801\uc6a9\ud558\ub294 \uac83\uc744 \uad8c\uc7a5\ud569\ub2c8\ub2e4:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\ud488\uc9c8 \uae30\ubc18 1\ucc28 \ud544\ud130\ub9c1<\/strong>: Fix \uc0c1\ud0dc, \uc704\uc131 \uac1c\uc218, HDOP<\/li>\n\n\n\n<li><strong>\uae30\uc900 \uc704\uce58 \uc124\uc815<\/strong>: \uc911\uc559\uac12 \uae30\ubc18 \uc548\uc815\uc801 \uae30\uc900\uc810<\/li>\n\n\n\n<li><strong>\uae09\uaca9\ud55c \ubcc0\ud654 \uc81c\uac70<\/strong>: \ubb3c\ub9ac\uc801\uc73c\ub85c \ubd88\uac00\ub2a5\ud55c \uc810\ud504 \uc81c\uac70<\/li>\n\n\n\n<li><strong>\ud1b5\uacc4\uc801 \ud544\ud130\ub9c1<\/strong>: MAD \ub610\ub294 3-Sigma<\/li>\n\n\n\n<li><strong>\uc2dc\uacc4\uc5f4 \ud544\ud130\ub9c1<\/strong>: \uc774\ub3d9 \uc911\uc559\uac12\uc73c\ub85c \uc810\uc9c4\uc801 \ubcc0\ud654 \ubcf4\uc874<\/li>\n\n\n\n<li><strong>\uace0\uae09 \ud544\ud130\ub9c1<\/strong> (\uc120\ud0dd): Kalman \ud544\ud130\ub85c \ucd5c\uc885 \uc815\ubc00\ub3c4 \ud5a5\uc0c1<\/li>\n<\/ol>\n\n\n\n<p>\uac01 \uad6c\uc870\ubb3c\uc758 \ud2b9\uc131\uacfc \uc694\uad6c\uc0ac\ud56d\uc5d0 \ub9de\ucdb0 \ud30c\ub77c\ubbf8\ud130\ub97c \uc870\uc815\ud558\uace0, \uc9c0\uc18d\uc801\uc778 \ubaa8\ub2c8\ud130\ub9c1\uacfc \uac80\uc99d\uc744 \ud1b5\ud574 \ucd5c\uc801\uc758 \uc124\uc815\uc744 \ucc3e\ub294 \uac83\uc774 \uc911\uc694\ud569\ub2c8\ub2e4.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>RTK GPS\ub294 mm \ub2e8\uc704\uc758 \uc815\ubc00\ub3c4\ub85c \uc704\uce58\ub97c \uce21\uc815\ud560 \uc218 \uc788\uc5b4 \uad6c\uc870\ubb3c \ubaa8\ub2c8\ud130\ub9c1, \uc9c0\ubc18 \uce68\ud558 \uce21\uc815, \ub310 \uc548\uc804 \uad00\ub9ac \ub4f1\uc5d0 \ub110\ub9ac \ud65c\uc6a9\ub429\ub2c8\ub2e4. \ud558\uc9c0\ub9cc \uc2e4\uc81c \ud604\uc7a5\uc5d0\uc11c \uc218\uc9d1\ub41c \ub370\uc774\ud130\uc5d0\ub294 \ub2e4\uc591\ud55c \uc6d0\uc778\uc73c\ub85c \uc778\ud55c \uc544\uc6c3\ub77c\uc774\uc5b4(\uc774\uc0c1\uce58)\uac00 \ud3ec\ud568\ub418\uc5b4 \uc788\uc5b4, \uc815\ud655\ud55c \ubcc0\uc704 \ubd84\uc11d\uc744 \uc704\ud574\uc11c\ub294 \uccb4\uacc4\uc801\uc778 \ub370\uc774\ud130 \uc815\uc81c\uac00 \ud544\uc218\uc801\uc785\ub2c8\ub2e4. \uc774 \uae00\uc5d0\uc11c\ub294 \uace0\uc815\ub41c \ub85c\ubc84\ub97c \uc774\uc6a9\ud55c \uad6c\uc870\ubb3c \ubaa8\ub2c8\ud130\ub9c1\uc5d0 \ud2b9\ud654\ub41c \uc544\uc6c3\ub77c\uc774\uc5b4 \uac80\ucd9c \ubc29\ubc95\uc744 \uc18c\uac1c\ud569\ub2c8\ub2e4. RTK GPS \ub370\uc774\ud130\uc758 \ud2b9\uc131\uacfc<\/p>\n<div class=\"more-link\">\n\t\t\t\t <a href=\"http:\/\/practical.kr\/?p=873\" class=\"link-btn theme-btn\"><span>Read More <\/span> <i class=\"fa fa-caret-right\"><\/i><\/a>\n\t\t\t<\/div>\n","protected":false},"author":1,"featured_media":874,"comment_status":"closed","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[116,33,35],"tags":[118,117],"class_list":["post-873","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-gps","category-iot","category-python","tag-gps","tag-rtk"],"jetpack_featured_media_url":"http:\/\/practical.kr\/wp-content\/uploads\/2025\/11\/rtkgps2.jpg","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"http:\/\/practical.kr\/index.php?rest_route=\/wp\/v2\/posts\/873","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/practical.kr\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/practical.kr\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/practical.kr\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/practical.kr\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=873"}],"version-history":[{"count":2,"href":"http:\/\/practical.kr\/index.php?rest_route=\/wp\/v2\/posts\/873\/revisions"}],"predecessor-version":[{"id":876,"href":"http:\/\/practical.kr\/index.php?rest_route=\/wp\/v2\/posts\/873\/revisions\/876"}],"wp:featuredmedia":[{"embeddable":true,"href":"http:\/\/practical.kr\/index.php?rest_route=\/wp\/v2\/media\/874"}],"wp:attachment":[{"href":"http:\/\/practical.kr\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=873"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/practical.kr\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=873"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/practical.kr\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=873"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}