I've been searching the web trying to find a way to calculate bearing without using the ATAN2 function. I found the this code but I can't make it work. I trying to validate the equation before I use it in my PLC program but the numbers are not coming up correctly. Any help is appreciated.
y = sin(lon2-lon1)*cos(lat2)
x = cos(lat1)*sin(lat2)-sin(lat1)*cos(lat2)*cos(lon2-lon1)
if y > 0 then
if x > 0 then tc1 = arctan(y/x)
if x < 0 then tc1 = 180 - arctan(-y/x)
if x = 0 then tc1 = 90
if y < 0 then
if x > 0 then tc1 = -arctan(-y/x)
if x < 0 then tc1 = arctan(y/x)-180
if x = 0 then tc1 = 270
if y = 0 then
if x > 0 then tc1 = 0
if x < 0 then tc1 = 180
if x = 0 then [the 2 points are the same]
Gene
Your equation is fine.
Here is a working implementation on bash.
# /bin/bash
DEG_PER_RAD=$(echo "scale=10; 180 / 3.141592653589" | bc)
function atan2 {
if [ $(echo "scale=10; $1 > 0" | bc -l) -eq 1 ]
then
if [ $(echo "scale=10; $2 > 0" | bc -l) -eq 1 ]
then
a2=$(echo "scale=10; a($1 / $2)" | bc -l)
fi
if [ $(echo "scale=10; $2 < 0" | bc -l) -eq 1 ]
then
a2=$(echo "scale=10; 3.141592653589 - a(-1 * $1 / $2)" | bc -l)
fi
if [ $(echo "scale=10; $2 == 0" | bc -l) -eq 1 ]
then
a2=$(echo "scale=10; 3.141592653589 / 2" | bc -l)
fi
fi
if [ $(echo "scale=10; $1 < 0" | bc -l) -eq 1 ]
then
if [ $(echo "scale=10; $2 > 0" | bc -l) -eq 1 ]
then
a2=$(echo "scale=10; -1 * a(-1 * $1 / $2)" | bc -l)
fi
if [ $(echo "scale=10; $2 < 0" | bc -l) -eq 1 ]
then
a2=$(echo "scale=10; a($1 / $2) - 3.141592653589" | bc -l)
fi
if [ $(echo "scale=10; $2 == 0" | bc -l) -eq 1 ]
then
a2=$(echo "scale=10; 3 * 3.141592653589 / 2" | bc -l)
fi
fi
if [ $(echo "scale=10; $1 == 0" | bc -l) -eq 1 ]
then
if [ $(echo "scale=10; $2 > 0" | bc -l) -eq 1 ]
then
a2=0
fi
if [ $(echo "scale=10; $2 < 0" | bc -l) -eq 1 ]
then
a2=$(echo "scale=10; 3.141592653589" | bc -l)
fi
if [ $(echo "scale=10; $2 == 0" | bc -l) -eq 1 ]
then
a2=0
fi
fi
}
function get_bearing {
rad_lat1=$(echo "scale=9; ("$1" / $DEG_PER_RAD)" | bc)
rad_lon1=$(echo "scale=9; ("$2" / $DEG_PER_RAD)" | bc)
rad_lat2=$(echo "scale=9; ("$3" / $DEG_PER_RAD)" | bc)
rad_lon2=$(echo "scale=9; ("$4" / $DEG_PER_RAD)" | bc)
dLon=$(echo "scale=10; $rad_lon2 - $rad_lon1" | bc -l)
y=$(echo "scale=10; s($dLon) * c($rad_lat2)" | bc -l)
x=$(echo "scale=10; (c($rad_lat1) * s($rad_lat2)) - (s($rad_lat1) * c($rad_lat2) * c($dLon))" | bc -l)
atan2 $y $x
bearing=$(echo "scale=10; $DEG_PER_RAD * $a2" | bc -l)
}
get_bearing 49.624196795 6.1256280094 49.6241653669 6.1242621755
echo "Bearing is "$bearing
Regarding PLC I have no experiance so I can't help you. Sorry
Related
I am writing a script that will loop through columns to find an instance of a word.
I decided I do it through nested loops and after executing my code, I get this error:
./gallupscript.sh: line 115: syntax error near unexpected token done'
./gallupscript.sh: line 115:done'
Here is the area where my code fails:
token=2 #token is the column number
starter=0
s1="First" ; s2="Second" ; s3="Third" ; s4="Fourth" ; s5="Fifth"
s=s ; a=1
while [ $token -le 6 ]
do
cat gallup.csv | cut -d',' -f"$token" | grep -n $strength1 | cut -d':' -f1 > str1
if [ -s str1 ]
then
for i in $(cat str1)
do
if [[ $i -ne $number && $starter -eq 0 ]]
then
save=$(cat gallup.csv | head -$i | tail +$i | cut -d',' -f1)
s=s ; s+=$a ; starter=1
printf "-- $strength1 --"
printf "${!s} Strength: $save"
elif [[ $i -ne $number && $starter -ne 0 ]]
then
save=$(cat gallup.csv | head -$i | tail +$i | cut -d',' -f1)
printf ", $save"
fi
done
starter=0
a=$((a+1))
token=$((token+1))
echo #new line
done
This code is expected to output the names (in first columns) where the word is matched with the one I am searching for.
You are not closing your if statement, it doesn't have to do with for.
Use the following code instead:
token=2 #token is the column number
starter=0
s1="First" ; s2="Second" ; s3="Third" ; s4="Fourth" ; s5="Fifth"
s=s ; a=1
while [ $token -le 6 ]
do
cat gallup.csv | cut -d',' -f"$token" | grep -n $strength1 | cut -d':' -f1 > str1
if [ -s str1 ]
then
for i in $(cat str1)
do
if [[ $i -ne $number && $starter -eq 0 ]]
then
save=$(cat gallup.csv | head -$i | tail +$i | cut -d',' -f1)
s=s ; s+=$a ; starter=1
printf "-- $strength1 --"
printf "${!s} Strength: $save"
elif [[ $i -ne $number && $starter -ne 0 ]]
then
save=$(cat gallup.csv | head -$i | tail +$i | cut -d',' -f1)
printf ", $save"
fi
done
fi # <------------ add this line
starter=0
a=$((a+1))
token=$((token+1))
echo #new line
done
i input command in the bash shell:
#!/bin/bash
[[ a>2 ]];echo $?
I get 0
and another command:
#!/bin/bash
[[ 3>2 ]];echo $?
I get
bash: unexpected token 283 in conditional command
bash: syntax error near `3>'
Why I get the err ?
How do I use > < in the [[ ]] ?
I am more curious, in [[]] how to use > < . [[ a>2 ]];echo $? do not add spaces, but [[ 3 > 2 ]] must be added space, more curious about the reasons
thank you!
As the man page for bash builtins states: "Each operator and operand
must be a separate argument."
Also your variable a should be $a
Here is example :
# Returns true
$ a=10; [[ "$a" -gt 1 ]]; echo "$?"
0
# Returns false
$ a=10; [[ "$a" -gt 12 ]]; echo "$?"
1
Following may help you
Integer comparison operators
| Operator | Description | Example |
|----------|-----------------------------|----------------------------------------------------------|
| -eq | Is Equal To | if [ $1 -eq 200 ] |
| -ne | Is Not Equal To | if [ $1 -ne 1 ] |
| -gt | Is Greater Than | if [ $1 -gt 15 ] |
| -ge | Is Greater Than Or Equal To | if [ $1 -ge 10 ] |
| -lt | Is Less Than | if [ $1 -lt 5 ] |
| -le | Is Less Than Or Equal To | if [ $1 -le 0 ] |
| == | Is Equal To | if (( $1 == $2 )) [Note: Used within double parentheses] |
| != | Is Not Equal To | if (( $1 != $2 )) |
| < | Is Less Than | if (( $1 < $2 )) |
| <= | Is Less Than Or Equal To | if (( $1 <= $2 )) |
| > | Is Greater Than | if (( $1 > $2 )) |
| >= | Is Greater Than Or Equal To | if (( $1 >= $2 )) |
String comparison operators
| Operator | Description | Example |
|----------|------------------------------------|-----------------|
| = or == | Is Equal To | if [ $1 == $2 ] |
| != | Is Not Equal To | if [ $1 != $2 ] |
| > | Is Greater Than (ASCII comparison) | if [ $1 > $2 ] |
| >= | Is Greater Than Or Equal To | if [ $1 >= $2 ] |
| < | Is Less Than | if [ $1 < $2 ] |
| <= | Is Less Than Or Equal To | if [ $1 <= $2 ] |
| -n | Is Not Null | if [ -n $1 ] |
| -z | Is Null (Zero Length String) | if [ -z $1 ] |
I have function
function contain() {
if [[ $(echo "$1" | grep "$2" | wc -c) -gt 0 ]]; then
return 0
else
return 1
fi
}
when I write instead
if [[ $(md5sum -c tool | grep -v "OK$" | wc -c) -gt 0 ]]; then
this
if contain "$(md5sum -c tool)" "OK$"
wants not work
read n
i=0
sum=0
while [ $i -lt $n ]
do
read X
sum=`expr $X + $sum `
i=`expr $i + 1 `
done
echo "scale = 3; $sum/$n" | bc -l
--my above code is rounding upto a lesser value, where i want the greater one
e.g. if the ans is 4696.9466 it is rounding up to 4696.946 whereas 4696.947 is what i want. So , suggest any edits
You may pipe your bc to printf :
echo "scale = 4; $sum/$n" | bc -l | xargs printf '%.*f\n' 3
From you example :
$ echo "scale = 4; 4696.9466" | bc -l | xargs printf '%.*f\n' 3
4696,947
Change last line of your script from echo "scale = 3; $sum/$n" | bc -l to
printf %.3f $(echo "$sum/$n" | bc -l)
printf will round it off correctly. For example,
$ sum=1345
$ n=7
$ echo "$sum/$n" | bc -l
192.14285714285714285714
$ printf %.3f $(echo "$sum/$n" | bc -l)
192.143
I'm sure someone has already solved this problem: what is an easy and portable way to convert a hex color value (anything from 000000 to FFFFFF) to 3 decimal values from 0 to 255. (If you're not familiar with how colors are traditionally represented in HTML, the first two hex digits are the first decimal number, and so forth.)
$ cat hexrgb.sh
#!/bin/bash
hex="11001A"
printf "%d %d %d\n" 0x${hex:0:2} 0x${hex:2:2} 0x${hex:4:2}
$ ./hexrgb.sh
17 0 26
If you are not willing to use bash for substring expansion, I'd still use printf for the conversion.
You can use a script like:
#!/bin/sh
# hextorgb.sh
hexinput=`echo $1 | tr '[:lower:]' '[:upper:]'` # uppercase-ing
a=`echo $hexinput | cut -c-2`
b=`echo $hexinput | cut -c3-4`
c=`echo $hexinput | cut -c5-6`
r=`echo "ibase=16; $a" | bc`
g=`echo "ibase=16; $b" | bc`
b=`echo "ibase=16; $c" | bc`
echo $r $g $b
exit 0
and use it like:
./hextorgb.sh "11001A"
resulting in output like:
17 0 26
It can be improved by testing for arguments and so on, but it does what you want.
#!/usr/bin/env bash
hex2rgb() {
hex=$(echo "${1^^}" | sed 's/#//g')
a=$(echo $hex | cut -c-2)
b=$(echo $hex | cut -c3-4)
c=$(echo $hex | cut -c5-6)
r=$(echo "ibase=16; $a" | bc)
g=$(echo "ibase=16; $b" | bc)
b=$(echo "ibase=16; $c" | bc)
echo ${1^^}
echo $r $g $b
}
hex2rgb "#FF0000"
hex2rgb "#00FF00"
hex2rgb "#0000FF"
I know this question is quite old but to add an anecdote;
alternatively, if you wanted to convert rgb to hex you could do a little something like:
#!/bin/sh
# rgbtohex.sh
f="$1,"
focus=0
start=0
until [ "$limit" == "3" ]
do
focus=$((focus+1))
if [ "${f:$focus:1}" == "," ]
then
limit=$((limit+1))
length=$(($focus-$start))
let c$limit="${f:start:length}"
start=$((focus+1))
fi
done
r=`echo "obase=16; $c1" | bc`
r2=`echo "obase=16; $c2" | bc`
r3=`echo "obase=16; $c3" | bc`
if [ "${r:1:2}" == "" ]
then r=0$r
fi
if [ "${r2:1:2}" == "" ]
then r2=0$r2
fi
if [ "${r3:1:2}" == "" ]
then r3=0$r3
fi
echo $r$r2$r3