Skip to content

Commit

Permalink
Merge 52fde60 into 4e38ddd
Browse files Browse the repository at this point in the history
  • Loading branch information
hungpham2511 authored Nov 7, 2018
2 parents 4e38ddd + 52fde60 commit ae86afa
Show file tree
Hide file tree
Showing 37 changed files with 608 additions and 281 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ before_install:
- ./install-fcl.sh
- ./install-openrave.sh
- sudo apt install python-tk
- pip install --ignore-installed cython matplotlib coverage python-coveralls --user
- pip install --ignore-installed cython matplotlib coverage python-coveralls cvxopt --user

install:
# Install dependencies
Expand Down
5 changes: 3 additions & 2 deletions examples/kinematics.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,9 @@ def main():
pc_acc = constraint.JointAccelerationConstraint(
alim, discretization_scheme=constraint.DiscretizationType.Interpolation)

# Setup a parametrization instance
instance = algo.TOPPRA([pc_vel, pc_acc], path, solver_wrapper='seidel')
# Setup a parametrization instance. The keyword arguments are
# optional.
instance = algo.TOPPRA([pc_vel, pc_acc], path)

# Retime the trajectory, only this step is necessary.
t0 = time.time()
Expand Down
3 changes: 2 additions & 1 deletion tests/constraint/test_create_rave_torque.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ def test_torque_bound_barret(barret_robot, dof):
constraint = toppra.create_rave_torque_path_constraint(barret_robot)
np.random.seed(0)
path = toppra.SplineInterpolator(np.linspace(0, 1, 5), np.random.rand(5, dof))
a, b, c, F, g, _, _ = constraint.compute_constraint_params(path, np.linspace(0, path.get_duration(), 5))
a, b, c, F, g, _, _ = constraint.compute_constraint_params(
path, np.linspace(0, path.get_duration(), 5), 1.0)

assert a.shape[1] == dof
assert b.shape[1] == dof
Expand Down
9 changes: 5 additions & 4 deletions tests/constraint/test_joint_acceleration.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import numpy.testing as npt
import toppra as ta
import toppra.constraint as constraint
from toppra.constants import MAXU
from toppra.constants import JACC_MAXU


@pytest.fixture(scope="class", params=[1, 2, 6], name='acceleration_pc_data')
Expand Down Expand Up @@ -70,7 +70,7 @@ def test_constraint_params(self, acceleration_pc_data):
path, ss, alim = data

# An user of the class
a, b, c, F, g, ubound, xbound = constraint.compute_constraint_params(path, ss)
a, b, c, F, g, ubound, xbound = constraint.compute_constraint_params(path, ss, 1.0)
assert xbound is None

N = ss.shape[0] - 1
Expand All @@ -88,13 +88,14 @@ def test_constraint_params(self, acceleration_pc_data):
npt.assert_allclose(a[i], ps[i])
npt.assert_allclose(b[i], pss[i])
npt.assert_allclose(c[i], np.zeros_like(ps[i]))
npt.assert_allclose(ubound[i], [-MAXU, MAXU])
assert ubound is None
assert xbound is None

def test_wrong_dimension(self, acceleration_pc_data):
data, pc = acceleration_pc_data
path_wrongdim = ta.SplineInterpolator(np.linspace(0, 1, 5), np.random.randn(5, 10))
with pytest.raises(ValueError) as e_info:
pc.compute_constraint_params(path_wrongdim, np.r_[0, 0.5, 1])
pc.compute_constraint_params(path_wrongdim, np.r_[0, 0.5, 1], 1.0)
assert e_info.value.args[0] == "Wrong dimension: constraint dof ({:d}) not equal to path dof ({:d})".format(
pc.get_dof(), 10
)
Expand Down
12 changes: 6 additions & 6 deletions tests/constraint/test_joint_velocity.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import numpy.testing as npt
import toppra as ta
import toppra.constraint as constraint
from toppra.constants import TINY, MAXSD
from toppra.constants import TINY, JVEL_MAXSD
from scipy.interpolate import CubicSpline


Expand Down Expand Up @@ -53,7 +53,7 @@ def test_constraint_satisfaction(self, velocity_pc_data):
data, pc = velocity_pc_data
path, ss, vlim = data

constraint_param = pc.compute_constraint_params(path, ss)
constraint_param = pc.compute_constraint_params(path, ss, 1.0)
_, _, _, _, _, _, xlimit = constraint_param

qs = path.evald(ss)
Expand All @@ -65,7 +65,7 @@ def test_constraint_satisfaction(self, velocity_pc_data):
# 2. Compute max sd from the data
constraints = [qs[i] * sd <= vlim[:, 1],
qs[i] * sd >= vlim[:, 0],
sd >= 0, sd <= MAXSD]
sd >= 0, sd <= JVEL_MAXSD]
prob = cvx.Problem(cvx.Maximize(sd), constraints)
prob.solve(solver=cvx.ECOS, abstol=1e-9)
xmax = sd.value ** 2
Expand All @@ -84,7 +84,7 @@ def test_wrong_dimension(self, velocity_pc_data):
data, pc = velocity_pc_data
path_wrongdim = ta.SplineInterpolator(np.linspace(0, 1, 5), np.random.randn(5, 10))
with pytest.raises(ValueError) as e_info:
pc.compute_constraint_params(path_wrongdim, [0, 0.5, 1])
pc.compute_constraint_params(path_wrongdim, [0, 0.5, 1], 1.0)
assert e_info.value.args[0] == "Wrong dimension: constraint dof ({:d}) not equal to path dof ({:d})".format(
pc.get_dof(), 10
)
Expand All @@ -111,7 +111,7 @@ def test_jnt_vel_varying_basic():
coeff = [[1., 2, 3], [-2., -3., 4., 5.]]
path = ta.PolynomialPath(coeff)
gridpoints = np.linspace(0, 2, 10)
_, _, _, _, _, _, xlimit = constraint.compute_constraint_params(path, gridpoints)
_, _, _, _, _, _, xlimit = constraint.compute_constraint_params(path, gridpoints, 1.0)
# constraint splines
qs = path.evald(gridpoints)
# test
Expand All @@ -122,7 +122,7 @@ def test_jnt_vel_varying_basic():
# 2. compute max sd from the data
constraints = [qs[i] * sd <= vlim[:, 1],
qs[i] * sd >= vlim[:, 0],
sd >= 0, sd <= MAXSD]
sd >= 0, sd <= JVEL_MAXSD]
prob = cvx.Problem(cvx.Maximize(sd), constraints)
prob.solve(solver=cvx.ECOS, abstol=1e-9)
xmax = sd.value ** 2
Expand Down
15 changes: 7 additions & 8 deletions tests/constraint/test_robust_can_linear.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,8 @@ def test_basic(accel_constraint, dist_scheme):
assert ro_cnst.get_constraint_type() == toppra.constraint.ConstraintType.CanonicalConic
assert ro_cnst.get_dof() == 5

a, b, c, P = ro_cnst.compute_constraint_params(
path, np.linspace(0, path.get_duration(), 10))
d = a.shape[1] - 2
a, b, c, P, _, _ = ro_cnst.compute_constraint_params(
path, np.linspace(0, path.get_duration(), 10), 1.0)

# assert a.shape == (10, 2 * path.get_dof())
# assert b.shape == (10, 2 * path.get_dof())
Expand All @@ -38,18 +37,18 @@ def test_basic(accel_constraint, dist_scheme):

# Linear params
cnst.set_discretization_type(dist_scheme)
a0, b0, c0, F0, g0, _, _ = cnst.compute_constraint_params(path, np.linspace(0, path.get_duration(), 10))
a0, b0, c0, F0, g0, _, _ = cnst.compute_constraint_params(
path, np.linspace(0, path.get_duration(), 10), 1.0)

# Assert values
for i in range(10):
np.testing.assert_allclose(a[i, :d], F0.dot(a0[i]))
np.testing.assert_allclose(b[i, :d], F0.dot(b0[i]))
np.testing.assert_allclose(c[i, :d], F0.dot(c0[i]) - g0)
np.testing.assert_allclose(a[i], F0.dot(a0[i]))
np.testing.assert_allclose(b[i], F0.dot(b0[i]))
np.testing.assert_allclose(c[i], F0.dot(c0[i]) - g0)
for i in range(10):
for j in range(a0.shape[1]):
np.testing.assert_allclose(P[i, j], np.diag([0.1, 2, .3]))


def test_negative_perb(accel_constraint):
"If negative pertubations are given, raise ValueError"
cnst, path = accel_constraint
Expand Down
5 changes: 3 additions & 2 deletions tests/constraint/test_second_order.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def inv_dyn(q, qd, qdd):
constraint = toppra.constraint.CanonicalLinearSecondOrderConstraint(inv_dyn, cnst_F, cnst_g, dof=2)
path_wrongdim = toppra.SplineInterpolator(np.linspace(0, 1, 5), np.random.randn(5, 10))
with pytest.raises(AssertionError) as e_info:
constraint.compute_constraint_params(path_wrongdim, np.r_[0, 0.5, 1])
constraint.compute_constraint_params(path_wrongdim, np.r_[0, 0.5, 1], 1.0)
assert e_info.value.args[0] == "Wrong dimension: constraint dof ({:d}) not equal to path dof ({:d})".format(
constraint.get_dof(), 10
)
Expand All @@ -56,7 +56,8 @@ def inv_dyn(q, qd, qdd):
return A(q).dot(qdd) + np.dot(qd.T, np.dot(B(q), qd)) + C(q)
constraint = toppra.constraint.CanonicalLinearSecondOrderConstraint(inv_dyn, cnst_F, cnst_g, dof=2)
constraint.set_discretization_type(0)
a, b, c, F, g, _, _ = constraint.compute_constraint_params(path, np.linspace(0, path.get_duration(), 10))
a, b, c, F, g, _, _ = constraint.compute_constraint_params(
path, np.linspace(0, path.get_duration(), 10), 1.0)

# Correct params
q_vec = path.eval(np.linspace(0, path.get_duration(), 10))
Expand Down
35 changes: 35 additions & 0 deletions tests/retime/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import pytest
import numpy as np
import toppra
import toppra.constraint as constraint


@pytest.fixture(params=[(0, 0)])
def basic_constraints(request):
""" Return a set of relatively simple constraints.
"""
dtype_a, dtype_ra = request.param
vlims = np.array([[-1, 1], [-1, 2], [-1, 4], [-3, 4], [-2, 4], [-3, 4], [-2, 5]],
dtype=float) * 10
alims = np.array([[-1, 1], [-1, 2], [-1, 4], [-3, 4], [-2, 4], [-3, 4], [-2, 5]],
dtype=float) * 10

vel_cnst = constraint.JointVelocityConstraint(vlims)
accl_cnst = constraint.JointAccelerationConstraint(alims, dtype_a)
robust_accl_cnst = constraint.RobustCanonicalLinearConstraint(
accl_cnst, [1e-4, 1e-4, 5e-4], dtype_ra)
yield vel_cnst, accl_cnst, robust_accl_cnst


@pytest.fixture(params=["spline", "poly"])
def basic_path(request):
""" Return a generic path.
"""
if request.param == "spline":
np.random.seed(1)
path = toppra.SplineInterpolator(np.linspace(0, 1, 5), np.random.randn(5, 7))
elif request.param == "poly":
np.random.seed(1)
coeffs = np.random.randn(7, 3) # 7 random quadratic equations
path = toppra.PolynomialPath(coeffs)
yield path
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import toppra
import toppra.constraint

toppra.setup_logging(level="DEBUG")
toppra.setup_logging(level="INFO")


@pytest.fixture(params=[0, 1], name="velacc_fixture")
Expand All @@ -30,10 +30,10 @@ def path_fixture(request):

def test_specific_duration_parametrization(velacc_fixture, path_fixture):
"""A simple test for `TOPPRAsd`, a variant of TOPPRA that computes
parameterizations with specified duration. TOPPRAsd has an
identical interface to TOPPRA with an additional method
`set_desired_duration`.
parameterizations with specified duration.
TOPPRAsd has an identical interface to TOPPRA with an additional
method `set_desired_duration`.
"""
t_desired = 50
cvlim, calim = velacc_fixture
Expand Down
84 changes: 84 additions & 0 deletions tests/retime/test_general_cases.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
"""General cases
This test suite guarantees that the basic functionalities provided by
toppra and the many interfaces to optimization solvers contained with
it work.
"""
import pytest
import numpy as np
import toppra
import toppra.constraint as constraint

toppra.setup_logging(level="INFO")

try:
import mosek
FOUND_MOSEK = True
except ImportError:
FOUND_MOSEK = False

try:
import cvxpy
FOUND_CXPY = True
except ImportError:
FOUND_CXPY = False


@pytest.mark.parametrize("solver_wrapper", ["cvxpy", "qpoases", "hotqpoases", "seidel"])
def test_toppra_linear(basic_constraints, basic_path, solver_wrapper):
"""Solve some basic problem instances.
Passing this test guaranetees that the basic functionalities are
inplace.
"""
vel_c, acc_c, ro_acc_c = basic_constraints
instance = toppra.algorithm.TOPPRA(
[vel_c, acc_c], basic_path, solver_wrapper=solver_wrapper)
X = instance.compute_feasible_sets()
assert np.all(X >= 0)
assert not np.any(np.isnan(X))

K = instance.compute_controllable_sets(0, 0)
assert np.all(K >= 0)
assert not np.any(np.isnan(K))

traj, _ = instance.compute_trajectory(0, 0)
assert traj is not None


@pytest.mark.parametrize("solver_wrapper", [
"cvxpy,qpoases",
"qpoases,hotqpoases",
"qpoases,seidel",
"hotqpoases,seidel"
])
def test_toppra_linear_compare(basic_constraints, basic_path, solver_wrapper):
""" Compare the output of the algorithm for basic instances.
"""
print("compare {:} and {:}".format(*solver_wrapper))
solver_wrapper = solver_wrapper.split(",")
vel_c, acc_c, ro_acc_c = basic_constraints
instance = toppra.algorithm.TOPPRA(
[vel_c, acc_c], basic_path, solver_wrapper=solver_wrapper[0])
instance2 = toppra.algorithm.TOPPRA(
[vel_c, acc_c], basic_path, solver_wrapper=solver_wrapper[1])

K = instance.compute_controllable_sets(0, 0)
K2 = instance2.compute_controllable_sets(0, 0)
for i in range(instance._N, -1, -1):
np.testing.assert_allclose(K[i], K2[i], atol=1e-6, rtol=1e-2,
err_msg="Mismatched at i={:} / N={:}".format(i, instance._N))

X = instance.compute_feasible_sets()
X2 = instance2.compute_feasible_sets()
for i in range(instance._N, -1, -1):
np.testing.assert_allclose(X[i], X2[i], atol=1e-6, rtol=1e-2,
err_msg="Mismatched at i={:} / N={:}".format(i, instance._N))

sd, sdd, _ = instance.compute_parameterization(0, 0)
sd2, sdd2, _ = instance2.compute_parameterization(0, 0)
for i in range(instance._N - 1, -1, -1):
np.testing.assert_allclose(sd[i], sd2[i], atol=1e-6, rtol=1e-2,
err_msg="Mismatched at i={:} / N={:}".format(i, instance._N))

29 changes: 29 additions & 0 deletions tests/retime/test_retime_scaling.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
"""This test suite ensures that problem scaling does not affect
solution quality, in the sense that a very short path (~1e-2) and a
very long path (~1e2) can be both parameterized.
"""
import pytest
import numpy as np
import toppra
import toppra.constraint as constraint

toppra.setup_logging(level="INFO")


@pytest.mark.parametrize("solver_wrapper", ["cvxpy", "hotqpoases", "seidel"])
def test_linear_case1(basic_constraints, basic_path, solver_wrapper):
"""A generic test case.
Compare scaling between 0.5 and 1.0. Since the scaling factor is
quite small, resulting trajectories should have similar durations.
"""
vel_c, acc_c, ro_acc_c = basic_constraints
instance_scale1 = toppra.algorithm.TOPPRA(
[vel_c, acc_c], basic_path, solver_wrapper=solver_wrapper, scaling=1.0)
instance_scale05 = toppra.algorithm.TOPPRA(
[vel_c, acc_c], basic_path, solver_wrapper=solver_wrapper, scaling=5)
traj1, _ = instance_scale1.compute_trajectory()
traj05, _ = instance_scale05.compute_trajectory()
# accurate up to 0.1%
np.testing.assert_allclose(traj1.duration, traj05.duration, rtol=1e-3)
Loading

0 comments on commit ae86afa

Please sign in to comment.