Skip to content

merge v3.0.0 #2

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 18 commits into from
Apr 4, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion hypernets/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
__version__ = "2.3.0"
__version__ = "3.0.0"

import sys
MIN_PYTHON = (3, 9)
Expand Down
15 changes: 11 additions & 4 deletions hypernets/geometry/pan_tilt.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ def print_position(ser):
print("Failed to read current position from pan-tilt!")


def move_to(ser, pan=None, tilt=None, wait=False):
def move_to(ser, pan=None, tilt=None, wait=False, tilt_limiter=True):

if ser is None:
ser = open_serial()
Expand Down Expand Up @@ -178,6 +178,10 @@ def move_to(ser, pan=None, tilt=None, wait=False):

info(f"Requested Position :\t({pan}, {tilt})\t(10^-2 degrees)")

# Tilt no-go-zone: abs_deg (130.0, 181.0); abs_tilt (13000, 18100)
if tilt_limiter is True and tilt is not None and tilt > 13000 and tilt < 18010:
raise Exception(f"Requested absolute tilt position {tilt/100:.2f} is in no-go zone (130.0, 181.0) !!")

if wait:
initial_position = query_position(ser)
estimated_time = pt_time_estimation(initial_position, (pan, tilt))
Expand Down Expand Up @@ -259,8 +263,8 @@ def move_to(ser, pan=None, tilt=None, wait=False):
return position_1


def move_to_geometry(geometry, wait=False):
return move_to(None, geometry.pan_abs, geometry.tilt_abs, wait=wait)
def move_to_geometry(geometry, wait=False, tilt_limiter=True):
return move_to(None, geometry.pan_abs, geometry.tilt_abs, wait=wait, tilt_limiter=True)


def open_serial():
Expand Down Expand Up @@ -343,6 +347,9 @@ def restricted_float(x):
if args.get:
print_position(ser)
else:
print(move_to(ser, args.pan, args.tilt, wait=args.wait))
try:
print(move_to(ser, args.pan, args.tilt, wait=args.wait))
except Exception as e:
error(f"{e}")

ser.close()
2 changes: 1 addition & 1 deletion hypernets/gui/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ def configure_gui(self):
# self.resizable(0, 0)

def create_logo(self):
logo_hypernets = resources.read_binary(img, "logo.png")
logo_hypernets = resources.files(img).joinpath("logo.png").read_bytes()
self.img_hyp = PhotoImage(data=logo_hypernets)
logo_lbl = Label(self, image=self.img_hyp)
logo_lbl.grid(column=0, row=0, columnspan=2)
Expand Down
7 changes: 6 additions & 1 deletion hypernets/gui/frame_pantilt.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
from tkinter import Tk, Button
from tkinter.ttk import Combobox

from logging import error

from hypernets.abstract.geometry import Geometry
from hypernets.geometry.pan_tilt import move_to_geometry

Expand Down Expand Up @@ -56,7 +58,10 @@ def callback(self):

geometry = Geometry(pan=pan, tilt=tilt, reference=reference)
geometry.get_absolute_pan_tilt()
move_to_geometry(geometry)
try:
move_to_geometry(geometry)
except Exception as e:
error(f"{e}")


if __name__ == '__main__':
Expand Down
2 changes: 1 addition & 1 deletion hypernets/hypstar/libhypstar
40 changes: 38 additions & 2 deletions hypernets/open_sequence.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@


yoctoWDTflag = threading.Event()
tilt_limiter = True

class yoctoWathdogTimeout(Exception):
pass
Expand All @@ -41,6 +42,33 @@ def run_sequence_file(sequence_file, instrument_port, instrument_br, # noqa C901
DATA_DIR="DATA",
check_rain=False):

## check tilt limiter
## if key is missing, defaults False
## if key exists and is not "no", defaults True
##
## use global variable because we need to access it in park_to_nadir()
global tilt_limiter

if instrument_standalone:
tilt_limiter = False
debug("Standalone mode, tilt_limiter = no")
else:
try:
from configparser import ConfigParser
config = ConfigParser()
config.read("config_static.ini")
config_value = config["pantilt"]["tilt_limiter"]
if config_value == "no":
tilt_limiter = False
debug("tilt_limiter = no in config_static.ini")
else:
tilt_limiter = True
debug("tilt_limiter = yes because not explicitly disabled in config_static.ini")
except KeyError as key:
tilt_limiter = False
debug("pantilt/tilt_limiter not found in config_static.ini, defaults to tilt_limiter = no")


# Check if it is raining
if not instrument_standalone and check_rain:
try:
Expand Down Expand Up @@ -280,7 +308,7 @@ def run_sequence_file(sequence_file, instrument_port, instrument_br, # noqa C901
yoctoWDTwatcher.join()

try:
pan_real, tilt_real = move_to_geometry(geometry, wait=True)
pan_real, tilt_real = move_to_geometry(geometry, wait=True, tilt_limiter=tilt_limiter)
pan_real = float(pan_real) / 100
tilt_real = float(tilt_real) / 100

Expand All @@ -303,6 +331,11 @@ def run_sequence_file(sequence_file, instrument_port, instrument_br, # noqa C901
warning(f"Failed to read the final position from pan-tilt")
pan_real, tilt_real = -999, -999

except Exception as e:
error(f"{e}")
# Don't retry if this was the first attempt
i = 1

logger.setLevel(old_loglevel)

for request in requests:
Expand Down Expand Up @@ -442,11 +475,14 @@ def park_to_nadir():
import serial
while True:
try:
move_to(ser=None, tilt=park.tilt_abs, wait=True)
move_to(ser=None, tilt=park.tilt_abs, wait=True, tilt_limiter=tilt_limiter)
break
except serial.serialutil.SerialException:
debug("Previous pan-tilt move in progress. Waiting...")
sleep(1)
except Exception as e:
error(f"{e}")
break


def relay3_delayed_on():
Expand Down
1 change: 0 additions & 1 deletion hypernets/rain_sensor/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
from logging import basicConfig, getLogger, info, error # noqa
from time import sleep
from .rain_sensor import RainSensor
import gpiod


if __name__ == '__main__':
Expand Down
42 changes: 32 additions & 10 deletions hypernets/resources/config_dynamic.ini.template
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
##########################################################################
[general]

# keep_pc - control the system status after the end of the automated sequence
Expand All @@ -18,35 +19,50 @@ start_sequence = no
# Allowed values: yes/no - do/don't check the Yocto wakeup reason
#
# If the wakeup reason check is enabled, the sequence is chosen as follows:
# SCHEDULE1 - run default sequence (sequence_file)
# SCHEDULE2 - run alternative sequence (sequence_file_alt)
# SCHEDULE1 - run default sequence (sequence_file or sequence_file_sched1)
# SCHEDULE2 - run LED measurement sequence (sequence_file_alt or sequence_file_sched2)
# SCHEDULE3 - run custom sequence (sequence_file_sched3
# available only on host units V4 and newer)
# Any other wakeup reason - don't start the sequence
#
# If Yocto deep sleep mode is disabled, then both wakeup schedules report the
# wakeup reason as SCHEDULE2 and the alternative sequence is started. This is
# caused by a bug in the Yocto firmware.
# If Yocto deep sleep mode is disabled, then all wakeup schedules report the
# wakeup reason as SCHEDULE2 and the sequence defined by sequence_file_alt or
# sequence_file_sched2 is started. This is caused by a bug in the Yocto firmware.
check_wakeup_reason = yes

# sequence_file - the default sequence that is executed
# sequence_file_sched1 - the default sequence that is executed
# For backwards compatibility sequence_file is also accepted as the parameter name
#
# runseq shortcut always executes the default sequence
# Yocto Schedule1 always executes the default sequence
# Yocto Schedule2 executes the default sequence if check_wakeup_reason = no
# Yocto Schedule3 executes the default sequence if check_wakeup_reason = no
#
# If any modifications are made to the sample sequence file it is strongly
# recommended to edit a copy instead of the original sample file in order to
# avoid git conflicts in the future.
sequence_file = hypernets/resources/sequences_samples/your_sequence.txt
sequence_file_sched1 = hypernets/resources/sequences_samples/your_sequence.txt

# sequence_file_alt - the alternative sequence that is executed
# sequence_file_sched2 - the alternative sequence that is executed, typically LED source measurement
# For backwards compatibility sequence_file_alt is also accepted as the parameter name
#
# Yocto Schedule1 executes the alternative sequence if Yocto deep sleep mode is disabled
# Yocto Schedule2 executes the alternative sequence if check_wakeup_reason = yes
# Yocto Schedule3 executes the alternative sequence if Yocto deep sleep mode is disabled
#
# If any modifications are made to the sample sequence file it is strongly
# recommended to edit a copy instead of the original sample file in order to
# avoid git conflicts in the future.
sequence_file_alt = hypernets/resources/sequences_samples/your_validation_sequence.txt
sequence_file_sched2 = hypernets/resources/sequences_samples/your_validation_sequence.txt

# sequence_file_sched3 - another alternative sequence, e.g site-specific custom acquisition
# Yocto Schedule3 is available on host units V4 and newer with Yocto-Pictor-GPS boards
#
# Yocto Schedule3 executes the sequence_file_sched3 sequence if check_wakeup_reason = yes
#
# If any modifications are made to the sample sequence file it is strongly
# recommended to edit a copy instead of the original sample file in order to
# avoid git conflicts in the future.
sequence_file_sched3 = hypernets/resources/sequences_samples/your_custom_sequence.txt

# check_rain - check the rain sensor and skip or abort the sequence if rain is detected
# Allowed values: yes/no
Expand All @@ -71,6 +87,7 @@ auto_update = no
verbosity = INFO


##########################################################################
[GPS]
# The geographic coordinates of the system which are used for calculating the Sun angles
# and copied to the metadata.txt of each sequence
Expand All @@ -89,6 +106,7 @@ latitude = 0.0
longitude = 0.0


##########################################################################
[SPA]
# elevation - elevation of the HYPSTAR in meters from WGS-84 ellipsoid used for
# calculating the Sun angles
Expand All @@ -99,6 +117,7 @@ longitude = 0.0
elevation = 0


##########################################################################
[pantilt]
# offset_pan - the offset from geographic north in degrees when HYPSTAR is pointing
# at pan(abs) = 0, tilt(hyper) = 90
Expand Down Expand Up @@ -131,6 +150,7 @@ pantilt_port = /dev/ttyS0
azimuth_switch = 0


##########################################################################
[hypstar]
# pantilt_port - link to the radiometer serial port device file
#
Expand Down Expand Up @@ -167,10 +187,12 @@ loglevel = INFO
swir_tec = 0


##########################################################################
[metadata]
# The fields in the [metadata] section are directly copied into metadata.txt of each sequence.
# In addition, the following fields are automatically populated in metadata.txt:
# datetime, hypstar_sn, led_sn, latitude, longitude, protocol_file_name, offset_pan,
# offset_tilt, azimuth_switch
principal_investigator = Investigator Name
site_id = A Site ID

36 changes: 33 additions & 3 deletions hypernets/resources/config_static.ini.template
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
#########################################################################
[yoctopuce]
# HYPSTAR host systems V1-V3 use Yocto-Pictor-Wifi and need
# yocto_prefix1, yocto_prefix2, and yocto_gps parameters
#
# HYPSTAR host systems from V4 onward use Yocto-Pictor-GPS and need
# yocto_prefix1 and yocto_prefix3 parameters

# yocto_prefix1 - Yocto-Pictor (relay board) serial number
yocto_prefix1 = OBSVLFR1-XXXXXX

# yocto_prefix2 - Yocto-Pictor-Wifi (upper board) serial number
# yocto_prefix2 - Yocto-Pictor-Wifi (upper board up to V3) serial number
yocto_prefix2 = OBSVLFR2-XXXXXX

# yocto_gps - Yocto-GPS-V2 (gps board) serial number
# yocto_prefix3 - Yocto-Pictor-GPS (upper board from V4 onward) serial number
yocto_prefix3 = OBSVLFR3-XXXXXX

# yocto_gps - Yocto-GPS-V2 (gps board up to V3) serial number
yocto_gps = YGNSSMK2-XXXXXX

# bypass_yocto - disable all Yocto functionality
Expand All @@ -19,6 +29,7 @@ bypass_yocto = no
debug_yocto = no


#########################################################################
[network]
# credentials - the ssh credentials of the network server
credentials = user@server
Expand All @@ -38,7 +49,7 @@ ssh_port = 22
#
# remote ssh port must be unused on the network server and unique for each site
# connected to the same server
remote_ssh_port = 20213
remote_ssh_port = unique_for_each_site

# ssh_loglevel - the verbosity of the reverse ssh tunnel client
# Allowed values: ERROR, DEBUG, DEBUG2, DEBUG3
Expand All @@ -63,14 +74,33 @@ backup_ssh_ip = 10.42.0.1
dhcp_server = yes


#########################################################################
[webcam]
# For disabling either webcam and suppressing warnings about inaccessible or invalid IP
# comment out the respective webcam_... parameter
#
# ip_cam_... must be an IPv4 address
#
# Note that for PoE cameras the first address of the camera subnet (i.e. X.Y.Z.1) is reserved
# for rugged PC enp2s0 interface (eth port 2)

# webcam_site - site webcam (relay 5) credentials
webcam_site = user:pass@ip_cam_site

# webcam_sky - sky webcam (relay 6) credentials
webcam_sky = user:pass@ip_cam_sky

# Both PoE cameras are powered by relay 5 so relay switching logic is different for PoE cameras
# Allowed values: yes/no
poe_cameras = no


#########################################################################
[pantilt]
# If the mechanical tilt axis limiter is installed, tilt movement commands into
# (130.0, 181.0) absolute position no-go zone are rejected.
#
# NB!! The tilt axis gearbox can be damaged when driven into the limiter at full speed!
#
# Allowed values: yes/no
tilt_limiter = no
3 changes: 2 additions & 1 deletion hypernets/yocto/get_FW_ver.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ def get_module_FW_ver(url_base):
for url_base in [get_url_base(), get_url_base_prefixed(), get_url_gps()]:
values.append((get_module_FW_ver(url_base)))

return values
# return only unique values
return list(set(values))

if __name__ == "__main__":
out="Yocto firmware versions: "
Expand Down
Loading