Skip to content

Commit

Permalink
Merge pull request #60 from RoboticExplorationLab/cones
Browse files Browse the repository at this point in the history
Equality Cones
  • Loading branch information
bjack205 authored Mar 2, 2022
2 parents 99816ef + 0f98ce1 commit f556de4
Show file tree
Hide file tree
Showing 26 changed files with 296 additions and 207 deletions.
8 changes: 8 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
# New `v0.6`

## v`0.6.2`
Treats equality constraints as cones.
Fixes deprecation warnings and small API changes from RobotDynamics v`0.4.3`, including:
- Replacing `Traj` with `SampledTrajectory`
- Using `RobotDynamics.dims` instead of `Base.size`
- Using `RobotDynamics.errstate_jacobian!` instead of `RobotDynamics.state_diff_jacobian!`

## Updated to new RobotDynamics `v0.4` API
Allows for both inplace and out-of-place dynamics, cost, and constraint evaluations.
Jacobians can be calculated using finite differences, forward AD, or user-specified.
Expand Down
4 changes: 2 additions & 2 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name = "TrajectoryOptimization"
uuid = "c79d492b-0548-5874-b488-5a62c1d9d0ca"
version = "0.6.1"
version = "0.6.2"

[deps]
DocStringExtensions = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae"
Expand All @@ -20,7 +20,7 @@ DocStringExtensions = "0.8"
FiniteDiff = "2"
ForwardDiff = "0.10"
MathOptInterface = "0.9"
RobotDynamics = "0.4"
RobotDynamics = "0.4.3"
RobotZoo = "0.3"
Rotations = "~1.0"
StaticArrays = "1"
Expand Down
4 changes: 2 additions & 2 deletions docs/src/constraint_interface.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,13 @@ end
control_dim(con::ControlNorm2) = con.m
sense(::ControlNorm2) = Inequality()
Base.length(::ControlNorm2) = 1
function evaluate!(vals, con::ControlNorm2, Z::AbstractTrajectory, inds=1:length(Z))
function evaluate!(vals, con::ControlNorm2, Z::SampledTrajectory, inds=1:length(Z))
for (i,k) in enumerate(inds)
u = control(Z[k])
vals[i] = SA[norm(u) - con.a[i]]
end
end
function jacobian!(∇c, con::ControlNorm2, Z::AbstractTrajectory, inds=1:length(Z),
function jacobian!(∇c, con::ControlNorm2, Z::SampledTrajectory, inds=1:length(Z),
is_const = BitArray(undef, size(∇c)))
for (i,k) in enumerate(inds)
u = control(Z[k])
Expand Down
2 changes: 1 addition & 1 deletion docs/src/creating_problems.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,5 +123,5 @@ set_times!(Z::Traj, t::Vector)

To initialize a problem with a given `Traj` type, you can use
```
initial_trajectory!(::Problem, Z::AbstractTrajectory)
initial_trajectory!(::Problem, Z::SampledTrajectory)
```
2 changes: 1 addition & 1 deletion src/TrajectoryOptimization.jl
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ using RobotDynamics: AbstractModel, DiscreteDynamics, LieGroupModel, DiscreteLie
QuadratureRule, Implicit, Explicit,
state_dim, control_dim, output_dim,
is_terminal, state_diff, state_diff_jacobian!,
state, control, states, controls, gettimes, Traj, AbstractTrajectory,
state, control, states, controls, gettimes, SampledTrajectory,
num_vars, dims,
FunctionSignature, DiffMethod,
FiniteDifference, ForwardAD, StaticReturn, InPlace, UserDefined
Expand Down
42 changes: 28 additions & 14 deletions src/abstract_constraint.jl
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,20 @@ in, they are assumed to be consistent with those returned by `state_dim` and `co
############################################################################################
# EVALUATION METHODS #
############################################################################################
function evaluate_constraint!(::StaticReturn, con::AbstractConstraint, val, args...)
val .= RD.evaluate(con, args...)
end

function evaluate_constraint!(::InPlace, con::AbstractConstraint, val, args...)
RD.evaluate!(con, val, args...)
val
end

function constraint_jacobian!(sig::FunctionSignature, diff::DiffMethod, con, jac, val, args...)
RD.jacobian!(sig, diff, con, jac, val, args...)
end


"""
evaluate!(vals, con::AbstractConstraint, Z, [inds])
Expand All @@ -168,11 +182,11 @@ The `inds` argument determines at which knot points the constraint is evaluated.
If `con` is a `StageConstraint`, this will call `evaluate(con, z)` by default, or
`evaluate(con, z1, z2)` if `con` is a `CoupledConstraint`.
"""
@generated function RD.evaluate!(
@generated function evaluate_constraints!(
sig::StaticReturn,
con::StageConstraint,
vals::Vector{V},
Z::AbstractTrajectory,
Z::SampledTrajectory,
inds = 1:length(Z)
) where V
op = V <: SVector ? :(=) : :(.=)
Expand All @@ -183,11 +197,11 @@ If `con` is a `StageConstraint`, this will call `evaluate(con, z)` by default, o
end
end

function RD.evaluate!(
function evaluate_constraints!(
sig::InPlace,
con::StageConstraint,
vals::Vector{<:AbstractVector},
Z::AbstractTrajectory,
Z::SampledTrajectory,
inds = 1:length(Z)
)
for (i, k) in enumerate(inds)
Expand All @@ -198,7 +212,7 @@ end
# function evaluate!(
# vals::Vector{<:AbstractVector},
# con::StageConstraint,
# Z::AbstractTrajectory,
# Z::SampledTrajectory,
# inds = 1:length(Z),
# )
# for (i, k) in enumerate(inds)
Expand All @@ -209,7 +223,7 @@ end
# function evaluate!(
# vals::Vector{<:AbstractVector},
# con::CoupledConstraint,
# Z::AbstractTrajectory,
# Z::SampledTrajectory,
# inds = 1:length(Z)-1,
# )
# for (i, k) in enumerate(inds)
Expand All @@ -233,13 +247,13 @@ The values are stored in `∇c`, which should be a matrix of matrices. If `con`
If `con` is a `StageConstraint`, this will call `jacobian!(∇c, con, z)` by default, or
`jacobian!(∇c, con, z1, z2, i)` if `con` is a `CoupledConstraint`.
"""
function RD.jacobian!(
function constraint_jacobians!(
sig::FunctionSignature,
dif::DiffMethod,
con::StageConstraint,
∇c::VecOrMat{<:AbstractMatrix},
c::VecOrMat{<:AbstractVector},
Z::AbstractTrajectory,
Z::SampledTrajectory,
inds = 1:length(Z)
)
for (i, k) in enumerate(inds)
Expand All @@ -250,7 +264,7 @@ end
# function jacobian!(
# ∇c::VecOrMat{<:AbstractMatrix},
# con::StageConstraint,
# Z::AbstractTrajectory,
# Z::SampledTrajectory,
# inds = 1:length(Z),
# is_const = BitArray(undef, size(∇c))
# )
Expand All @@ -262,7 +276,7 @@ end
# function jacobian!(
# ∇c::VecOrMat{<:AbstractMatrix},
# con::CoupledConstraint,
# Z::AbstractTrajectory,
# Z::SampledTrajectory,
# inds = 1:size(∇c, 1),
# is_const = BitArray(undef, size(∇c))
# )
Expand Down Expand Up @@ -295,7 +309,7 @@ function RD.∇jacobian!(
H::VecOrMat{<:AbstractMatrix},
λ::VecOrMat{<:AbstractVector},
c::VecOrMat{<:AbstractVector},
Z::AbstractTrajectory,
Z::SampledTrajectory,
inds = 1:length(Z)
)
for (i, k) in enumerate(inds)
Expand All @@ -305,7 +319,7 @@ end

function error_expansion!(jac, jac0, con::StageConstraint, model::DiscreteDynamics, G, inds) where C
if jac !== jac0
n,m = size(model)
n,m = RD.dims(model)
= RD.errstate_dim(model)
ix = 1:
iu =.+ (1:m)
Expand All @@ -329,7 +343,7 @@ end
# function ∇jacobian!(
# G::VecOrMat{<:AbstractMatrix},
# con::StageConstraint,
# Z::AbstractTrajectory,
# Z::SampledTrajectory,
# λ::Vector{<:AbstractVector},
# inds = 1:length(Z),
# is_const = ones(Bool, length(inds)),
Expand All @@ -345,7 +359,7 @@ end
# function ∇jacobian!(
# G::VecOrMat{<:AbstractMatrix},
# con::CoupledConstraint,
# Z::AbstractTrajectory,
# Z::SampledTrajectory,
# λ::Vector{<:AbstractVector},
# inds = 1:length(Z),
# is_const = ones(Bool, length(inds)),
Expand Down
32 changes: 30 additions & 2 deletions src/cones.jl
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,15 @@ If `sense(con) <: Conic` (i.e. not `Equality`), then the following operations ar
abstract type ConstraintSense end
abstract type Conic <: ConstraintSense end

struct IdentityCone <: Conic end
struct ZeroCone <: Conic end

"""
Equality constraints of the form ``g(x) = 0`.
Type singleton, so it is created with `Equality()`.
"""
struct Equality <: ConstraintSense end
const Equality = ZeroCone

"""
Inequality constraints of the form ``h(x) \\leq 0``.
Type singleton, so it is created with `Inequality()`.
Expand All @@ -37,10 +41,16 @@ the last element in the vector.
"""
struct SecondOrderCone <: Conic end

conename(::C) where {C <: Conic} = C.name.name

dualcone(::IdentityCone) = ZeroCone()
dualcone(::ZeroCone) = IdentityCone()
dualcone(::NegativeOrthant) = NegativeOrthant()
dualcone(::PositiveOrthant) = PositiveOrthant()
dualcone(::SecondOrderCone) = SecondOrderCone()

projection(::IdentityCone, x) = x
projection(::ZeroCone, x) = zero(x)
projection(::NegativeOrthant, x) = min.(0, x)
projection(::PositiveOrthant, x) = max.(0, x)

Expand All @@ -64,7 +74,9 @@ projection(::PositiveOrthant, x) = max.(0, x)
end
end

projection!(::Equality, px, x) = px .= 0
projection!(::IdentityCone, px, x) = px .= x
projection!(::ZeroCone, px, x) = px .= 0
# projection!(::Equality, px, x) = px .= 0

function projection!(::NegativeOrthant, px, x)
@assert length(px) == length(x)
Expand Down Expand Up @@ -95,6 +107,17 @@ function projection!(::SecondOrderCone, px, x::V) where V <: AbstractVector
return pv
end

function ∇projection!(::IdentityCone, J, x)
T = eltype(J)
J .= 0
for i = 1:length(x)
J[i,i] = one(T)
end
return J
end

∇projection!(::ZeroCone, J, x) = J .= 0

function ∇projection!(::NegativeOrthant, J, x)
for i in eachindex(x)
J[i,i] = x[i] <= 0 ? 1 : 0
Expand Down Expand Up @@ -145,6 +168,8 @@ end
end
end

Base.in(x, ::IdentityCone) = true
Base.in(x, ::ZeroCone) = norm(x, 1) zero(eltype(X))
Base.in(x, ::NegativeOrthant) = all(x->x<=0, x)

function Base.in(x, ::SecondOrderCone)
Expand All @@ -154,6 +179,9 @@ function Base.in(x, ::SecondOrderCone)
return a <= s
end

∇²projection!(::IdentityCone, hess, x, b) = hess .= 0
∇²projection!(::ZeroCone, hess, x, b) = hess .= 0

function ∇²projection!(::NegativeOrthant, hess, x, b)
get_data(hess) .= 0
end
Expand Down
8 changes: 4 additions & 4 deletions src/conset.jl
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,19 @@ Base.IteratorEltype(::AbstractConstraintSet) = Base.HasEltype()
Base.eltype(::AbstractConstraintSet) = AbstractConstraint

# Constraint Evaluation
function RD.evaluate!(conSet::AbstractConstraintSet, Z::AbstractTrajectory)
function RD.evaluate!(conSet::AbstractConstraintSet, Z::SampledTrajectory)
for i = 1:length(conSet)
RD.evaluate!(conSet.convals[i], Z)
end
end

function RD.jacobian!(conSet::AbstractConstraintSet, Z::AbstractTrajectory, init::Bool=true)
function RD.jacobian!(conSet::AbstractConstraintSet, Z::SampledTrajectory, init::Bool=true)
for conval in get_convals(conSet)
RD.jacobian!(conval, Z)
end
end

function RD.∇jacobian!(G::Vector{<:Matrix}, conSet::AbstractConstraintSet, Z::AbstractTrajectory,
function RD.∇jacobian!(G::Vector{<:Matrix}, conSet::AbstractConstraintSet, Z::SampledTrajectory,
λ::Vector{<:Vector})
for (i,conval) in enumerate(get_convals(conSet))
RD.∇jacobian!(G[i], conval, Z, λ[i])
Expand Down Expand Up @@ -102,7 +102,7 @@ function norm_violation!(conSet::AbstractConstraintSet, p=2)
end
end

function norm_dgrad(conSet::AbstractConstraintSet, dx::AbstractTrajectory, p=1)
function norm_dgrad(conSet::AbstractConstraintSet, dx::SampledTrajectory, p=1)
convals = get_convals(conSet)
T = eltype(conSet.c_max)
for i in eachindex(convals)
Expand Down
Loading

2 comments on commit f556de4

@bjack205
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator register()

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/55828

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v0.6.2 -m "<description of version>" f556de408e1b16b2acfd85f382c0732e49375cdc
git push origin v0.6.2

Please sign in to comment.