-
Notifications
You must be signed in to change notification settings - Fork 23
Enabeling opty to estimate input time shifts. #294
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
base: master
Are you sure you want to change the base?
Conversation
…aints, calculate free node map for timeshift instance constraints (incomplete/needs debugging)
…input trajectory derivatives. Add partials w.r.t timeshifts to instance constraints jacobian values func.
This would be nice if were an issue here, because forks are often temporary or just may disappear at some point. |
I added it to the first message in this PR |
|
I added the new indices of the new timeshift contraint partials to the jacobian indices. This assumes the following layout of the Jacobian. Can you confirm that this is correct, @moorepants? Green is the existing Jacobian, yellow is the extension with timeshift constraints. The constraint definition is as above: Creating a new problem with |
|
@chris-konrad : Curiosity: Once this works will opty be able to handle time delayed eoms, like |
|
@Peter230655: No, unfortunately this will not directly be possible. The implemented approach requires that the timeshifted trajectory is a known trajectory. |
Thanks! |
…ixSymbol; Convert dynamic indices to symbolic free to int.
|
All previously existing unittests now run fine but it seems to break some examples with variable times. This is little surprising as I did not pay any attention to that during implementation. Before addressing these issues, I will focus on testing if the new functions work at all. |
Are you treating |
| self.eom = sym.Matrix(((x_1(t).diff() - x_2(t),), | ||
| (x_2(t).diff() + a_0 * T_0 * x_1(t) | ||
| + a_1 * T_0 * x_2(t) | ||
| - T_0 * u(t-t_d),))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why would u_shift not be added here instead of u(t-t_d)? Shouldn't the eom's not have t_d present?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the eom that I pass to the constructor of Problem. It has t_d present in u(t-t_d). The ConstraintCollocator then looks through this eom, finds all expressions of the form U(time_symbol +/- symbol) and substitutes them with U_shift(time_symbol (see: ConstraintCollocator._substitute_timeshift_trajectories(self))
| self.state_symbols = (x_1, x_2) | ||
| self.constant_symbols = (a_0, a_1) | ||
| self.constant_values = (1, np.sqrt(2)) | ||
| self.timeshift_inputs = {u_shift(t): (u(t - t_d), t_d)} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why did you choose adding a new attribute here, instead of passing u_shift - u(t - t_d) directly to instance constraints?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After substituting the timeshift trajectories, ConstraintCollocator automatically appends instance constraints representing u_shift(t) - u(t - t_d) to the other instance constraints (see: ConstraintCollocator._generate_timeshift_constraints()) , I just didn't write a test for this yet. The attribute ConstraintCollocator.timeshift_trajectory_substitutes, that I check in this test, is just a map from the substitutes to the original trajectory and the timeshift parameter that I occasionally need throughout the code to look up which functions and parameters relate to the timeshift.
Thats what I do. Indeed there seems to be a problem in the Jacobian index function related to this. I will have a look. |
…k of it separately
…argument for jacobian evaluation
…pecified values for the case of single unknown trajectories
opty/direct_collocation.py
Outdated
| time_interval) | ||
|
|
||
| if all_specified.shape[0] == 1: | ||
| all_specified.squeeze() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be safe to call squeeze() without the if statement, as it will only affect arrays with an empty dimension.
…ng the whole time interval plus the bounds of the timeshift parameter
…iolations to show timeshift constraints.
|
I may have found a simple hack to do this: |
|
Yes, this sounds like a useful example to have. |
|
Are you doing |
Yes, this is exactly what I do. So far looks o.k. |
|
I don't think the internals of opty support anything but |
|
Of course only you know this best! I did not use a 'general function'. I did not think that given a bunch of measurements, opty could determine whether the driving for was a sine function or an exponential function, or whatever. |
|
|
|
Feel free to prove me wrong though! |
|
I do not think, you are wrong! :-) Anyway, let me play around a bit more, hopefully I can push it tomorrow, then you will see if useful or not so good. |
Christoph precisely needs an unknown input to have a delay, so |
|
Then I missunderstood, was too easy to be true! 😊😊 |
|
@chris-konrad |

This is work in progress addressing #224. The code currently does not run without exceptions and added functions are untested.
Motivation
For a dynamic system$\dot{x}(t) = f(x(t)) + u(t-\tau)$ , one may want to estimate the unknown input delay $\tau$ . Currently, opty does not support timeshift symbols and hence can't explicitly estimate this delay (See #224).
Method
A potential way to enable opty to find the desired$\tau$ directly is outlined as follows (credits to @moorepants)
Calculating the constrain Jacobian
The timeshift constraints have to be added to the constraint jacobian. For the constraints$c_i$ as defined above, the Jacobian is
for midpoint integration:
$G_i = [\frac{\partial c_i}{\partial u[i]}, \frac{\partial c_i}{\partial \tau}] = [1, \frac{u'[i-\frac{\tau}{\Delta t}+1] - u'[i-\frac{\tau}{\Delta t}-1]}{2\Delta t} \cdot \frac{1}{\Delta t}]$
for backwards euler integration:
$G_i = [\frac{\partial c_i}{\partial u[i]}, \frac{\partial c_i}{\partial \tau}] = [1, \frac{u'[i-\frac{\tau}{\Delta t}] - u'[i-\frac{\tau}{\Delta t}-1]}{\Delta t} \cdot \frac{1}{\Delta t}]$
Status
Development is ongoing in branch input-time-shifts. The current code does not run without exceptions and the added functions are untested.
TODO List
_find_closest_free_index()to create the indices of constraints with timeshift (b52a96f, 1e9a710, 11ab07d)_instance_constraints_func()to handle timeshift constraints. (b52a96f, 1e9a710, 11ab07d)_instance_constraints_jacobian_indices()to handle timeshift constraints (6f79482).jacobian_indices()to find the dynamic indices of timeshift constraintsconstraints_jacobian()needs to be adressed