The example I use below is a minimal network with 3 baselines, 1 reference point and 2 points to determine. The workflow would be as follows.
- Do all your PPK work in Emlid Studio with the following settings.
Name the output file correctly with the format BASE_ROVER, like here CHTL is the base and C8 is the rover.
Select the output format to be ECEF-X/Y/Z.
![image](https://community.emlid.com/uploads/default/original/3X/b/6/b623232839fec63a3e951b9a122c51b128b812a7.png)
You then have a bunch of POS files. Put them all in a single folder named as you wish, for example “my_pos_files_folder”. DO NOT put the *_events.pos in there, for scripting convenience. In my example, we have 3 baselines so 3 POS files.
-
After installation, open SALSA and create a new project in Project > New. Input the name and path to the project file. It created a .proj file that you can open with a Notepad.
![image](https://community.emlid.com/uploads/default/original/3X/f/e/fe81e908a7c15ae376117fecc7efb0c56b0a383b.png)
-
Put the focus in the project window and add the reference points in the project in Record > Insert > and POSC for cartesian inputs, or POSG for geographic inputs.
Example with the reference point CHTL here.
The point is added in the project window.
Click on Project > Save. You also see the info of this reference point in the proj file, in a Notepad.
![image](https://community.emlid.com/uploads/default/original/3X/8/c/8c535e667356f70b314cf04868c14098c5e5a0b4.png)
- Add the baselines in the project. As it needs DXYZ format, that is where the script become handy. You can run the script below to generate a txt file with the concatenated information readable by SALSA. Just edit line 85 to point on your POS files folder.
# -*- coding: utf-8 -*-
"""
Created on Sun Jul 16 11:19:11 2023
@author: Florian Birot - FB Geomatics
"""
import os
import re # to do some cool regex :-)
import pandas as pd
from datetime import datetime
def posfile2DXYZ(file_in):
"Reads the baseline info of a pos file made by Emlid Studio and return a DXYZ text block readable by SALSA"
filename = os.path.split(file_in)
file, ext = os.path.splitext(filename[-1])
base_name, rover_name = file.split('_') # works only if you respect the POS file naming convention BASE_ROVER.pos
with open(file_in) as f:
baseline_data = f.read().split('\n')[:-1]
# deal with the base information
ref_pos = next(l for l in baseline_data if l.startswith('% ref pos'))
# ref_lat, ref_long, ref_h = [float(c) for c in re.findall(r"[-+]?(?:\d*\.*\d+)", ref_pos)]
# ref_x, ref_y, ref_z = geo2ecef(ref_long, ref_lat, ref_h)
ref_x, ref_y, ref_z = [float(c) for c in re.findall(r"[-+]?(?:\d*\.*\d+)", ref_pos)]
# deal with the rover information
rov_data = baseline_data[-1]
computed_at = datetime.strptime(rov_data[:23], "%Y/%m/%d %H:%M:%S.%f")
rov_x, rov_y, rov_z, q, ns, sdx, sdy, sdz, sdxy, sdyz, sdzx, age, ratio = [float(c) for c in re.findall(r"[-+]?(?:\d*\.*\d+)", rov_data[23:])]
# construct a baseline Pandas Series for convenience
s = pd.Series({
"computed_at": computed_at,
"base": base_name,
"rover": rover_name,
"dx": rov_x - ref_x,
"dy": rov_y - ref_y,
"dz": rov_z - ref_z,
"cx": '%.3e' % sdx**2,
"cy": '%.3e' % sdy**2,
"cz": '%.3e' % sdz**2,
"cxy": '%.3e' % sdxy**2,
"cyz": '%.3e' % sdyz**2,
"cxz": '%.3e' % sdzx**2,
"l_cx": " ",
"l_cy": " ",
"l_cz": " ",
"l_cxy": " ",
"l_cyz": " ",
"l_cxz": " "
})
# construct the text block
line1 = f"DXYZ {s.base} {s.rover} {s.dx:.5f} {s.dy:.5f} {s.dz:.5f} m ...\n"
line2 = f"{s.l_cx}{s.cx}{s.l_cxy}{s.cxy}{s.l_cxz}{s.cxz} ...\n"
line3 = f"{s.l_cy}{s.cy}{s.l_cyz}{s.cyz} ...\n"
line4 = f"{s.l_cz}{s.cz}\n"
return line1 + line2 + line3 + line4
def buildDXYZ_from_folder(folder_in, file_out):
"builds a TXT file with DXYZ blocks readable by SALSA from the folder where POS files are stored"
pos_files = [os.path.join(folder_in,f) for f in os.listdir(folder_in) if f.endswith('.pos')]
# clear
if os.path.isfile(file_out):
os.remove(file_out)
# writes content
with open(file_out, "a") as f:
for file in pos_files:
f.write(posfile2DXYZ(file))
# LET'S GO
# set the pos_folder parameter with your local path to the folder where pos files are
pos_folder = "my_pos_files_folder" # do not put *_events.pos in this folder
# and run the function with this folder and the output file
buildDXYZ_from_folder(pos_folder, "dxyz_blocks.txt")
That created the file dxyz_blocs.txt, that you can open in a Notepad.
![image](https://community.emlid.com/uploads/default/original/3X/8/0/802dc74ea292330331ba13c5b193310019c92938.png)
-
Open the SALSA .proj file in a notepad. Copy the content of the script output file and paste it to append it to the .proj file. Then Save the file.
![image](https://community.emlid.com/uploads/default/original/3X/3/6/369d120af5fcc267edc098ee6bb6cde0b690efe4.png)
-
In SALSA, click on Project > Reload. Your baselines now appear in the project.
-
Generate the initial positions by clicking on Project > Generate initial position. You then see every point in the map on bottom right view.
![image](https://community.emlid.com/uploads/default/original/3X/9/f/9f20cc4ecebaa2f9a55ae45519a6f20d9be1faaf.png)
![image](https://community.emlid.com/uploads/default/original/3X/0/6/06aaba9f0a67adea9db634537402b2cd7e971cd9.png)
-
Do the network adjustement by clicking on Project > Calculate adjustment.
-
That created a CSV file with the projet name. The final coordinates are in there.
I won’t go into the details of analyzing the residuals and chi-squared test here.