Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
I
imagej-elphel
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
3
Issues
3
List
Board
Labels
Milestones
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
Elphel
imagej-elphel
Commits
3dbc0525
Commit
3dbc0525
authored
Mar 05, 2026
by
Andrey Filippov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implementing compatible flight log from DJI mini4 pro SRT files
parent
f84524bd
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
290 additions
and
30 deletions
+290
-30
EyesisCorrectionParameters.java
...com/elphel/imagej/cameras/EyesisCorrectionParameters.java
+11
-1
DjiSrt.java
src/main/java/com/elphel/imagej/ims/DjiSrt.java
+27
-19
DjiSrtReader.java
src/main/java/com/elphel/imagej/ims/DjiSrtReader.java
+203
-0
UasLogReader.java
src/main/java/com/elphel/imagej/ims/UasLogReader.java
+42
-8
UasLogRecord.java
src/main/java/com/elphel/imagej/ims/UasLogRecord.java
+7
-2
No files found.
src/main/java/com/elphel/imagej/cameras/EyesisCorrectionParameters.java
View file @
3dbc0525
...
@@ -2545,7 +2545,17 @@ public class EyesisCorrectionParameters {
...
@@ -2545,7 +2545,17 @@ public class EyesisCorrectionParameters {
if
(
this
.
cuasUasLogs
.
length
()
==
0
)
{
if
(
this
.
cuasUasLogs
.
length
()
==
0
)
{
return
""
;
return
""
;
}
}
if
(!
this
.
cuasUasLogs
.
endsWith
(
".json"
))
{
String
lowerPath
=
this
.
cuasUasLogs
.
toLowerCase
();
boolean
explicitExt
=
lowerPath
.
endsWith
(
".json"
)
||
lowerPath
.
endsWith
(
".srt"
)
||
lowerPath
.
contains
(
"*.srt"
)
||
lowerPath
.
contains
(
","
)
||
lowerPath
.
contains
(
";"
)
||
lowerPath
.
contains
(
"*"
)
||
lowerPath
.
contains
(
"?"
)
||
lowerPath
.
endsWith
(
Prefs
.
getFileSeparator
());
if
(!
explicitExt
)
{
this
.
cuasUasLogs
=
this
.
cuasUasLogs
+
".json"
;
this
.
cuasUasLogs
=
this
.
cuasUasLogs
+
".json"
;
}
}
return
this
.
cuasUasLogs
;
return
this
.
cuasUasLogs
;
...
...
src/main/java/com/elphel/imagej/ims/DjiSrt.java
View file @
3dbc0525
...
@@ -48,7 +48,7 @@ public class DjiSrt {
...
@@ -48,7 +48,7 @@ public class DjiSrt {
int
iso
=
-
1
;
int
iso
=
-
1
;
double
shutter
=
Double
.
NaN
;
double
shutter
=
Double
.
NaN
;
double
fnum
=
Double
.
NaN
;
double
fnum
=
Double
.
NaN
;
int
ev
=
-
1
;
double
ev
=
Double
.
NaN
;
String
color_md
=
""
;
String
color_md
=
""
;
double
focal_len
=
Double
.
NaN
;
double
focal_len
=
Double
.
NaN
;
double
latitude
=
Double
.
NaN
;
double
latitude
=
Double
.
NaN
;
...
@@ -132,25 +132,33 @@ public class DjiSrt {
...
@@ -132,25 +132,33 @@ public class DjiSrt {
for
(
int
k
=
0
;
k
<
SRT_KEYWORDS
.
length
;
k
++)
{
for
(
int
k
=
0
;
k
<
SRT_KEYWORDS
.
length
;
k
++)
{
if
(
s
.
startsWith
(
SRT_KEYWORDS
[
k
])){
if
(
s
.
startsWith
(
SRT_KEYWORDS
[
k
])){
String
sv
=
s
.
substring
(
SRT_KEYWORDS
[
k
].
length
()+
1
,
iclos
).
trim
();
String
sv
=
s
.
substring
(
SRT_KEYWORDS
[
k
].
length
()+
1
,
iclos
).
trim
();
switch
(
k
)
{
try
{
case
I_iso:
djiSrt
.
iso
=
Integer
.
parseInt
(
sv
);
break
;
switch
(
k
)
{
case
I_shutter:
djiSrt
.
shutter
=
1.0
/
Double
.
parseDouble
(
sv
.
substring
(
2
));
break
;
case
I_iso:
djiSrt
.
iso
=
Integer
.
parseInt
(
sv
);
break
;
case
I_fnum:
djiSrt
.
fnum
=
Double
.
parseDouble
(
sv
);
break
;
case
I_shutter:
djiSrt
.
shutter
=
1.0
/
Double
.
parseDouble
(
sv
.
substring
(
2
));
break
;
case
I_ev:
djiSrt
.
ev
=
Integer
.
parseInt
(
sv
);
break
;
case
I_fnum:
djiSrt
.
fnum
=
Double
.
parseDouble
(
sv
);
break
;
case
I_color_md:
djiSrt
.
color_md
=
sv
;
break
;
case
I_ev:
djiSrt
.
ev
=
Double
.
parseDouble
(
sv
);
break
;
case
I_focal_len:
djiSrt
.
focal_len
=
Double
.
parseDouble
(
sv
);
break
;
case
I_color_md:
djiSrt
.
color_md
=
sv
;
break
;
case
I_latitude:
djiSrt
.
latitude
=
Double
.
parseDouble
(
sv
);
break
;
case
I_focal_len:
djiSrt
.
focal_len
=
Double
.
parseDouble
(
sv
);
break
;
case
I_longitude:
djiSrt
.
longitude
=
Double
.
parseDouble
(
sv
);
break
;
case
I_latitude:
djiSrt
.
latitude
=
Double
.
parseDouble
(
sv
);
break
;
case
I_rel_alt:
case
I_longitude:
djiSrt
.
longitude
=
Double
.
parseDouble
(
sv
);
break
;
int
ispilt
=
sv
.
indexOf
(
" "
);
case
I_rel_alt:
djiSrt
.
rel_alt
=
Double
.
parseDouble
(
sv
.
substring
(
0
,
ispilt
));
int
ispilt
=
sv
.
indexOf
(
" "
);
String
sv2
=
sv
.
substring
(
ispilt
).
trim
();
if
(
ispilt
>
0
)
{
if
(
sv2
.
startsWith
(
SRT_KEYWORDS
[
I_abs_alt
]))
{
djiSrt
.
rel_alt
=
Double
.
parseDouble
(
sv
.
substring
(
0
,
ispilt
));
sv2
=
sv2
.
substring
(
SRT_KEYWORDS
[
I_abs_alt
].
length
()
+
1
).
trim
();
String
sv2
=
sv
.
substring
(
ispilt
).
trim
();
djiSrt
.
abs_alt
=
Double
.
parseDouble
(
sv2
);
if
(
sv2
.
startsWith
(
SRT_KEYWORDS
[
I_abs_alt
]))
{
sv2
=
sv2
.
substring
(
SRT_KEYWORDS
[
I_abs_alt
].
length
()
+
1
).
trim
();
djiSrt
.
abs_alt
=
Double
.
parseDouble
(
sv2
);
}
}
else
{
djiSrt
.
rel_alt
=
Double
.
parseDouble
(
sv
);
}
break
;
case
I_ct:
djiSrt
.
ct
=
Integer
.
parseInt
(
sv
);
break
;
}
}
break
;
}
catch
(
RuntimeException
e
)
{
case
I_ct:
djiSrt
.
ct
=
Integer
.
parseInt
(
sv
);
break
;
// Keep NaN/default values for malformed fields and continue parsing.
}
}
}
}
}
}
...
...
src/main/java/com/elphel/imagej/ims/DjiSrtReader.java
View file @
3dbc0525
package
com
.
elphel
.
imagej
.
ims
;
package
com
.
elphel
.
imagej
.
ims
;
import
java.io.IOException
;
import
java.nio.file.DirectoryStream
;
import
java.nio.file.Files
;
import
java.nio.file.Path
;
import
java.nio.file.Paths
;
import
java.util.ArrayList
;
import
java.util.Comparator
;
import
java.util.LinkedHashSet
;
public
class
DjiSrtReader
{
public
class
DjiSrtReader
{
private
final
String
pathSpec
;
private
final
ArrayList
<
String
>
sourceFiles
=
new
ArrayList
<
String
>();
private
UasLogRecord
[]
rec_arr
=
null
;
private
double
firstEpochSeconds
=
Double
.
NaN
;
private
double
lastEpochSeconds
=
Double
.
NaN
;
private
static
class
SrtRow
{
double
epochSeconds
;
double
latitude
;
double
longitude
;
double
relAlt
;
}
public
DjiSrtReader
(
String
path
)
{
public
DjiSrtReader
(
String
path
)
{
this
.
pathSpec
=
path
;
load
();
}
public
UasLogRecord
[]
getRecords
()
{
return
rec_arr
;
}
public
double
getFirstEpochSeconds
()
{
return
firstEpochSeconds
;
}
public
double
getLastEpochSeconds
()
{
return
lastEpochSeconds
;
}
public
String
[]
getSourceFiles
()
{
return
sourceFiles
.
toArray
(
new
String
[
0
]);
}
public
String
getPathSpec
()
{
return
pathSpec
;
}
public
static
boolean
looksLikeSrtPath
(
String
path
)
{
if
(
path
==
null
)
{
return
false
;
}
String
lower
=
path
.
toLowerCase
();
try
{
if
(
Files
.
isDirectory
(
Paths
.
get
(
path
)))
{
return
true
;
}
}
catch
(
RuntimeException
e
)
{
// ignore malformed paths and continue pattern-based checks
}
return
lower
.
contains
(
".srt"
)
||
lower
.
contains
(
"*.srt"
)
||
lower
.
contains
(
"?"
)
||
lower
.
contains
(
"*"
)
||
lower
.
contains
(
";"
)
||
lower
.
contains
(
","
);
}
private
void
load
()
{
ArrayList
<
Path
>
files
=
resolveSrtPaths
(
pathSpec
);
if
(
files
.
isEmpty
())
{
throw
new
IllegalArgumentException
(
"No DJI SRT files found for path: "
+
pathSpec
);
}
ArrayList
<
SrtRow
>
rows
=
new
ArrayList
<
SrtRow
>();
for
(
Path
filePath
:
files
)
{
ArrayList
<
DjiSrt
>
parsed
=
DjiSrt
.
parseDjiSrt
(
filePath
.
toString
());
if
((
parsed
==
null
)
||
parsed
.
isEmpty
())
{
continue
;
}
sourceFiles
.
add
(
filePath
.
toString
());
for
(
DjiSrt
djiSrt
:
parsed
)
{
if
(
djiSrt
.
date
==
null
)
{
continue
;
}
if
(
Double
.
isNaN
(
djiSrt
.
latitude
)
||
Double
.
isNaN
(
djiSrt
.
longitude
))
{
continue
;
}
SrtRow
row
=
new
SrtRow
();
row
.
epochSeconds
=
djiSrt
.
date
.
getTime
()
*
1.0
E
-
3
;
row
.
latitude
=
djiSrt
.
latitude
;
row
.
longitude
=
djiSrt
.
longitude
;
row
.
relAlt
=
Double
.
isNaN
(
djiSrt
.
rel_alt
)
?
0.0
:
djiSrt
.
rel_alt
;
rows
.
add
(
row
);
}
}
if
(
rows
.
isEmpty
())
{
throw
new
IllegalArgumentException
(
"No valid DJI SRT records found for path: "
+
pathSpec
);
}
rows
.
sort
(
new
Comparator
<
SrtRow
>()
{
@Override
public
int
compare
(
SrtRow
lhs
,
SrtRow
rhs
)
{
return
(
lhs
.
epochSeconds
>
rhs
.
epochSeconds
)
?
1
:
(
lhs
.
epochSeconds
<
rhs
.
epochSeconds
)
?
-
1
:
0
;
}
});
firstEpochSeconds
=
rows
.
get
(
0
).
epochSeconds
;
lastEpochSeconds
=
rows
.
get
(
rows
.
size
()
-
1
).
epochSeconds
;
double
homeLat
=
rows
.
get
(
0
).
latitude
;
double
homeLon
=
rows
.
get
(
0
).
longitude
;
ArrayList
<
UasLogRecord
>
recList
=
new
ArrayList
<
UasLogRecord
>(
rows
.
size
());
for
(
SrtRow
row
:
rows
)
{
double
[]
ned
=
Imx5
.
nedFromLla
(
new
double
[]
{
row
.
latitude
,
row
.
longitude
,
row
.
relAlt
},
new
double
[]
{
homeLat
,
homeLon
,
0.0
});
double
distance
=
Math
.
sqrt
(
ned
[
0
]
*
ned
[
0
]
+
ned
[
1
]
*
ned
[
1
]
+
ned
[
2
]
*
ned
[
2
]);
double
relTs
=
row
.
epochSeconds
-
firstEpochSeconds
;
recList
.
add
(
new
UasLogRecord
(
relTs
,
distance
,
row
.
latitude
,
row
.
longitude
,
row
.
relAlt
,
homeLat
,
homeLon
));
}
rec_arr
=
UasLogRecord
.
getArray
(
recList
);
UasLogRecord
.
fillUndefined
(
rec_arr
);
System
.
out
.
println
(
"DjiSrtReader: loaded "
+
rec_arr
.
length
+
" records from "
+
sourceFiles
.
size
()
+
" file(s)"
);
}
private
static
ArrayList
<
Path
>
resolveSrtPaths
(
String
pathSpec
)
{
ArrayList
<
Path
>
files
=
new
ArrayList
<
Path
>();
if
(
pathSpec
==
null
)
{
return
files
;
}
String
[]
tokens
=
splitPathSpec
(
pathSpec
);
LinkedHashSet
<
String
>
unique
=
new
LinkedHashSet
<
String
>();
for
(
String
token
:
tokens
)
{
if
(
token
==
null
)
{
continue
;
}
String
trimmed
=
token
.
trim
();
if
(
trimmed
.
isEmpty
())
{
continue
;
}
collectPaths
(
trimmed
,
unique
);
}
for
(
String
s
:
unique
)
{
files
.
add
(
Paths
.
get
(
s
));
}
files
.
sort
(
new
Comparator
<
Path
>()
{
@Override
public
int
compare
(
Path
lhs
,
Path
rhs
)
{
return
lhs
.
toString
().
compareTo
(
rhs
.
toString
());
}
});
return
files
;
}
private
static
String
[]
splitPathSpec
(
String
pathSpec
)
{
if
((
pathSpec
.
indexOf
(
','
)
<
0
)
&&
(
pathSpec
.
indexOf
(
';'
)
<
0
)
&&
(
pathSpec
.
indexOf
(
'\n'
)
<
0
))
{
return
new
String
[]
{
pathSpec
};
}
return
pathSpec
.
split
(
"[,;\\n]+"
);
}
}
private
static
boolean
hasWildcard
(
String
path
)
{
return
(
path
.
indexOf
(
'*'
)
>=
0
)
||
(
path
.
indexOf
(
'?'
)
>=
0
);
}
private
static
void
collectPaths
(
String
token
,
LinkedHashSet
<
String
>
unique
)
{
Path
path
=
Paths
.
get
(
token
);
if
(
Files
.
isDirectory
(
path
))
{
addDirectorySrt
(
path
,
unique
);
return
;
}
if
(
hasWildcard
(
token
))
{
Path
dir
=
path
.
getParent
();
if
(
dir
==
null
)
{
dir
=
Paths
.
get
(
"."
);
}
String
pattern
=
path
.
getFileName
().
toString
();
addDirectoryPattern
(
dir
,
pattern
,
unique
);
return
;
}
if
(
Files
.
isRegularFile
(
path
)
&&
path
.
toString
().
toLowerCase
().
endsWith
(
".srt"
))
{
unique
.
add
(
path
.
toAbsolutePath
().
normalize
().
toString
());
}
}
private
static
void
addDirectorySrt
(
Path
dir
,
LinkedHashSet
<
String
>
unique
)
{
addDirectoryPattern
(
dir
,
"*.srt"
,
unique
);
addDirectoryPattern
(
dir
,
"*.SRT"
,
unique
);
}
private
static
void
addDirectoryPattern
(
Path
dir
,
String
glob
,
LinkedHashSet
<
String
>
unique
)
{
if
(!
Files
.
isDirectory
(
dir
))
{
return
;
}
try
(
DirectoryStream
<
Path
>
stream
=
Files
.
newDirectoryStream
(
dir
,
glob
))
{
for
(
Path
p
:
stream
)
{
if
(
Files
.
isRegularFile
(
p
)
&&
p
.
toString
().
toLowerCase
().
endsWith
(
".srt"
))
{
unique
.
add
(
p
.
toAbsolutePath
().
normalize
().
toString
());
}
}
}
catch
(
IOException
e
)
{
System
.
err
.
println
(
"DjiSrtReader: failed to list "
+
dir
+
" ("
+
glob
+
"): "
+
e
.
getMessage
());
}
}
}
}
src/main/java/com/elphel/imagej/ims/UasLogReader.java
View file @
3dbc0525
...
@@ -84,10 +84,40 @@ public class UasLogReader {
...
@@ -84,10 +84,40 @@ public class UasLogReader {
QuadCLT
parentCLT
)
throws
JSONException
{
QuadCLT
parentCLT
)
throws
JSONException
{
this
.
parentCLT
=
parentCLT
;
this
.
parentCLT
=
parentCLT
;
setCameraLLA
(
camera_lla
);
setCameraLLA
(
camera_lla
);
setStartTimestamp
(
timestamp
);
if
(
DjiSrtReader
.
looksLikeSrtPath
(
filePath
))
{
// StringBuffer sb = new StringBuffer();
loadDjiSrt
(
filePath
,
timestamp
);
// sb.append(new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(Calendar.getInstance().getTime())+"\n");
}
else
{
// UasLogRecord[] rec_arr = null;
setStartTimestamp
(
timestamp
);
loadJson
(
filePath
);
}
if
((
rec_arr
==
null
)
||
(
rec_arr
.
length
==
0
))
{
throw
new
IllegalArgumentException
(
"No UAS log records loaded from "
+
filePath
);
}
}
private
void
loadDjiSrt
(
String
filePath
,
double
timestamp
)
{
DjiSrtReader
djiSrtReader
=
new
DjiSrtReader
(
filePath
);
rec_arr
=
djiSrtReader
.
getRecords
();
double
startTs
=
timestamp
;
if
(
startTs
==
0.0
)
{
startTs
=
djiSrtReader
.
getFirstEpochSeconds
();
System
.
out
.
println
(
String
.
format
(
"UasLogReader: using DJI SRT first timestamp %.3f as cuasUasTimeStamp (input was 0)"
,
startTs
));
}
setStartTimestamp
(
startTs
);
System
.
out
.
println
(
String
.
format
(
"UasLogReader: loaded DJI SRT path \"%s\": %d records, startTimestamp=%f, source files=%d"
,
filePath
,
rec_arr
.
length
,
start_timestamp
,
djiSrtReader
.
getSourceFiles
().
length
));
}
private
void
loadJson
(
String
filePath
)
throws
JSONException
{
JSONObject
logData
=
null
;
JSONObject
logData
=
null
;
JSONArray
flight_logging_items
=
null
;
JSONArray
flight_logging_items
=
null
;
JSONArray
flight_logging_keys
=
null
;
JSONArray
flight_logging_keys
=
null
;
...
@@ -103,7 +133,7 @@ public class UasLogReader {
...
@@ -103,7 +133,7 @@ public class UasLogReader {
System
.
err
.
println
(
"Error reading file: "
+
e
.
getMessage
());
System
.
err
.
println
(
"Error reading file: "
+
e
.
getMessage
());
}
}
if
(
log_indices
==
null
)
{
if
(
log_indices
==
null
)
{
return
;
throw
new
IllegalArgumentException
(
"Failed to parse UAS JSON log: "
+
filePath
)
;
}
}
for
(
int
i
=
0
;
i
<
flight_logging_keys
.
length
();
i
++)
{
for
(
int
i
=
0
;
i
<
flight_logging_keys
.
length
();
i
++)
{
...
@@ -111,7 +141,12 @@ public class UasLogReader {
...
@@ -111,7 +141,12 @@ public class UasLogReader {
}
}
int
[]
indices
=
new
int
[
UasLogRecord
.
FIELDS_USED
.
length
];
int
[]
indices
=
new
int
[
UasLogRecord
.
FIELDS_USED
.
length
];
for
(
int
i
=
0
;
i
<
UasLogRecord
.
FIELDS_USED
.
length
;
i
++)
{
for
(
int
i
=
0
;
i
<
UasLogRecord
.
FIELDS_USED
.
length
;
i
++)
{
indices
[
i
]
=
log_indices
.
get
(
UasLogRecord
.
FIELDS_USED
[
i
]);
Integer
idx
=
log_indices
.
get
(
UasLogRecord
.
FIELDS_USED
[
i
]);
if
(
idx
==
null
)
{
throw
new
IllegalArgumentException
(
"Missing field \""
+
UasLogRecord
.
FIELDS_USED
[
i
]
+
"\" in UAS JSON log "
+
filePath
);
}
indices
[
i
]
=
idx
;
}
}
ArrayList
<
UasLogRecord
>
uas_log_list
=
new
ArrayList
<
UasLogRecord
>();
ArrayList
<
UasLogRecord
>
uas_log_list
=
new
ArrayList
<
UasLogRecord
>();
double
[]
rec
=
new
double
[
indices
.
length
];
double
[]
rec
=
new
double
[
indices
.
length
];
...
@@ -135,8 +170,7 @@ public class UasLogReader {
...
@@ -135,8 +170,7 @@ public class UasLogReader {
uas_log_list
);
// ArrayList<UasLogRecord> rec_list)
uas_log_list
);
// ArrayList<UasLogRecord> rec_list)
UasLogRecord
.
fillUndefined
(
rec_arr
);
UasLogRecord
.
fillUndefined
(
rec_arr
);
System
.
out
.
println
(
rec_arr
.
length
+
" items"
);
System
.
out
.
println
(
"UasLogReader: loaded JSON log "
+
filePath
+
", records="
+
rec_arr
.
length
);
return
;
}
}
public
UasLogRecord
interpolate
(
double
timestamp
)
{
// relative
public
UasLogRecord
interpolate
(
double
timestamp
)
{
// relative
...
...
src/main/java/com/elphel/imagej/ims/UasLogRecord.java
View file @
3dbc0525
...
@@ -136,11 +136,16 @@ public class UasLogRecord {
...
@@ -136,11 +136,16 @@ public class UasLogRecord {
double
ts1
=
rec_arr
[
last
].
timestamp
;
double
ts1
=
rec_arr
[
last
].
timestamp
;
if
(
timestamp
<=
ts0
)
{
if
(
timestamp
<=
ts0
)
{
return
rec_arr
[
0
];
return
rec_arr
[
0
];
}
else
if
(
timestamp
>=
last
)
{
}
else
if
(
timestamp
>=
ts1
)
{
return
rec_arr
[
last
];
return
rec_arr
[
last
];
}
else
{
}
else
{
// assuming timestamps are uniform, but not requiring that
// assuming timestamps are uniform, but not requiring that
int
indx
=
(
int
)
Math
.
round
((
timestamp
-
ts0
)/(
ts1
-
ts0
));
int
indx
=
(
int
)
Math
.
round
(
last
*
(
timestamp
-
ts0
)/(
ts1
-
ts0
));
if
(
indx
<
0
)
{
indx
=
0
;
}
else
if
(
indx
>
(
last
-
1
))
{
indx
=
last
-
1
;
}
while
((
indx
<
(
last
-
1
))
&&
(
rec_arr
[
indx
+
1
].
timestamp
<
timestamp
))
indx
++;
// next record timestamp > requested
while
((
indx
<
(
last
-
1
))
&&
(
rec_arr
[
indx
+
1
].
timestamp
<
timestamp
))
indx
++;
// next record timestamp > requested
while
((
indx
>=
0
)
&&
(
rec_arr
[
indx
].
timestamp
>
timestamp
))
indx
--;
// this record timestamp <= requested
while
((
indx
>=
0
)
&&
(
rec_arr
[
indx
].
timestamp
>
timestamp
))
indx
--;
// this record timestamp <= requested
double
k
=
(
timestamp
-
rec_arr
[
indx
].
timestamp
)
/
(
rec_arr
[
indx
+
1
].
timestamp
-
rec_arr
[
indx
].
timestamp
);
double
k
=
(
timestamp
-
rec_arr
[
indx
].
timestamp
)
/
(
rec_arr
[
indx
+
1
].
timestamp
-
rec_arr
[
indx
].
timestamp
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment