Acu add sin el nod#1072
Conversation
|
Thanks Michael. I recommend that you move this to "draft" PR until we finalize design and test it on a real system. Initial reactions:
|
|
Aaaah I didn't even know there was a draft PR feature... that's super helpful! (I am not great at git... lol). Changed.
I think rewriting the driver to yield whole number of nods and then rewriting the agent process will be good. One of the worries I had with the current implementation into |
|
Alright I reverted |
| self._simple_process_stop, | ||
| blocking=False, | ||
| startup=False) | ||
| agent.register_process('generate_sin_el_nod', |
There was a problem hiding this comment.
Let's just call this "generate_elnod". If we invent alternatives, we'll likely jam them into this function.
There was a problem hiding this comment.
Done. Now just called generate_el_nod in the agent. I kept the generate_sin_el_nod in the driver
| @ocs_agent.param('az', type=float) | ||
| @ocs_agent.param('el_endpoint1', type=float, default=None) | ||
| @ocs_agent.param('el_endpoint2', type=float, default=None) |
There was a problem hiding this comment.
Instead of having these as args, let's just make this function run them at the current position. This makes for less bookkeeping in sorunlib. And then you'd just have "el_depth", which could be negative, as the parameter that determines how far apart the endpoints are.
There was a problem hiding this comment.
Done, changed to el_freq and el_depth as callable parameters
| 'el1': el_endpoint1, | ||
| 'el2': el_endpoint2, | ||
| 'el_freq': el_freq, | ||
| 'type': 'sin_el_nod', |
There was a problem hiding this comment.
The data here need to be exactly the same (same fields with same data types) as the ones in generate_scan. Otherwise the feed will complain (or, at best, data loading of this info will be totally messed up). I think you should indeed use 4 for the sin_el_nod -- and register it in the main list of scan types. Any irrelevant stuff should be set to 0 or nan or something like that.
There was a problem hiding this comment.
Copied the format from generate_scan and filled it with the available data.
Do you mean register scan_type 4 in the agent? Like in an enum? or is there another place to register the scan_type?
| if not self._get_sun_policy('map_valid'): | ||
| return False, 'Sun Safety Map not computed or stale; run the monitor_sun process.' | ||
|
|
||
| n = max(2, int(np.ceil((el2 - el1) / 1.))) |
There was a problem hiding this comment.
humor me and throw an "abs" in front of that (el2 - el1) ...
| MIN_STEP_TIME = 0.05 # in seconds. | ||
|
|
||
| # Get el throw | ||
| el_throw = abs(el_endpoint2 - el_endpoint1) / 2 |
There was a problem hiding this comment.
I think we want to allow downward nods; so remove the abs().
| raise ValueError("El Freq is too high! El Freq must be < 1.25Hz to keep " | ||
| "step_time > 0.05!") | ||
|
|
||
| step_time = POINTS_PER_NOD * el_freq # Divide nod into 16 points |
There was a problem hiding this comment.
Ya I don't think we should force step_time like this. Rather, respect what the user asked for but:
- round it, so it evenly divides the nod period.
- make sure there are at least 16 points per period.
That's what I described in previous comment. We'll likely need to experiment with this a little to see what step_times work well.
There was a problem hiding this comment.
Reworked the step_time in this function. It'll now take the step_time and find the closest step_time that divides the number of points per nod into the closest multiple of four (so that we get clean looking, regular sinewaves).
| timestamp=t + t0, | ||
| az=az, el=el, az_vel=0, el_vel=el_vel, | ||
| az_flag=0, el_flag=1, | ||
| group_flag=0)) |
There was a problem hiding this comment.
set group_flag=1 except for the final point in each cycle -- that is what will actually force only complete cycles to be uploaded.
| az_flag=0, el_flag=1, | ||
| group_flag=0)) | ||
|
|
||
| t += step_time |
There was a problem hiding this comment.
Consider restructuring the loop like this:
# Templates for one cycle
template_t = step_time * np.arange(points_per_nod)
template_el, template_el_vel = get_el(template_t) # vectors
while not done():
point_block = [PointBlock(timestamp=t0 + t, ..., group_flag=1)
for (t, el, el_v) in zip(template_t, template_el, template_el_vel)]
point_block[0].group_flag = 0 # Ok to stop on the zero vel starting point!
yield point_block
t0 += 1 / el_freq
# And one last zero-vel point.
yield [PointBlock(timestamp=t0, ... vels=0, group_flag=0)]
This reduces floating point errors, but also just makes it crystal clear that we're doing one cycle at a time, and they're always identical in el shape.
There was a problem hiding this comment.
Reworked the loop to make the cycle more obvious.
c8dee4c to
6db658d
Compare
|
I had to change part of the I also added some comments into the abort checks to make it clear what we're checking for abort mode. |


Added the
gen_sin_el_nodscan generator function into the ACU drivers.Description
Added a new generator function for generating sinusoidal elevation nods into the ACU agent. This generator will allow us to generate sine wave el nods that do not move in azimuth. This is basically a replica of type3 scan behavior with no azimuth movement.
Motivation and Context
LAT ISO review requested sinusoidal elevation nods with no azimuth movement.
How Has This Been Tested?
I've simmed the

gen_sin_el_noddriver function output with success. The generator function should work as intended.I have not yet tested the changes to the agent
generate_scanfunction or tested an movement on the LAT. This needs to be tested before PR approval.Types of changes
Checklist: