Skip to content

Commit 044cd8b

Browse files
committed
doc updates, fix this_side_up and unit test it
1 parent 58bd74a commit 044cd8b

File tree

13 files changed

+122
-50
lines changed

13 files changed

+122
-50
lines changed

cmake/add_python_unit_tests.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ set(python_test_scripts
44
arm_to_cart_target.py
55
fullbody_plan.py
66
position_base.py
7+
this_side_up.py
78
)
89

910
foreach(pyfile ${python_test_scripts})

doc/Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ all: sphinx doxygen
4949
doxygen:
5050
doxygen Doxyfile
5151

52+
shell:
53+
sh generate_shell_output.sh
54+
5255
upload:
5356
rsync -azvu --delete --progress ./ [email protected]:/var/www/trajopt/doc/
5457

doc/cmd_output/ctest.txt

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
Test project /home/joschu/build/trajopt
2+
Start 1: arm_to_joint_target.py
3+
1/9 Test #1: arm_to_joint_target.py ............. Passed 1.53 sec
4+
Start 2: arm_to_cart_target.py
5+
2/9 Test #2: arm_to_cart_target.py .............. Passed 1.78 sec
6+
Start 3: fullbody_plan.py
7+
3/9 Test #3: fullbody_plan.py ................... Passed 2.63 sec
8+
Start 4: position_base.py
9+
4/9 Test #4: position_base.py ................... Passed 1.84 sec
10+
Start 5: arm_to_cart_target_position_only
11+
5/9 Test #5: arm_to_cart_target_position_only ... Passed 1.77 sec
12+
Start 6: sco-unit
13+
6/9 Test #6: sco-unit ........................... Passed 0.08 sec
14+
Start 7: collision-checker-unit
15+
7/9 Test #7: collision-checker-unit ............. Passed 0.09 sec
16+
Start 8: planning-unit
17+
8/9 Test #8: planning-unit ...................... Passed 1.05 sec
18+
Start 9: cast-cost-unit
19+
9/9 Test #9: cast-cost-unit ..................... Passed 0.09 sec
20+
21+
100% tests passed, 0 tests failed out of 9
22+
23+
Total Test time (real) = 10.90 sec

doc/generate_shell_output.sh

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#!/bin/sh
2+
3+
curdir=`pwd`
4+
cd ~/build/trajopt
5+
ctest > $curdir/cmd_output/ctest.txt
6+

doc/install.rst

Lines changed: 16 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -9,29 +9,31 @@ This code has been tested on Linux and OSX.
99
Dependencies
1010
------------
1111

12-
- OpenRAVE
12+
- OpenRAVE (>= 0.8 required, >= 0.9 highly recommended)
1313
- OpenSceneGraph
1414
- CMake
1515
- boost
1616
- Eigen
17-
- Gurobi [#gurobi]_
17+
- Gurobi [#gurobi]_ (recommended)
18+
19+
.. [#gurobi] On Linux, Trajopt now works with the free solver BPMPD, which is included with the source distribution (as a static library). However, Gurobi is better-tested with Trajopt and usually performs better.
1820
19-
.. [#gurobi] Good news! Trajopt now works with the excellent free solver BPMPD. It's not very well-tested at the moment, but you can use it now by checking out the devel branch and setting TRAJOPT_CONVEX_SOLVER=BPMPD.
2021
2122
Instructions
2223
-------------
2324

24-
- install OpenRAVE 0.8 or above
25-
26-
.. note:: For best results, install a new version of OpenRAVE (version 0.9). Due to a recent bugfix, optimization over affine DOFs won't work with 0.8. You can install from source or use the `openrave testing <https://launchpad.net/~openrave/+archive/testing>`_ PPA.
25+
- install OpenRAVE. To obtain OpenRAVE 0.9, you can install from source or use the `openrave testing <https://launchpad.net/~openrave/+archive/testing>`_ PPA.
2726

2827

2928
- install OpenSceneGraph, CMake, boost, and Eigen using your package manager. In Ubuntu, that's::
3029

31-
sudo apt-get install libopenscene-graph cmake libboost-all-dev libeigen3-dev
30+
sudo apt-get install libopenscenegraph-dev cmake libboost-all-dev libeigen3-dev python-numpy
31+
32+
- Gurobi (optional):
33+
34+
- download and install Gurobi from `<http://www.gurobi.com>`_. You'll need to make an account and obtain a license. It's free for academic use, and non-academic users can get a free trial.
35+
- set the environment variable GUROBI_HOME to point to the folder of your Gurobi directory that contains the folders :file:`include` and :file:`lib`. On my development machines, these are :file:`/home/username/Src/gurobi502/linux64` and :file:`/Library/gurobi501/mac64`.
3236

33-
- download and install Gurobi from `<http://www.gurobi.com>`_. You'll need to make an account and obtain a license. It's free for academic use, and non-academic users can get a free trial.
34-
- set the environment variable GUROBI_HOME to point to the folder of your Gurobi directory that contains the folders :file:`include` and :file:`lib`. On my development machines, these are :file:`/home/username/Src/gurobi502/linux64` and :file:`/Library/gurobi501/mac64`.
3537
- Clone trajopt from `github <https://github.com/joschu/trajopt>`_
3638
- Follow the usual CMake procedure::
3739

@@ -55,26 +57,10 @@ You can check if the build worked by typing
5557

5658
ctest
5759
58-
in the build directory. The output should look something like this::
59-
60-
Running tests...
61-
Test project /Users/joschu/build/trajopt-release
62-
Start 1: arm_to_cart_target.py
63-
1/6 Test #1: arm_to_cart_target.py ............ Passed 2.30 sec
64-
Start 2: arm_to_joint_target.py
65-
2/6 Test #2: arm_to_joint_target.py ........... Passed 1.93 sec
66-
Start 3: sco-unit
67-
3/6 Test #3: sco-unit ......................... Passed 0.04 sec
68-
Start 4: collision-checker-unit
69-
4/6 Test #4: collision-checker-unit ........... Passed 0.05 sec
70-
Start 5: planning-unit
71-
5/6 Test #5: planning-unit .................... Passed 1.43 sec
72-
Start 6: cast-cost-unit
73-
6/6 Test #6: cast-cost-unit ................... Passed 0.05 sec
74-
75-
100% tests passed, 0 tests failed out of 7
76-
77-
Total Test time (real) = 8.09 sec
60+
in the build directory. The output should look something like this:
61+
62+
.. include:: cmd_output/ctest.txt
63+
:literal:
7864

7965
If one of the unit tests fails, you can get more diagnostic information by running with ``ctest -V``, or running the test scripts individually. The python executables are in ``SOURCE_DIR/python_examples`` and the compiled c++ executables are in ``BUILD_DIR/bin``.
8066

@@ -94,4 +80,4 @@ Common installation problems
9480

9581
* *All the python tests fail* with an ``ImportError``, because ``trajoptpy`` is not found or ``ctrajoptpy`` is not found. That means your ``PYTHONPATH`` is not set correctly. It should have both the trajopt source directory ``/path/to/trajopt`` and the ``lib`` subdirectory of the build directory, ``/path/to/build_trajopt/lib``.
9682

97-
* *Almost all the tests fail, where OpenRAVE symbols aren't found*. Set ``LD_LIBRARY_PATH=/usr/local/lib`` or whereever libopenrave.so is. (Note: if you know how to fix this problem through RPATH settings or linker flags, please enlighten me.)
83+
* *Almost all the tests fail, where OpenRAVE symbols aren't found*. Set ``LD_LIBRARY_PATH=/usr/local/lib`` or whereever libopenrave.so is. (Note: if you know how to fix this problem through RPATH settings or linker flags, please enlighten me.)

doc/misc.rst

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,36 +11,38 @@ Downloading test data
1111

1212
First navigate to the ``bigdata`` directory, and then run the script ``download.py``.
1313

14+
15+
.. _collcosts:
16+
1417
Collision costs
1518
------------------
1619

1720
There are two types of collision penalty provided: a discrete-time penalty and a continuous-time penalty. The discrete-time penalty is based on the signed distance between the robot's links and the obstacles (including robot links). The continuous-time penalty considers the volume swept-out by the robot's links as it moves from one timestep to the next. See the paper for more details. While the discrete-time penalty will often jump through a thin obstacle, the continuous-time penalty will properly penalize such events. The only downside of the continuous-time penalty is that it currently doesn't check self-collisions. If you want to avoid self-collisions, you can add a discrete-time and continuous-time penalty.
1821

19-
From python, both penalties have the same API. The optional ``first_step`` and ``last_step`` arguments are the first and last timestep (inclusive) for the costs.
22+
In JSON, you can switch between the types of cost with the ``continuous`` parameter, which is ``True`` by default.
2023

2124
Discrete-time collision:
2225

2326
.. code-block:: python
2427
2528
{
2629
"type" : "collision",
27-
"params" : {"coeffs" : [10],"dist_pen" : [0.025], "first_step":0, "last_step":19}
30+
"params" : {"coeffs" : [20],"dist_pen" : [0.025], "first_step":0, "last_step":19, "continuous":False}
2831
}
2932
30-
TODO: update this
3133
Continuous-time collision:
3234

3335
.. code-block:: python
3436
3537
{
36-
"type" : "continuous_collision",
37-
"params" : {"coeffs" : [10],"dist_pen" : [0.025], "first_step":0, "last_step":19}
38+
"type" : "collision",
39+
"params" : {"coeffs" : [20],"dist_pen" : [0.025], "first_step":0, "last_step":19, "continuous":True}
3840
}
3941
4042
Finding out about available costs and constraints
4143
----------------------------------------------------------------
4244

4345
Some costs and constraints have been implemented but are not currently documented here.
44-
One way to find out about which ones have been implemented and what parameters are available is to look at the Doxygen documentation for the subclasses of `CostInfo <../../dox_build/structtrajopt_1_1_cost_info.html>`_ and `CntInfo <../../dox_build/structtrajopt_1_1_cnt_info.html>`_ because each item under "costs" or "constraints" in the JSON document is first converted to one of these structs when the JSON file is read.
46+
One way to find out about which ones have been implemented and what parameters are available is to look at the Doxygen documentation for the subclasses of `TermInfo <../../dox_build/structtrajopt_1_1_term_info.html>`_ because each item under "costs" or "constraints" in the JSON document is first converted to one of these structs when the JSON file is read.
4547

4648

doc/open_index.sh

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#!/bin/sh
2+
3+
index=sphinx_build/html/index.html
4+
if [ `uname` = Linux ]
5+
then
6+
google-chrome $index
7+
else
8+
open -a Google\ Chrome $index
9+
fi

doc/tutorial.rst

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,17 @@ The optimization will pause at every iteration and plot the current trajectory a
2121

2222
Every problem description contains four sections: basic_info, costs, constraints, and init_info (i.e., initialization info).
2323

24-
Here, there are two cost components: joint-space velocity, and the collision penalty. There is one constraint: the final joint state.
24+
Here, there are two cost components: joint-space velocity, and the collision penalty. There is one constraint: the final joint state.
2525

2626
.. note:: Why do we use a collision cost, rather than a constraint? In the sequential convex optimization procedure, constraints get converted into costs--specifically, :math:`\ell_1` penalties (see the paper). So the difference between a constraint and an :math:`\ell_1` cost is that for a constraint, the optimizer checks to see if it is satisfied (to some tolerance), and if not, it jacks up the penalty coefficient. The thing about collisions is that it's often necessary to violate the safety margin, e.g. when you need to contact an object. So you're best off handling the logic yourself of adjusting penalties and safety margins, based on your specific problem.
2727

28+
See :ref:`collcosts` for more info on the collision penalty.
29+
2830

2931
Move arm to pose target
3032
-------------------------
3133
Full source code: :file:`python_examples/arm_to_cart_target.py`
3234

33-
3435
Next, let's solve the same problem, but instead of specifying the target joint position, we'll specify the target pose.
3536

3637
Now we use a pose constraint instead of a joint constraint:
@@ -48,6 +49,7 @@ Initialize using collision-free IK:
4849
...
4950

5051
.. literalinclude:: ../python_examples/arm_to_cart_target.py
52+
:language: python
5153
:start-after: BEGIN init
5254
:end-before: END init
5355

@@ -62,6 +64,49 @@ Whether you use a straight-line initialization, stationary initialization, or so
6264
You can see this strategy in ``benchmark.py``, which uses four waypoints. Using this strategy, the algorithm solves 100% of 204 planning problems in the three provided scenes (tabletop, bookshelves, and kitchen_counter).
6365

6466

67+
All in all, there are several ways to initialize:
68+
69+
- **Stationary**: Initialize with the trajectory that stands still for ``n_steps`` timesteps.
70+
71+
.. code-block:: python
72+
73+
"init_info" : {
74+
"type" : "stationary"
75+
}
76+
77+
- **With a given trajectory**:
78+
79+
.. code-block:: python
80+
81+
"init_info" : {
82+
"type" : "given_traj"
83+
"data" : [[ 0. , 0. , 0. ],
84+
[ 0.111, 0.222, 0.333],
85+
[ 0.222, 0.444, 0.667],
86+
[ 0.333, 0.667, 1. ],
87+
[ 0.444, 0.889, 1.333],
88+
[ 0.556, 1.111, 1.667],
89+
[ 0.667, 1.333, 2. ],
90+
[ 0.778, 1.556, 2.333],
91+
[ 0.889, 1.778, 2.667],
92+
[ 1. , 2. , 3. ]]
93+
}
94+
95+
``data`` must be a 2d array with ``n_steps`` rows, and the first row must be the robot's current DOF values
96+
97+
- **With a straight line in configuration space**.
98+
99+
.. code-block:: python
100+
101+
"init_info" : {
102+
"type" : "given_traj"
103+
"endpoint" : [ 1. , 2. , 3. ]
104+
}
105+
106+
The robot's DOF values are used for the start point of the line.
107+
108+
109+
65110
.. _rollingyourown:
66111

67112
Rolling your own costs and constraints in python
@@ -72,7 +117,8 @@ Full source code: :file:`python_examples/this_side_up.py`
72117

73118
This next script shows how you can easily implement your own costs and constraints. The constraint we consider here says that a certain vector defined in the robot gripper frame must point up (in the world coordinates). For example, one might imagine that the robot is holding a glass of water, and we don't want it to spill.
74119

75-
The basic setup of the problem is similar to the previous examples.
120+
The basic setup of the problem is similar to the previous examples. Before getting to the python constraint functions, we'll add some constraints to the problem in the json file, including a cartesian velocity constraint.
121+
76122
We set a pose constraint at the end of the trajectory. This time, we ignore the rotation (by setting :code:`rot_coefs = [0,0,0]`).
77123

78124
.. literalinclude:: ../python_examples/this_side_up.py

notes/trajopt-todo.txt

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,15 @@ RobotAndDOF is a mess now
1414

1515
filtermask arguments in collision_terms
1616

17+
fixed length steps: need a custom constraint + projection
18+
1719
Eventually
1820
===========
1921

20-
do something about METERS
2122

22-
fix up bpmd interface
2323

2424
boost python arguments
2525

26-
voxel grid collision checking. or at least preprocess voxel grid data.
27-
2826
TrajArray/DblMatrix/MatrixXd mean the same thing
2927

3028
PECost is PE^2

python_examples/arm_to_cart_target.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@
4242
{
4343
"type" : "joint_vel", # joint-space velocity cost
4444
"params": {"coeffs" : [1]} # a list of length one is automatically expanded to a list of length n_dofs
45-
# Also valid: "coeffs" : [7,6,5,4,3,2,1]
4645
},
4746
{
4847
"type" : "collision",
@@ -61,8 +60,7 @@
6160
"params" : {"xyz" : xyz_target,
6261
"wxyz" : quat_target,
6362
"link": "r_gripper_tool_frame",
64-
# "timestep" : 9
65-
# omitted because timestep = n_steps-1 is default
63+
"timestep" : 9
6664
}
6765

6866
}

python_examples/arm_to_joint_target.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
{
3333
"type" : "joint_vel", # joint-space velocity cost
3434
"params": {"coeffs" : [1]} # a list of length one is automatically expanded to a list of length n_dofs
35-
# Also valid: "coeffs" : [7,6,5,4,3,2,1]
35+
# also valid: [1.9, 2, 3, 4, 5, 5, 4, 3, 2, 1]
3636
},
3737
{
3838
"type" : "collision",

python_examples/this_side_up.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@
6767
"type" : "cart_vel",
6868
"name" : "cart_vel",
6969
"params" : {
70-
"distance_limit" : .05,
70+
"max_displacement" : .05,
7171
"first_step" : 0,
7272
"last_step" : n_steps-1, #inclusive
7373
"link" : "r_gripper_tool_frame"
@@ -117,4 +117,4 @@ def dfdx(x):
117117
# END add_constraints
118118

119119
result = trajoptpy.OptimizeProblem(prob) # do optimization
120-
print result
120+
assert [viol <= 1e-4 for (_name,viol) in result.GetConstraints()]

src/trajopt/problem_description.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -420,7 +420,7 @@ void CartVelCntInfo::fromJson(const Value& v) {
420420
PRINT_AND_THROW( boost::format("invalid link name: %s")%linkstr);
421421
}
422422

423-
const char* all_fields[] = {"first_step", "last_step", "max_displacement"};
423+
const char* all_fields[] = {"first_step", "last_step", "max_displacement","link"};
424424
ensure_only_members(params, all_fields, sizeof(all_fields)/sizeof(char*));
425425

426426

0 commit comments

Comments
 (0)