-
Notifications
You must be signed in to change notification settings - Fork 22
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
Ackermann constraints #42
Comments
Looking into this I see a few options:
Perhaps to some degree my lack of familiarity with xtensor / views, but I'm not exactly sure I'm not seeing how that adds into the last iteration's velocity to get the propogated state velocity from initials that the function Passing by that question, the next thing to ask is where makes the most sense to apply the curvature limitation constraint to the ackermann motion model we'd like to support. Both Path poses are by far the easiest way to find the curvature between points in to threshold, but then "fixing" up the trajectory that violates it would be less straight forward. So I think it would be adventitious to apply this constraint as early as possible. While projecting poses would be fine, but then we'd have to break down the process into a Given that the propagation occurs in tandem with the motion model's I've worked on ackermann path planners in the past so they way I typically think about them is in the limitation of curvature of paths it can generate (e.g. minimum radius circle the car can create, between 3 path points, compute the curvature of a circle that they could make up). However, if we're working in velocity-space, that's not the right way to think about it. The 2 constraints we need are turning rate and curvature that would occur if completing that command at that state. The first is the constraint With that assumption that we're going to be working in body-fix coordinates rather than wheel turning rates / constraints, we should use that also in the motion model constraints we want to have set up. So, the main constraint we need to add for Ackermann is the constraint for curvature. To be continued... ran out of time to come to conclusive thoughts on this. But I think this is a decent starting point -- we know where to do it and have half the context for constraints required and thorough enough for documentation about what On another topic, I feel like the control constraints should actually be members of the motion model, as they're constraints to the motion of the vehicle. I'd like your opinion on that from an engineering standpoint if that would be sensible for us to abstract out into the motion model class or not. |
Back on this ackermann constraint thing So we have linear body-fixed frame velocities and angular velocities. Perhaps I'm overthinking this, but if we think about it in body-fixed angles, when we're driving "forward" whereas forward is not straight, there is a component of both X and Y velocity. So the single-valued velocity would need to be the velocity of the wheels? There's the classical kinematics formula Rather than trying to think of some infinitesimally small slice of a circle made up of a single timestep's linear and angular velocity and trying to use some fancy math to find its curvature -- what if I zoom out and allow those velocities to be forward simulated such that they create a perfect circle (assuming v and w are constant). In that situation, then our rotation rate defines the time it takes to complete a circle. Knowing there are 2PI radians, the time to complete a circle is Perhaps unsurprisingly to those reading this at home, the reduction is So this is EZ-PZ to find the curvature to know if we have exceeded the minimum turning radius to threshold via. The open question now is that we can find I would think we should reduce angular velocity, but it might be wise to scale linear as well to some degree. |
Coming back on this Monday, I think the answer is to restrict So in summary:
I'm definitely not an xtensor wizard -- @artofnothingness is this something you can add to |
Now predict just returns controls. i.e given time step i, we predict velocity at time_step i+1 as equal to current control (at time step i).
Even though we could do this, i'm not sure that it's the right place. predict must predict velocity, given current velocity, current control. |
I think we must constraint only controls, integrate works with predicted velocities, so if we change something here in controls, we must re-predict whole batch again. |
Yeah, that looks quite easy |
In general, i agree that restrict W make more sense. |
But this is where the motion model is implemented, if we don't do it here for ackermann, we'd have to redesign the motion model API to include another location for this restriction. If e.g. (inefficiently, but illustratively)
I suppose we could do it here instead but then we'd have to introduce a loop over all controls to threshold, which already exists for the I think both options are fine, but the first involves the least change to existing code and wouldn't involve any more looping than already exists. It would though be problematic in the future if we did the second option and more complex dynamic models were added. Then the curvature constraint would again have to be applied within motion model's predict after applying the model. ^^ actually thinking that through, if we ever wanted to support more complex dynamic models, it must be done in predict, not on generation, to account for other irregularities in previous timesteps. I revise my view, I think it should definitely be in predict, or else it could cause subtle bugs later for more complex dynamic models and it doesn't really matter to us at all for the trivial case that we set |
Let's make it simpler
We have "Model" that predicts velocities, given initial vels and controls over time window. It could be simple Naive model (predicted velocities = controls) or neural network model in future. If we know that using given motion model we can't achieve W more than some threshold, then, why not just restrict controls over that threshold (like you propose w_coontrol = sgn_of_w(v_control / Rmin) ) ? |
If later we have a more involved motion model based on a neural network (as opposed to a more 'normal' dynamic model), we don't want the generated controls into the model to be already cut off of curvature. If its already driving on a curvature too small than the kinematic limits of the vehicle because its drifting in a turn, then the neutral network literally couldn't generate a trajectory in the entire state space if previously limited, so much of its actual drivable options would be removed. Remember for the Ackermann model, we're working in body-fixed coordinates as discussed above, not steering angle coordinates. So in order to make sure that this doesn't become an issue in the future, its up to the prediction model to update the control input based on what's possible at that timestep. Right now, our naive model is just passing it through. But if we think about it slightly differently, we can think about it as a kinematics model, where for omni / differential drive robots, anything is technically possible (within velocity and acceleration limits) so passing through is an OK first-order approximation. But for ackermann models, this is where invalid controls should be cut off - because for more complex models in the future, this is also where we would expect them to be cut off too or considered if valid in context with more complex effects the NN is modeling. If we cut them off too early, then future models (if any were to be added) dealing with slippage or high-speed drifting effects could be artificially limited. At least, that's my intuition about it. For what we have right now, I agree, it doesn't really matter. But I think for instance we could make our Or like I think we both talk about above, adding a new API to motion model in addition to |
I'm not sure what you propose instead of cutting off controls right after their random generation Given generated randomly controls
Something like that ? |
Yeah, I imagine that the NN in (1) would do that itself, but (2) for non-NN (or post NN logical checks that output is rational) to deal with model constraints -- which would include curvature. We could do it in apply control constraints if it was going to have significant differences in runtime, but that might introduce some issues if we ever did add NN support |
Oh ok, i see. |
Exactly! We need the real last timestep's solutions to consider this one's in the propagation in case a more complex model starts to do non-naive behavior.
Isn't that the equations I set up in a prior comment?
No, because you would be correcting that timestep, then we get the next timestep which should be based on the last time step's state, and recursively so in the future. Its only a problem if the motion model cannot make those modifications and have it be the initial condition for the next step. |
Oh, i got it
This one? I don't see here changing controls. I see this like only predicted velocities changed I see this idea like that:
Obscure part for me is 3. Imagine an example - one iteration of prediction step: |
I suppose I thought that I think some of what's tripping me up here is that this isn't the way I had thought about this problem, and I'm not sure how what's in code now could be made to work with a dynamics/NN model (e.g. if I can't actually modify velocities/controls in I thought about However, the code has the As a result of this, the input the Then all we're doing in the model for naive is adding them and passing through like we do now (half in I know that was alot, this is something much easier to talk about in front of a white board 😆 So when we're talking about updating controls for ackermann, if we have So analyzing 3 cases:
|
In summary, since this is alot and it would be good to just get everything in 1 place:
For how I think about controls and to combat it
Alternatively
|
Naive model expects that if at time step i we have velocity
generateNoisedControls generates random control sequences from current (from previous time_step) best control sequence.
It's literally what will be passed to the topic i'll back to this thread a little later |
We have Basically at time step 0 we have robot_speed which corresponds to 0 time step For naive model we have I'm explaining how it works now, if we have some misunderstanding at this point |
in |
lets say i = current moment t
This input serves a different purpose as i think.
That's a good point. We need some benchmarking/profiling |
I guess that's not how I think about it from the aerospace perspective, its the role of the motion model to tell you what the outcome I understand how the code is written from that perspective, but I don't think it provides the motion model the proper inputs to be able to apply a NN or dynamics model solution. For example another MPPI implementation using a NN for dynamics: tl;dr: we should be giving the |
Separately, because the random controls are already added to the last-best velocity (https://github.com/artofnothingness/mppic/blob/develop/src/optimizer.cpp#L186-L187), I think (right?) there is a problem if at some timestep I suppose we could make the controls immutable in the predict, but then we'd need a prior processing step to handle motion model limitations (e.g. max acceleration between steps, ackermann curvature constraints) in the apply control constraints section of the code, but that again brings up the bit below:
But perhaps its unavoidable if we want to add acceleration constraints for smoothness anyway. And we maybe do? Though I'm surprised not to see that in another implementation, so maybe there's a reason not to (or they were research focused, not production focused). Because of random independent generation, its possible that kinematic constraints are impractical, due to roll out effects just like So I'm starting to come around to your thinking on where we should put the ackermann constraint on control ( tl;dr: lets add the ackermann constraint to |
In works in PR #59 |
Support maximum curvature contraint on controls so that the system is able to work with ackermann vehicles
The text was updated successfully, but these errors were encountered: