├── .gitignore
├── CHANGELOG.rst
├── CMakeLists.txt
├── Makefile
├── README.md
├── catkin.cmake
├── license-gpl.txt
├── package.xml
├── pythonsrc
└── orcdchomp
│ ├── __init__.py
│ └── orcdchomp.py
├── rosbuild.cmake
├── scripts
├── barrettwam_withspheres.robot.xml
└── test_wam7.py
├── setup.py
└── src
├── libcd
├── chomp.c
├── chomp.h
├── grid.c
├── grid.h
├── grid_flood.c
├── grid_flood.h
├── kin.c
├── kin.h
├── mat.c
├── mat.h
├── os.c
├── os.h
├── spatial.c
├── spatial.h
├── util.c
├── util.h
├── util_shparse.c
└── util_shparse.h
├── orcdchomp.cpp
├── orcdchomp_kdata.cpp
├── orcdchomp_kdata.h
├── orcdchomp_mod.cpp
├── orcdchomp_mod.h
├── orcwrap.cpp
└── orcwrap.h
/.gitignore:
--------------------------------------------------------------------------------
1 | *.pyc
2 |
--------------------------------------------------------------------------------
/CHANGELOG.rst:
--------------------------------------------------------------------------------
1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2 | Changelog for package or_cdchomp
3 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4 |
5 | 1.0.2 (2015-05-01)
6 | ------------------
7 | * added some simple documentation
8 | * Contributors: Chris Dellin
9 |
10 | 1.0.1 (2015-02-10)
11 | ------------------
12 | * expanded error message, and using found kinbody pointer to avoid consistency problems
13 | * merged from libcd upstream (cdellin): reworked distance field caching to just cache data (not kinbody name or sdf parameters) (commit:505)
14 | * added check if kinbody does not exist
15 | * Contributors: Chris Dellin, Christopher Dellin, Evan Shapiro
16 |
17 | 1.0.0 (2014-10-07)
18 | ------------------
19 | * Added atlas dependency.
20 | * Added libblas-dev dependency.
21 | * Preparing for 1.0.0 release.
22 | * updated copyright statement, added floating base python wrapper, and reworked runchomp kwargs handling
23 | * merged from libcd upstream (cdellin): timing now at velocity/accel limits (change limits on robot to change speed) (commit:489)
24 | * merged from libcd upstream (cdellin): added support for floating base (commits:481,491), chomp now can handle an arbitrary number of tsr constraints on both links and manipulators (commit:487)
25 | * merged from libcd upstream (cdellin): added removefield stuff (commit:484)
26 | * merged from libcd upstream (cdellin): cleaned up some grid code (commit:493)
27 | * merged from libcd upstream (cdellin): added consts to cd_kin and cd_mat (commit:492)
28 | * removed commented abort() call
29 | * completed removal of arun joint limit change due to perported performance degradation
30 | * Switched to openrave_plugin.
31 | * added support for spheres via geometry groups
32 | * Only include geometry group code in 0.9.
33 | * Added code to search for (but not create) spheres
34 | * Catkin-ized or_cdchomp.
35 | * undoing arun change to joint limits, since it performs worse
36 | * exposing derivative choice
37 | * Added libgsl as a rosdep requirement for orcdchomp.
38 | * Added release tag to orcdchomp.
39 | * chomp compiles
40 | * Added the correct joint limit fix for CHOMP
41 | * Add exception handling if an invalid linkname is provided to orcdchomp tag
42 | * throwing exception instead of aborting for joint limits
43 | * added gpl license
44 | * updated with copyright notices from libcd r490 (code isnt yet up-to-date though)
45 | * Added the releasegil flag to the Python module.
46 | * fixing bug with sending execute flag
47 | * Moved orcdchomp to pr-ros-pkg.
48 | * committing chris's changes
49 | * added temporary isnan check on smoothness cost)
50 | * length based collisionc check, untested
51 | * linear timer
52 | * orcdchomp now correctly collisions checks for self-collisions, including with grabbed bodies (mirrors orcdchomp proper r481)
53 | * Added liblapacke as a dependency
54 | * Added ability to get the total cost of a chomp path back out. This change shoudl not be disruptive. Cost is passed in as an optional parameter. It should be a list of lenght 1. If the parameter is passed, that list willb e modified to contain the cost of the chomp path.
55 | * Fixed type, and forgotten local header include in orcwrap
56 | * Updating orcdchomp to match libcd r469; removed libcd as a separate package; moved needed files into orcdchomp package
57 | * Upped libcd to fix multi-constraint matrix issue; added every_n constraint to orcdchomp; added code to time sdf computation to orcdchomp
58 | * fixed trajs_fileformstr bug introduced when runchomp was split (r15752)
59 | * reworked orcdchomp into separate functions to create, iterate, and gettraj a chomp run; runchomp simulated in python for backwards compatability!
60 | * Fixed some ee_force bugs ...
61 | * Working on ee_force addition to orcdchomp_mod
62 | * Fixed h->sphere_poss_all bug in orcdchomp ...
63 | * Working on adding ee_force stuff, but other things are broken all of a sudden ...
64 | * upped to libcd r455; improved orcdchomp by adding start_tsr functionality and removing allowlimadj; added a reconfig test to orcdchomp_tests
65 | * Adding the recent cdchomp changes to the pr tree ...
66 | * Updating orcdchomp for cd_chomp r450 ...
67 | * Removed incorrect argc check from argument parsing ...
68 | * Added allowlimadj to orcdchomp; microwave uses it, and uses cbirrt allowlimadj as well!
69 | * Fixed string reference bug (only present on older (lucid) g++ compilers ...)
70 | * Simplifying orcdchomp some more ...
71 | * Added copyright notices to files; added autotools build files for non-ROS users
72 | * Switched from ros_exportenv to openrave_exports
73 | * Fixing up orcdchomp/libcd stuff
74 | * Added hmc stuff to orcdchomp ...
75 | * Now using optional momentum term from cd_chomp r439 ...
76 | * A few adjustments to the planner implementations ...
77 | * Added max_time parameter to orcdchomp, now able to generate raw stats graphs ...
78 | * Made wrapper package for libcd ...
79 | * Some more improvements to orcdchomp for the paper ...
80 | * Reworked orcdchomp, now faster, and with curvature computation.
81 | * Fixed orcdchomp_tests cmake stuff, added timing information to orcdchomp, and cached sdfs ...
82 | * CHOMP is now 3.5x faster!
83 | * Oops! Forgot to check in the orcdchomp changes (to keep it from running into things!)
84 | * Moved orcdchomp and owd_ortraj from cdellin's branch to trunk.
85 | * Converted all orcdchomp compile-time constants to run-time parameters; now building against libcd-r434 ...
86 | * Now correctly checking whether we're actually inside each distance field.
87 | * Modified orcdchomp to use composite distance fields; also reworked cpp structure.
88 | * Committing half-baked work on orcdchomp multi-distance-field revamp ...
89 | * Now correctly raises exception on failure!
90 | * Reverting to old libcd, original OBS_FACTOR ...
91 | * Added bind to cbirrt_problem, libprrave send_for_traj now works with bound methods, chomp now accepts a starting trajectory, and we have more microwave chomp tests!
92 | * Using this sweet Python technique to bind SendCommand serializers to the module object ...
93 | * Spitting orcdchomp tests off to a separate packgae
94 | * Adding a description, and a test script (which should really go in a new package!)
95 | * Fixing some syntax errors
96 | * added simply python interface to orcdchomp ...
97 | * Removed auto-refresh from pkgbuilder
98 | * Fixed silly world origin bug!
99 | * Now checks for collision before returning the trajectory!
100 | * added xmlreader to orcdchomp module, and added spheres to the herb2_padded robot model!
101 | * Added some preliminary cost self-collision stuffs ...
102 | * Added viewspheres command and test script from anca
103 | * orcdchomp working pretty well, now for some more tests!
104 | * Got orcdchomp working with the new libcd chomp!
105 | * Working on orcdchomp ... at some point, I should sit down and better understand this cost stuff ...
106 | * Playing around with a openrave CHOMP from the libcd implementation
107 | * Contributors: Anca Dragan, Arunkumar Byravan, Chris Dellin, Christopher Dellin, Jennifer King, Michael Koval, Mike Vande Weghe, Prasanna Velagapudi
108 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | #
2 | # Personal Robotics Laboratory
3 | # Catkin/Rosbuild Switching Template
4 | #
5 | # This CMakeLists.txt file is designed to correctly switch two CMakeLists,
6 | # one for rosbuild and one for catkin.
7 | #
8 | # To use this file, create two CMakeLists:
9 | # - catkin.cmake : the CMakeLists used in ROS catkin builds
10 | # - rosbuild.cmake : the CMakeLists used for ROS rosbuild builds
11 | #
12 | cmake_minimum_required(VERSION 2.8.3)
13 | project(or_cdchomp)
14 |
15 | if (DEFINED CATKIN_TOPLEVEL OR (NOT ("$ENV{ROS_DISTRO}" STREQUAL "fuerte")))
16 | include(${PROJECT_SOURCE_DIR}/catkin.cmake)
17 | else ()
18 | include(${PROJECT_SOURCE_DIR}/rosbuild.cmake)
19 | endif ()
20 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | include $(shell rospack find mk)/cmake.mk
2 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # or_cdchomp
2 |
3 | `or_cdchomp` is a ROS package providing `orcdchomp`, an implementation of the
4 | [CHOMP] trajectory optimizer for the [OpenRAVE] simulation environment.
5 | Internally, it uses the OpenRAVE-agnostic implementation of CHOMP in [libcd]
6 | (whose code is included in this package in the `src/libcd` directory).
7 |
8 | Documentation for the package is provided primarily by way of the following
9 | usage examples. An example as a runnable script can be located at
10 | `scripts/test_wam7.py`.
11 |
12 | ## Loading the Module
13 |
14 | Once the package has been built, an instance of the module can be created as
15 | follows. As a generic module, all communication occurs over the SendCommand
16 | interface; however, the package also includes python bindings, which we
17 | attach to the module instance below. This allows us to run commands as
18 | methods of the module object (e.g. `m_chomp.viewspheres()` below).
19 |
20 | m_chomp = openravepy.RaveCreateModule(e, 'orcdchomp')
21 | import orcdchomp.orcdchomp
22 | orcdchomp.orcdchomp.bind(m_chomp)
23 |
24 | ## Robot spheres
25 |
26 | The module uses a sphere model of the robot, which in general differs from
27 | the normal geometry used for collision checking. This sphere model can be
28 | defined in two ways as specified below. In either case, the spheres defined
29 | for a robot as understood by the `orcdchomp` module can be viewed using the
30 | following command:
31 |
32 | m_chomp.viewspheres(robot=or_robot_object)
33 |
34 | This command will instantiate a new sphere kinbody in the environment for
35 | for each robot sphere (in the location given by the robot's current
36 | configuration). To remove the spheres, simply remove bodies from the
37 | environment whose names start with the string "`orcdchomp_sphere_`".
38 |
39 | ### Robot spheres in an orcdchomp XML tag
40 |
41 | See the file `scripts/barrettwam_withspheres.robot.xml` for an example.
42 | Here is a snippet:
43 |
44 |
45 | ..
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 | ...
54 |
55 | ...
56 |
57 |
58 | Here, every sphere is specified relative to a robot link via a
59 | space-separated x y z location and radius.
60 |
61 | ### Robot spheres in a special geometry group
62 |
63 | Newer versions of OpenRAVE support geometry groups which are not used by
64 | default by collision checkers, and CHOMP spheres can also be specified in
65 | this way.
66 |
67 | ## Environment signed distance fields
68 |
69 | The CHOMP algorithm uses signed distance fields to represent environment
70 | obstacles. The `orcdchomp` module computes and manages these fields
71 | internally, and will use all fields which have been defined to it.
72 |
73 | To define (and add) a new field, use the following command:
74 |
75 | m_chomp.computedistancefield(kinbody=r,cache_filename='blah.dat')
76 |
77 | This method takes the following named arguments:
78 |
79 | * `kinbody` (required): the kinbody whose base link to attach the distance field to. If the kinbody is later moved, the field will move along with it.
80 | * `cube_extent`: the extent of the cubes which constitute the discrete field.
81 | * `aabb_padding`: the padding (the same in x,y,z) used around the bounding box of the kinbody used to determine the size of the field.
82 | * `cache_filename`: the field, once calculated, will be saved to this file (binary format); it will then be read from this file subsequently.
83 |
84 | ## Running the optimizer
85 |
86 | The module instance can work on any number of optimization runs at a
87 | time. To manage these runs, one can use the following methods:
88 |
89 | run_handle = m_chomp.create(...)
90 | m_chomp.iterate(run=run_handle, ...)
91 | m_chomp.gettraj(run=run_handle, ...)
92 | m_chomp.destroy(run=run_handle)
93 |
94 | The `create()` method takes the bulk of the options, and is used to set
95 | parameters to the optimizer (described below). Once an optimization run has
96 | been created, it is referenced by a string run handle, which must be passed
97 | to the remaining methods.
98 |
99 | The `iterate()` method performs iterations of the CHOMP algorithm.
100 |
101 | The `gettraj()` method returns the current trajectory from the optimizer,
102 | and also optionally performs collision checks on the trajectory.
103 |
104 | The `destroy()` method simply cleans up internal data structures for the run.
105 |
106 | While this API was designed so that `iterate()` and `gettraj()` can be called
107 | multiple times, it is common that the four methods will simply be called
108 | once in turn. To simplify that use case, the module also provides a single
109 | `runchomp()` method, which encapsulates handling of the run object for you,
110 | and returns the trajectory directly.
111 |
112 | ## Parameters
113 |
114 | The `orcdchomp` `create()` method (as well as the `runchomp()` helper)
115 | supports a large number of parameters to control the behavior of the
116 | optimizer. Below is a partial list.
117 |
118 | * `robot` (required): the robot object whose active dofs to use for planning
119 | * `adofgoal`: the goal dof values for the robot's active dofs (the current configuration is used for the start dof values)
120 | * `basegoal`: the goal pose of the base of the robot (for floating base optimization)
121 | * `floating_base`: whether to do floating base optimization
122 | * `lambda_`: the update rate of the optimizer
123 | * `starttraj`: the starting trajectory to use (defaults to a straight line in configuration space)
124 | * `n_points`: the number of moving points in the waypoint trajectory representation
125 | * `con_tsr`, `con_tsrs`: constraints to be respected (experimantal)
126 | * `start_tsr`: constraint to be respected at the start (deprecated)
127 | * `start_cost`: additional cost function callback for start configurations
128 | * `everyn_tsr`: a constraint to be respected at every `n` waypoints
129 | * `use_momentum`: whether to do second-order optimization (used with HMC)
130 | * `use_hmc`: whether to do Hamiltonian Monte-Carlo randomization
131 | * `hmc_resample_lambda`: the HMC resampling parameter
132 | * `seed`: the HMC random number generator seed
133 | * `epsilon`: the obstacle padding distance
134 | * `epsilon_self`: the self-collision padding distance
135 | * `obs_factor`: the coefficient for environment obstacle cost
136 | * `obs_factor_self`: the coefficient for self-collision obstacle cost
137 | * `no_report_cost`: whether to disable reporting costs at each iteration
138 | * `dat_filename`: a file to dump optimization data to
139 |
140 | ## Contributors
141 |
142 | `or_cdchomp` was primarily developed by Chris Dellin ()
143 | at the [Robotics Institute][ri] at [Carnegie Mellon University][cmu],
144 | both as a member of the [Personal Robotics Lab][pr] with
145 | [Sidd Srinivasa][srinivasa] and as a graduate student of
146 | [Chris Atkeson][atkeson]. Other significant contributions were made by Jen
147 | King, Michael Koval, and Anca Dragan.
148 |
149 | [ri]: https://www.ri.cmu.edu/
150 | [cmu]: http://www.cmu.edu/
151 | [pr]: https://personalrobotics.ri.cmu.edu/
152 | [srinivasa]: http://www.cs.cmu.edu/~siddh/
153 | [atkeson]: http://www.cs.cmu.edu/~cga/
154 | [CHOMP]: http://www.ri.cmu.edu/publication_view.html?pub_id=7421
155 | [OpenRAVE]: http://openrave.org/
156 | [libcd]: http://libcd.com/
157 |
158 |
159 |
160 |
161 |
162 |
163 |
--------------------------------------------------------------------------------
/catkin.cmake:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 2.8.3)
2 |
3 | find_package(catkin REQUIRED COMPONENTS openrave_catkin)
4 | catkin_package()
5 | catkin_python_setup()
6 |
7 | SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3")
8 |
9 | find_package(OpenRAVE REQUIRED)
10 | include_directories(${catkin_INCLUDE_DIRS})
11 |
12 | openrave_plugin("${PROJECT_NAME}_plugin"
13 | src/orcdchomp.cpp
14 | src/orcdchomp_mod.cpp
15 | src/orcdchomp_kdata.cpp
16 | src/orcwrap.cpp
17 | src/libcd/chomp.c
18 | src/libcd/grid.c
19 | src/libcd/grid_flood.c
20 | src/libcd/kin.c
21 | src/libcd/mat.c
22 | src/libcd/os.c
23 | src/libcd/spatial.c
24 | src/libcd/util.c
25 | src/libcd/util_shparse.c
26 | )
27 | target_link_libraries("${PROJECT_NAME}_plugin"
28 | blas
29 | lapacke
30 | lapack
31 | gsl
32 | ${catkin_LIBRARIES}
33 | )
34 |
--------------------------------------------------------------------------------
/license-gpl.txt:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 | Preamble
9 |
10 | The GNU General Public License is a free, copyleft license for
11 | software and other kinds of works.
12 |
13 | The licenses for most software and other practical works are designed
14 | to take away your freedom to share and change the works. By contrast,
15 | the GNU General Public License is intended to guarantee your freedom to
16 | share and change all versions of a program--to make sure it remains free
17 | software for all its users. We, the Free Software Foundation, use the
18 | GNU General Public License for most of our software; it applies also to
19 | any other work released this way by its authors. You can apply it to
20 | your programs, too.
21 |
22 | When we speak of free software, we are referring to freedom, not
23 | price. Our General Public Licenses are designed to make sure that you
24 | have the freedom to distribute copies of free software (and charge for
25 | them if you wish), that you receive source code or can get it if you
26 | want it, that you can change the software or use pieces of it in new
27 | free programs, and that you know you can do these things.
28 |
29 | To protect your rights, we need to prevent others from denying you
30 | these rights or asking you to surrender the rights. Therefore, you have
31 | certain responsibilities if you distribute copies of the software, or if
32 | you modify it: responsibilities to respect the freedom of others.
33 |
34 | For example, if you distribute copies of such a program, whether
35 | gratis or for a fee, you must pass on to the recipients the same
36 | freedoms that you received. You must make sure that they, too, receive
37 | or can get the source code. And you must show them these terms so they
38 | know their rights.
39 |
40 | Developers that use the GNU GPL protect your rights with two steps:
41 | (1) assert copyright on the software, and (2) offer you this License
42 | giving you legal permission to copy, distribute and/or modify it.
43 |
44 | For the developers' and authors' protection, the GPL clearly explains
45 | that there is no warranty for this free software. For both users' and
46 | authors' sake, the GPL requires that modified versions be marked as
47 | changed, so that their problems will not be attributed erroneously to
48 | authors of previous versions.
49 |
50 | Some devices are designed to deny users access to install or run
51 | modified versions of the software inside them, although the manufacturer
52 | can do so. This is fundamentally incompatible with the aim of
53 | protecting users' freedom to change the software. The systematic
54 | pattern of such abuse occurs in the area of products for individuals to
55 | use, which is precisely where it is most unacceptable. Therefore, we
56 | have designed this version of the GPL to prohibit the practice for those
57 | products. If such problems arise substantially in other domains, we
58 | stand ready to extend this provision to those domains in future versions
59 | of the GPL, as needed to protect the freedom of users.
60 |
61 | Finally, every program is threatened constantly by software patents.
62 | States should not allow patents to restrict development and use of
63 | software on general-purpose computers, but in those that do, we wish to
64 | avoid the special danger that patents applied to a free program could
65 | make it effectively proprietary. To prevent this, the GPL assures that
66 | patents cannot be used to render the program non-free.
67 |
68 | The precise terms and conditions for copying, distribution and
69 | modification follow.
70 |
71 | TERMS AND CONDITIONS
72 |
73 | 0. Definitions.
74 |
75 | "This License" refers to version 3 of the GNU General Public License.
76 |
77 | "Copyright" also means copyright-like laws that apply to other kinds of
78 | works, such as semiconductor masks.
79 |
80 | "The Program" refers to any copyrightable work licensed under this
81 | License. Each licensee is addressed as "you". "Licensees" and
82 | "recipients" may be individuals or organizations.
83 |
84 | To "modify" a work means to copy from or adapt all or part of the work
85 | in a fashion requiring copyright permission, other than the making of an
86 | exact copy. The resulting work is called a "modified version" of the
87 | earlier work or a work "based on" the earlier work.
88 |
89 | A "covered work" means either the unmodified Program or a work based
90 | on the Program.
91 |
92 | To "propagate" a work means to do anything with it that, without
93 | permission, would make you directly or secondarily liable for
94 | infringement under applicable copyright law, except executing it on a
95 | computer or modifying a private copy. Propagation includes copying,
96 | distribution (with or without modification), making available to the
97 | public, and in some countries other activities as well.
98 |
99 | To "convey" a work means any kind of propagation that enables other
100 | parties to make or receive copies. Mere interaction with a user through
101 | a computer network, with no transfer of a copy, is not conveying.
102 |
103 | An interactive user interface displays "Appropriate Legal Notices"
104 | to the extent that it includes a convenient and prominently visible
105 | feature that (1) displays an appropriate copyright notice, and (2)
106 | tells the user that there is no warranty for the work (except to the
107 | extent that warranties are provided), that licensees may convey the
108 | work under this License, and how to view a copy of this License. If
109 | the interface presents a list of user commands or options, such as a
110 | menu, a prominent item in the list meets this criterion.
111 |
112 | 1. Source Code.
113 |
114 | The "source code" for a work means the preferred form of the work
115 | for making modifications to it. "Object code" means any non-source
116 | form of a work.
117 |
118 | A "Standard Interface" means an interface that either is an official
119 | standard defined by a recognized standards body, or, in the case of
120 | interfaces specified for a particular programming language, one that
121 | is widely used among developers working in that language.
122 |
123 | The "System Libraries" of an executable work include anything, other
124 | than the work as a whole, that (a) is included in the normal form of
125 | packaging a Major Component, but which is not part of that Major
126 | Component, and (b) serves only to enable use of the work with that
127 | Major Component, or to implement a Standard Interface for which an
128 | implementation is available to the public in source code form. A
129 | "Major Component", in this context, means a major essential component
130 | (kernel, window system, and so on) of the specific operating system
131 | (if any) on which the executable work runs, or a compiler used to
132 | produce the work, or an object code interpreter used to run it.
133 |
134 | The "Corresponding Source" for a work in object code form means all
135 | the source code needed to generate, install, and (for an executable
136 | work) run the object code and to modify the work, including scripts to
137 | control those activities. However, it does not include the work's
138 | System Libraries, or general-purpose tools or generally available free
139 | programs which are used unmodified in performing those activities but
140 | which are not part of the work. For example, Corresponding Source
141 | includes interface definition files associated with source files for
142 | the work, and the source code for shared libraries and dynamically
143 | linked subprograms that the work is specifically designed to require,
144 | such as by intimate data communication or control flow between those
145 | subprograms and other parts of the work.
146 |
147 | The Corresponding Source need not include anything that users
148 | can regenerate automatically from other parts of the Corresponding
149 | Source.
150 |
151 | The Corresponding Source for a work in source code form is that
152 | same work.
153 |
154 | 2. Basic Permissions.
155 |
156 | All rights granted under this License are granted for the term of
157 | copyright on the Program, and are irrevocable provided the stated
158 | conditions are met. This License explicitly affirms your unlimited
159 | permission to run the unmodified Program. The output from running a
160 | covered work is covered by this License only if the output, given its
161 | content, constitutes a covered work. This License acknowledges your
162 | rights of fair use or other equivalent, as provided by copyright law.
163 |
164 | You may make, run and propagate covered works that you do not
165 | convey, without conditions so long as your license otherwise remains
166 | in force. You may convey covered works to others for the sole purpose
167 | of having them make modifications exclusively for you, or provide you
168 | with facilities for running those works, provided that you comply with
169 | the terms of this License in conveying all material for which you do
170 | not control copyright. Those thus making or running the covered works
171 | for you must do so exclusively on your behalf, under your direction
172 | and control, on terms that prohibit them from making any copies of
173 | your copyrighted material outside their relationship with you.
174 |
175 | Conveying under any other circumstances is permitted solely under
176 | the conditions stated below. Sublicensing is not allowed; section 10
177 | makes it unnecessary.
178 |
179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
180 |
181 | No covered work shall be deemed part of an effective technological
182 | measure under any applicable law fulfilling obligations under article
183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or
184 | similar laws prohibiting or restricting circumvention of such
185 | measures.
186 |
187 | When you convey a covered work, you waive any legal power to forbid
188 | circumvention of technological measures to the extent such circumvention
189 | is effected by exercising rights under this License with respect to
190 | the covered work, and you disclaim any intention to limit operation or
191 | modification of the work as a means of enforcing, against the work's
192 | users, your or third parties' legal rights to forbid circumvention of
193 | technological measures.
194 |
195 | 4. Conveying Verbatim Copies.
196 |
197 | You may convey verbatim copies of the Program's source code as you
198 | receive it, in any medium, provided that you conspicuously and
199 | appropriately publish on each copy an appropriate copyright notice;
200 | keep intact all notices stating that this License and any
201 | non-permissive terms added in accord with section 7 apply to the code;
202 | keep intact all notices of the absence of any warranty; and give all
203 | recipients a copy of this License along with the Program.
204 |
205 | You may charge any price or no price for each copy that you convey,
206 | and you may offer support or warranty protection for a fee.
207 |
208 | 5. Conveying Modified Source Versions.
209 |
210 | You may convey a work based on the Program, or the modifications to
211 | produce it from the Program, in the form of source code under the
212 | terms of section 4, provided that you also meet all of these conditions:
213 |
214 | a) The work must carry prominent notices stating that you modified
215 | it, and giving a relevant date.
216 |
217 | b) The work must carry prominent notices stating that it is
218 | released under this License and any conditions added under section
219 | 7. This requirement modifies the requirement in section 4 to
220 | "keep intact all notices".
221 |
222 | c) You must license the entire work, as a whole, under this
223 | License to anyone who comes into possession of a copy. This
224 | License will therefore apply, along with any applicable section 7
225 | additional terms, to the whole of the work, and all its parts,
226 | regardless of how they are packaged. This License gives no
227 | permission to license the work in any other way, but it does not
228 | invalidate such permission if you have separately received it.
229 |
230 | d) If the work has interactive user interfaces, each must display
231 | Appropriate Legal Notices; however, if the Program has interactive
232 | interfaces that do not display Appropriate Legal Notices, your
233 | work need not make them do so.
234 |
235 | A compilation of a covered work with other separate and independent
236 | works, which are not by their nature extensions of the covered work,
237 | and which are not combined with it such as to form a larger program,
238 | in or on a volume of a storage or distribution medium, is called an
239 | "aggregate" if the compilation and its resulting copyright are not
240 | used to limit the access or legal rights of the compilation's users
241 | beyond what the individual works permit. Inclusion of a covered work
242 | in an aggregate does not cause this License to apply to the other
243 | parts of the aggregate.
244 |
245 | 6. Conveying Non-Source Forms.
246 |
247 | You may convey a covered work in object code form under the terms
248 | of sections 4 and 5, provided that you also convey the
249 | machine-readable Corresponding Source under the terms of this License,
250 | in one of these ways:
251 |
252 | a) Convey the object code in, or embodied in, a physical product
253 | (including a physical distribution medium), accompanied by the
254 | Corresponding Source fixed on a durable physical medium
255 | customarily used for software interchange.
256 |
257 | b) Convey the object code in, or embodied in, a physical product
258 | (including a physical distribution medium), accompanied by a
259 | written offer, valid for at least three years and valid for as
260 | long as you offer spare parts or customer support for that product
261 | model, to give anyone who possesses the object code either (1) a
262 | copy of the Corresponding Source for all the software in the
263 | product that is covered by this License, on a durable physical
264 | medium customarily used for software interchange, for a price no
265 | more than your reasonable cost of physically performing this
266 | conveying of source, or (2) access to copy the
267 | Corresponding Source from a network server at no charge.
268 |
269 | c) Convey individual copies of the object code with a copy of the
270 | written offer to provide the Corresponding Source. This
271 | alternative is allowed only occasionally and noncommercially, and
272 | only if you received the object code with such an offer, in accord
273 | with subsection 6b.
274 |
275 | d) Convey the object code by offering access from a designated
276 | place (gratis or for a charge), and offer equivalent access to the
277 | Corresponding Source in the same way through the same place at no
278 | further charge. You need not require recipients to copy the
279 | Corresponding Source along with the object code. If the place to
280 | copy the object code is a network server, the Corresponding Source
281 | may be on a different server (operated by you or a third party)
282 | that supports equivalent copying facilities, provided you maintain
283 | clear directions next to the object code saying where to find the
284 | Corresponding Source. Regardless of what server hosts the
285 | Corresponding Source, you remain obligated to ensure that it is
286 | available for as long as needed to satisfy these requirements.
287 |
288 | e) Convey the object code using peer-to-peer transmission, provided
289 | you inform other peers where the object code and Corresponding
290 | Source of the work are being offered to the general public at no
291 | charge under subsection 6d.
292 |
293 | A separable portion of the object code, whose source code is excluded
294 | from the Corresponding Source as a System Library, need not be
295 | included in conveying the object code work.
296 |
297 | A "User Product" is either (1) a "consumer product", which means any
298 | tangible personal property which is normally used for personal, family,
299 | or household purposes, or (2) anything designed or sold for incorporation
300 | into a dwelling. In determining whether a product is a consumer product,
301 | doubtful cases shall be resolved in favor of coverage. For a particular
302 | product received by a particular user, "normally used" refers to a
303 | typical or common use of that class of product, regardless of the status
304 | of the particular user or of the way in which the particular user
305 | actually uses, or expects or is expected to use, the product. A product
306 | is a consumer product regardless of whether the product has substantial
307 | commercial, industrial or non-consumer uses, unless such uses represent
308 | the only significant mode of use of the product.
309 |
310 | "Installation Information" for a User Product means any methods,
311 | procedures, authorization keys, or other information required to install
312 | and execute modified versions of a covered work in that User Product from
313 | a modified version of its Corresponding Source. The information must
314 | suffice to ensure that the continued functioning of the modified object
315 | code is in no case prevented or interfered with solely because
316 | modification has been made.
317 |
318 | If you convey an object code work under this section in, or with, or
319 | specifically for use in, a User Product, and the conveying occurs as
320 | part of a transaction in which the right of possession and use of the
321 | User Product is transferred to the recipient in perpetuity or for a
322 | fixed term (regardless of how the transaction is characterized), the
323 | Corresponding Source conveyed under this section must be accompanied
324 | by the Installation Information. But this requirement does not apply
325 | if neither you nor any third party retains the ability to install
326 | modified object code on the User Product (for example, the work has
327 | been installed in ROM).
328 |
329 | The requirement to provide Installation Information does not include a
330 | requirement to continue to provide support service, warranty, or updates
331 | for a work that has been modified or installed by the recipient, or for
332 | the User Product in which it has been modified or installed. Access to a
333 | network may be denied when the modification itself materially and
334 | adversely affects the operation of the network or violates the rules and
335 | protocols for communication across the network.
336 |
337 | Corresponding Source conveyed, and Installation Information provided,
338 | in accord with this section must be in a format that is publicly
339 | documented (and with an implementation available to the public in
340 | source code form), and must require no special password or key for
341 | unpacking, reading or copying.
342 |
343 | 7. Additional Terms.
344 |
345 | "Additional permissions" are terms that supplement the terms of this
346 | License by making exceptions from one or more of its conditions.
347 | Additional permissions that are applicable to the entire Program shall
348 | be treated as though they were included in this License, to the extent
349 | that they are valid under applicable law. If additional permissions
350 | apply only to part of the Program, that part may be used separately
351 | under those permissions, but the entire Program remains governed by
352 | this License without regard to the additional permissions.
353 |
354 | When you convey a copy of a covered work, you may at your option
355 | remove any additional permissions from that copy, or from any part of
356 | it. (Additional permissions may be written to require their own
357 | removal in certain cases when you modify the work.) You may place
358 | additional permissions on material, added by you to a covered work,
359 | for which you have or can give appropriate copyright permission.
360 |
361 | Notwithstanding any other provision of this License, for material you
362 | add to a covered work, you may (if authorized by the copyright holders of
363 | that material) supplement the terms of this License with terms:
364 |
365 | a) Disclaiming warranty or limiting liability differently from the
366 | terms of sections 15 and 16 of this License; or
367 |
368 | b) Requiring preservation of specified reasonable legal notices or
369 | author attributions in that material or in the Appropriate Legal
370 | Notices displayed by works containing it; or
371 |
372 | c) Prohibiting misrepresentation of the origin of that material, or
373 | requiring that modified versions of such material be marked in
374 | reasonable ways as different from the original version; or
375 |
376 | d) Limiting the use for publicity purposes of names of licensors or
377 | authors of the material; or
378 |
379 | e) Declining to grant rights under trademark law for use of some
380 | trade names, trademarks, or service marks; or
381 |
382 | f) Requiring indemnification of licensors and authors of that
383 | material by anyone who conveys the material (or modified versions of
384 | it) with contractual assumptions of liability to the recipient, for
385 | any liability that these contractual assumptions directly impose on
386 | those licensors and authors.
387 |
388 | All other non-permissive additional terms are considered "further
389 | restrictions" within the meaning of section 10. If the Program as you
390 | received it, or any part of it, contains a notice stating that it is
391 | governed by this License along with a term that is a further
392 | restriction, you may remove that term. If a license document contains
393 | a further restriction but permits relicensing or conveying under this
394 | License, you may add to a covered work material governed by the terms
395 | of that license document, provided that the further restriction does
396 | not survive such relicensing or conveying.
397 |
398 | If you add terms to a covered work in accord with this section, you
399 | must place, in the relevant source files, a statement of the
400 | additional terms that apply to those files, or a notice indicating
401 | where to find the applicable terms.
402 |
403 | Additional terms, permissive or non-permissive, may be stated in the
404 | form of a separately written license, or stated as exceptions;
405 | the above requirements apply either way.
406 |
407 | 8. Termination.
408 |
409 | You may not propagate or modify a covered work except as expressly
410 | provided under this License. Any attempt otherwise to propagate or
411 | modify it is void, and will automatically terminate your rights under
412 | this License (including any patent licenses granted under the third
413 | paragraph of section 11).
414 |
415 | However, if you cease all violation of this License, then your
416 | license from a particular copyright holder is reinstated (a)
417 | provisionally, unless and until the copyright holder explicitly and
418 | finally terminates your license, and (b) permanently, if the copyright
419 | holder fails to notify you of the violation by some reasonable means
420 | prior to 60 days after the cessation.
421 |
422 | Moreover, your license from a particular copyright holder is
423 | reinstated permanently if the copyright holder notifies you of the
424 | violation by some reasonable means, this is the first time you have
425 | received notice of violation of this License (for any work) from that
426 | copyright holder, and you cure the violation prior to 30 days after
427 | your receipt of the notice.
428 |
429 | Termination of your rights under this section does not terminate the
430 | licenses of parties who have received copies or rights from you under
431 | this License. If your rights have been terminated and not permanently
432 | reinstated, you do not qualify to receive new licenses for the same
433 | material under section 10.
434 |
435 | 9. Acceptance Not Required for Having Copies.
436 |
437 | You are not required to accept this License in order to receive or
438 | run a copy of the Program. Ancillary propagation of a covered work
439 | occurring solely as a consequence of using peer-to-peer transmission
440 | to receive a copy likewise does not require acceptance. However,
441 | nothing other than this License grants you permission to propagate or
442 | modify any covered work. These actions infringe copyright if you do
443 | not accept this License. Therefore, by modifying or propagating a
444 | covered work, you indicate your acceptance of this License to do so.
445 |
446 | 10. Automatic Licensing of Downstream Recipients.
447 |
448 | Each time you convey a covered work, the recipient automatically
449 | receives a license from the original licensors, to run, modify and
450 | propagate that work, subject to this License. You are not responsible
451 | for enforcing compliance by third parties with this License.
452 |
453 | An "entity transaction" is a transaction transferring control of an
454 | organization, or substantially all assets of one, or subdividing an
455 | organization, or merging organizations. If propagation of a covered
456 | work results from an entity transaction, each party to that
457 | transaction who receives a copy of the work also receives whatever
458 | licenses to the work the party's predecessor in interest had or could
459 | give under the previous paragraph, plus a right to possession of the
460 | Corresponding Source of the work from the predecessor in interest, if
461 | the predecessor has it or can get it with reasonable efforts.
462 |
463 | You may not impose any further restrictions on the exercise of the
464 | rights granted or affirmed under this License. For example, you may
465 | not impose a license fee, royalty, or other charge for exercise of
466 | rights granted under this License, and you may not initiate litigation
467 | (including a cross-claim or counterclaim in a lawsuit) alleging that
468 | any patent claim is infringed by making, using, selling, offering for
469 | sale, or importing the Program or any portion of it.
470 |
471 | 11. Patents.
472 |
473 | A "contributor" is a copyright holder who authorizes use under this
474 | License of the Program or a work on which the Program is based. The
475 | work thus licensed is called the contributor's "contributor version".
476 |
477 | A contributor's "essential patent claims" are all patent claims
478 | owned or controlled by the contributor, whether already acquired or
479 | hereafter acquired, that would be infringed by some manner, permitted
480 | by this License, of making, using, or selling its contributor version,
481 | but do not include claims that would be infringed only as a
482 | consequence of further modification of the contributor version. For
483 | purposes of this definition, "control" includes the right to grant
484 | patent sublicenses in a manner consistent with the requirements of
485 | this License.
486 |
487 | Each contributor grants you a non-exclusive, worldwide, royalty-free
488 | patent license under the contributor's essential patent claims, to
489 | make, use, sell, offer for sale, import and otherwise run, modify and
490 | propagate the contents of its contributor version.
491 |
492 | In the following three paragraphs, a "patent license" is any express
493 | agreement or commitment, however denominated, not to enforce a patent
494 | (such as an express permission to practice a patent or covenant not to
495 | sue for patent infringement). To "grant" such a patent license to a
496 | party means to make such an agreement or commitment not to enforce a
497 | patent against the party.
498 |
499 | If you convey a covered work, knowingly relying on a patent license,
500 | and the Corresponding Source of the work is not available for anyone
501 | to copy, free of charge and under the terms of this License, through a
502 | publicly available network server or other readily accessible means,
503 | then you must either (1) cause the Corresponding Source to be so
504 | available, or (2) arrange to deprive yourself of the benefit of the
505 | patent license for this particular work, or (3) arrange, in a manner
506 | consistent with the requirements of this License, to extend the patent
507 | license to downstream recipients. "Knowingly relying" means you have
508 | actual knowledge that, but for the patent license, your conveying the
509 | covered work in a country, or your recipient's use of the covered work
510 | in a country, would infringe one or more identifiable patents in that
511 | country that you have reason to believe are valid.
512 |
513 | If, pursuant to or in connection with a single transaction or
514 | arrangement, you convey, or propagate by procuring conveyance of, a
515 | covered work, and grant a patent license to some of the parties
516 | receiving the covered work authorizing them to use, propagate, modify
517 | or convey a specific copy of the covered work, then the patent license
518 | you grant is automatically extended to all recipients of the covered
519 | work and works based on it.
520 |
521 | A patent license is "discriminatory" if it does not include within
522 | the scope of its coverage, prohibits the exercise of, or is
523 | conditioned on the non-exercise of one or more of the rights that are
524 | specifically granted under this License. You may not convey a covered
525 | work if you are a party to an arrangement with a third party that is
526 | in the business of distributing software, under which you make payment
527 | to the third party based on the extent of your activity of conveying
528 | the work, and under which the third party grants, to any of the
529 | parties who would receive the covered work from you, a discriminatory
530 | patent license (a) in connection with copies of the covered work
531 | conveyed by you (or copies made from those copies), or (b) primarily
532 | for and in connection with specific products or compilations that
533 | contain the covered work, unless you entered into that arrangement,
534 | or that patent license was granted, prior to 28 March 2007.
535 |
536 | Nothing in this License shall be construed as excluding or limiting
537 | any implied license or other defenses to infringement that may
538 | otherwise be available to you under applicable patent law.
539 |
540 | 12. No Surrender of Others' Freedom.
541 |
542 | If conditions are imposed on you (whether by court order, agreement or
543 | otherwise) that contradict the conditions of this License, they do not
544 | excuse you from the conditions of this License. If you cannot convey a
545 | covered work so as to satisfy simultaneously your obligations under this
546 | License and any other pertinent obligations, then as a consequence you may
547 | not convey it at all. For example, if you agree to terms that obligate you
548 | to collect a royalty for further conveying from those to whom you convey
549 | the Program, the only way you could satisfy both those terms and this
550 | License would be to refrain entirely from conveying the Program.
551 |
552 | 13. Use with the GNU Affero General Public License.
553 |
554 | Notwithstanding any other provision of this License, you have
555 | permission to link or combine any covered work with a work licensed
556 | under version 3 of the GNU Affero General Public License into a single
557 | combined work, and to convey the resulting work. The terms of this
558 | License will continue to apply to the part which is the covered work,
559 | but the special requirements of the GNU Affero General Public License,
560 | section 13, concerning interaction through a network will apply to the
561 | combination as such.
562 |
563 | 14. Revised Versions of this License.
564 |
565 | The Free Software Foundation may publish revised and/or new versions of
566 | the GNU General Public License from time to time. Such new versions will
567 | be similar in spirit to the present version, but may differ in detail to
568 | address new problems or concerns.
569 |
570 | Each version is given a distinguishing version number. If the
571 | Program specifies that a certain numbered version of the GNU General
572 | Public License "or any later version" applies to it, you have the
573 | option of following the terms and conditions either of that numbered
574 | version or of any later version published by the Free Software
575 | Foundation. If the Program does not specify a version number of the
576 | GNU General Public License, you may choose any version ever published
577 | by the Free Software Foundation.
578 |
579 | If the Program specifies that a proxy can decide which future
580 | versions of the GNU General Public License can be used, that proxy's
581 | public statement of acceptance of a version permanently authorizes you
582 | to choose that version for the Program.
583 |
584 | Later license versions may give you additional or different
585 | permissions. However, no additional obligations are imposed on any
586 | author or copyright holder as a result of your choosing to follow a
587 | later version.
588 |
589 | 15. Disclaimer of Warranty.
590 |
591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
599 |
600 | 16. Limitation of Liability.
601 |
602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
610 | SUCH DAMAGES.
611 |
612 | 17. Interpretation of Sections 15 and 16.
613 |
614 | If the disclaimer of warranty and limitation of liability provided
615 | above cannot be given local legal effect according to their terms,
616 | reviewing courts shall apply local law that most closely approximates
617 | an absolute waiver of all civil liability in connection with the
618 | Program, unless a warranty or assumption of liability accompanies a
619 | copy of the Program in return for a fee.
620 |
621 | END OF TERMS AND CONDITIONS
622 |
623 | How to Apply These Terms to Your New Programs
624 |
625 | If you develop a new program, and you want it to be of the greatest
626 | possible use to the public, the best way to achieve this is to make it
627 | free software which everyone can redistribute and change under these terms.
628 |
629 | To do so, attach the following notices to the program. It is safest
630 | to attach them to the start of each source file to most effectively
631 | state the exclusion of warranty; and each file should have at least
632 | the "copyright" line and a pointer to where the full notice is found.
633 |
634 |
635 | Copyright (C)
636 |
637 | This program is free software: you can redistribute it and/or modify
638 | it under the terms of the GNU General Public License as published by
639 | the Free Software Foundation, either version 3 of the License, or
640 | (at your option) any later version.
641 |
642 | This program is distributed in the hope that it will be useful,
643 | but WITHOUT ANY WARRANTY; without even the implied warranty of
644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
645 | GNU General Public License for more details.
646 |
647 | You should have received a copy of the GNU General Public License
648 | along with this program. If not, see .
649 |
650 | Also add information on how to contact you by electronic and paper mail.
651 |
652 | If the program does terminal interaction, make it output a short
653 | notice like this when it starts in an interactive mode:
654 |
655 | Copyright (C)
656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
657 | This is free software, and you are welcome to redistribute it
658 | under certain conditions; type `show c' for details.
659 |
660 | The hypothetical commands `show w' and `show c' should show the appropriate
661 | parts of the General Public License. Of course, your program's commands
662 | might be different; for a GUI interface, you would use an "about box".
663 |
664 | You should also get your employer (if you work as a programmer) or school,
665 | if any, to sign a "copyright disclaimer" for the program, if necessary.
666 | For more information on this, and how to apply and follow the GNU GPL, see
667 | .
668 |
669 | The GNU General Public License does not permit incorporating your program
670 | into proprietary programs. If your program is a subroutine library, you
671 | may consider it more useful to permit linking proprietary applications with
672 | the library. If this is what you want to do, use the GNU Lesser General
673 | Public License instead of this License. But first, please read
674 | .
675 |
--------------------------------------------------------------------------------
/package.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | or_cdchomp
4 | 1.0.2
5 |
6 | OpenRAVE plugin that implements the CHOMP trajectory optimizer using libcd.
7 |
8 | https://github.com/personalrobotics/orcdchomp
9 | Christopher Dellin
10 | Christopher Dellin
11 | BSD
12 | catkin
13 | atlas
14 | libblas-dev
15 | liblapacke
16 | libgsl
17 | openrave_catkin
18 | atlas
19 | liblapacke
20 | libgsl
21 | openrave_catkin
22 |
23 |
--------------------------------------------------------------------------------
/pythonsrc/orcdchomp/__init__.py:
--------------------------------------------------------------------------------
1 | from orcdchomp import *
2 |
--------------------------------------------------------------------------------
/pythonsrc/orcdchomp/orcdchomp.py:
--------------------------------------------------------------------------------
1 | # \file orcdchomp.py
2 | # \brief Python interface to orcdchomp.
3 | # \author Christopher Dellin
4 | # \date 2012-2013
5 |
6 | # (C) Copyright 2012-2013 Carnegie Mellon University
7 |
8 | # This module (orcdchomp) is part of libcd.
9 | #
10 | # This module of libcd is free software: you can redistribute it
11 | # and/or modify it under the terms of the GNU General Public License as
12 | # published by the Free Software Foundation, either version 3 of the
13 | # License, or (at your option) any later version.
14 | #
15 | # This module of libcd is distributed in the hope that it will be
16 | # useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
17 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 | # GNU General Public License for more details.
19 | #
20 | # A copy of the GNU General Public License is provided with libcd
21 | # (license-gpl.txt) and is also available at .
22 |
23 |
24 | import types
25 | import openravepy
26 |
27 | def bind(mod):
28 | mod.viewspheres = types.MethodType(viewspheres,mod)
29 | mod.computedistancefield = types.MethodType(computedistancefield,mod)
30 | mod.addfield_fromobsarray = types.MethodType(addfield_fromobsarray,mod)
31 | mod.viewfields = types.MethodType(viewfields,mod)
32 | mod.removefield = types.MethodType(removefield,mod)
33 | mod.create = types.MethodType(create,mod)
34 | mod.iterate = types.MethodType(iterate,mod)
35 | mod.gettraj = types.MethodType(gettraj,mod)
36 | mod.destroy = types.MethodType(destroy,mod)
37 | mod.runchomp = types.MethodType(runchomp,mod)
38 |
39 | def shquot(s):
40 | return "'" + s.replace("'","'\\''") + "'"
41 |
42 | def viewspheres(mod, robot=None, releasegil=False):
43 | cmd = 'viewspheres'
44 | if robot is not None:
45 | if hasattr(robot,'GetName'):
46 | cmd += ' robot %s' % shquot(robot.GetName())
47 | else:
48 | cmd += ' robot %s' % shquot(robot)
49 | print 'cmd:', cmd
50 | return mod.SendCommand(cmd, releasegil)
51 |
52 | def computedistancefield(mod, kinbody=None, cube_extent=None, aabb_padding=None,
53 | cache_filename=None, require_cache=None, releasegil=False):
54 | cmd = 'computedistancefield'
55 | if kinbody is not None:
56 | if hasattr(kinbody,'GetName'):
57 | cmd += ' kinbody %s' % shquot(kinbody.GetName())
58 | else:
59 | cmd += ' kinbody %s' % shquot(kinbody)
60 | if cube_extent is not None:
61 | cmd += ' cube_extent %f' % cube_extent
62 | if aabb_padding is not None:
63 | cmd += ' aabb_padding %f' % aabb_padding
64 | if cache_filename is not None:
65 | cmd += ' cache_filename %s' % shquot(cache_filename)
66 | if require_cache is not None and require_cache:
67 | cmd += ' require_cache'
68 | print 'cmd:', cmd
69 | return mod.SendCommand(cmd, releasegil)
70 |
71 | def addfield_fromobsarray(mod, kinbody=None, obsarray=None, sizes=None, lengths=None,
72 | pose=None, releasegil=False):
73 | cmd = 'addfield_fromobsarray'
74 | if kinbody is not None:
75 | if hasattr(kinbody,'GetName'):
76 | cmd += ' kinbody %s' % shquot(kinbody.GetName())
77 | else:
78 | cmd += ' kinbody %s' % shquot(kinbody)
79 | if obsarray is not None:
80 | cmd += ' obsarray %s' % obsarray
81 | if sizes is not None:
82 | cmd += ' sizes %s' % shquot(' '.join([str(v) for v in sizes]))
83 | if lengths is not None:
84 | cmd += ' lengths %s' % shquot(' '.join([str(v) for v in lengths]))
85 | if pose is not None:
86 | cmd += ' pose %s' % shquot(' '.join([str(v) for v in pose]))
87 | print 'cmd:', cmd
88 | return mod.SendCommand(cmd, releasegil)
89 |
90 | def viewfields(mod, releasegil=False):
91 | cmd = 'viewfields'
92 | print 'cmd:', cmd
93 | return mod.SendCommand(cmd, releasegil)
94 |
95 | def removefield(mod, kinbody=None, releasegil=False):
96 | cmd = 'removefield'
97 | if kinbody is not None:
98 | if hasattr(kinbody,'GetName'):
99 | cmd += ' kinbody %s' % shquot(kinbody.GetName())
100 | else:
101 | cmd += ' kinbody %s' % shquot(kinbody)
102 | print 'cmd:', cmd
103 | return mod.SendCommand(cmd, releasegil)
104 |
105 | def create(mod, robot=None, adofgoal=None, basegoal=None, floating_base=None, lambda_=None,
106 | starttraj=None, n_points=None,
107 | con_tsr=None, con_tsrs=None, start_tsr=None, start_cost=None, everyn_tsr=None,
108 | use_momentum=None, use_hmc=None, hmc_resample_lambda=None, seed=None,
109 | epsilon=None, epsilon_self=None, obs_factor=None, obs_factor_self=None,
110 | no_report_cost=None, dat_filename=None, releasegil=False, derivative=None, **kwargs):
111 | cmd = 'create'
112 | if robot is not None:
113 | if hasattr(robot,'GetName'):
114 | cmd += ' robot %s' % shquot(robot.GetName())
115 | else:
116 | cmd += ' robot %s' % shquot(robot)
117 | if adofgoal is not None:
118 | cmd += ' adofgoal %s' % shquot(' '.join([str(v) for v in adofgoal]))
119 | if basegoal is not None:
120 | cmd += ' basegoal %s' % shquot(' '.join([str(v) for v in basegoal]))
121 | if floating_base is not None and floating_base:
122 | cmd += ' floating_base'
123 | if lambda_ is not None:
124 | cmd += ' lambda %0.04f' % lambda_
125 | if starttraj is not None:
126 | in_traj_data = starttraj.serialize(0) # options
127 | cmd += ' starttraj %s' % shquot(in_traj_data)
128 | if n_points is not None:
129 | cmd += ' n_points %d' % n_points
130 | if con_tsr is not None:
131 | cmd += ' con_tsr \'%s\' \'%s\'' % (con_tsr[0], con_tsr[1].serialize())
132 | if con_tsrs is not None:
133 | for sub_con_tsr in con_tsrs:
134 | cmd += ' con_tsr \'%s\' \'%s\'' % (sub_con_tsr[0], sub_con_tsr[1].serialize())
135 | if derivative is not None:
136 | cmd += ' derivative %d' % derivative
137 | if start_tsr is not None:
138 | cmd += ' start_tsr \'%s\'' % start_tsr.serialize()
139 | if start_cost is not None:
140 | if isinstance(start_cost, str):
141 | cmd += ' start_cost \'%s\'' % start_cost
142 | else:
143 | cmd += ' start_cost \'%s %s\'' % (start_cost[0], start_cost[1])
144 | if everyn_tsr is not None:
145 | cmd += ' everyn_tsr \'%s\'' % everyn_tsr.serialize()
146 | if use_momentum is not None and use_momentum:
147 | cmd += ' use_momentum'
148 | if use_hmc is not None and use_hmc:
149 | cmd += ' use_hmc'
150 | if hmc_resample_lambda is not None:
151 | cmd += ' hmc_resample_lambda %f' % hmc_resample_lambda
152 | if seed is not None:
153 | cmd += ' seed %d' % seed
154 | if epsilon is not None:
155 | cmd += ' epsilon %f' % epsilon
156 | if epsilon_self is not None:
157 | cmd += ' epsilon_self %f' % epsilon_self
158 | if obs_factor is not None:
159 | cmd += ' obs_factor %f' % obs_factor
160 | if obs_factor_self is not None:
161 | cmd += ' obs_factor_self %f' % obs_factor_self
162 | if no_report_cost is not None and no_report_cost:
163 | cmd += ' no_report_cost'
164 | if dat_filename is not None:
165 | cmd += ' dat_filename %s' % shquot(dat_filename)
166 | print 'cmd:', cmd
167 | return mod.SendCommand(cmd, releasegil)
168 |
169 | def iterate(mod, run=None, n_iter=None, max_time=None, trajs_fileformstr=None,
170 | cost=None, releasegil=False):
171 | cmd = 'iterate'
172 | if run is not None:
173 | cmd += ' run %s' % run
174 | if n_iter is not None:
175 | cmd += ' n_iter %d' % n_iter
176 | if max_time is not None:
177 | cmd += ' max_time %f' % max_time
178 | if trajs_fileformstr is not None:
179 | cmd += ' trajs_fileformstr %s' % shquot(trajs_fileformstr)
180 | cost_data = mod.SendCommand(cmd, releasegil)
181 | if cost is not None:
182 | cost[0] = float(cost_data)
183 |
184 | def gettraj(mod, run=None, no_collision_check=None, no_collision_exception=None,
185 | no_collision_details=None, releasegil=False):
186 | cmd = 'gettraj'
187 | if run is not None:
188 | cmd += ' run %s' % run
189 | if no_collision_check is not None and no_collision_check:
190 | cmd += ' no_collision_check'
191 | if no_collision_exception is not None and no_collision_exception:
192 | cmd += ' no_collision_exception'
193 | if no_collision_details is not None and no_collision_details:
194 | cmd += ' no_collision_details'
195 | out_traj_data = mod.SendCommand(cmd, releasegil)
196 | return openravepy.RaveCreateTrajectory(mod.GetEnv(),'').deserialize(out_traj_data)
197 |
198 | def destroy(mod, run=None, releasegil=False):
199 | cmd = 'destroy'
200 | if run is not None:
201 | cmd += ' run %s' % run
202 | return mod.SendCommand(cmd, releasegil)
203 |
204 | def runchomp(mod,
205 | # iterate args
206 | n_iter=None, max_time=None, trajs_fileformstr=None, cost=None,
207 | # gettraj args
208 | no_collision_check=None, no_collision_exception=None, no_collision_details=None,
209 | releasegil=False, **kwargs):
210 | # pass unknown args to create
211 | run = create(mod, releasegil=releasegil, **kwargs)
212 | iterate(mod, run=run, n_iter=n_iter, max_time=max_time, trajs_fileformstr=trajs_fileformstr, cost=cost, releasegil=releasegil)
213 | traj = gettraj(mod, run=run,
214 | no_collision_check=no_collision_check,
215 | no_collision_exception=no_collision_exception,
216 | no_collision_details=no_collision_details,
217 | releasegil=releasegil)
218 | destroy(mod, run=run, releasegil=releasegil)
219 | return traj
220 |
--------------------------------------------------------------------------------
/rosbuild.cmake:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 2.4.6)
2 | include($ENV{ROS_ROOT}/core/rosbuild/rosbuild.cmake)
3 | rosbuild_init()
4 | set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
5 | set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
6 |
7 | SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3")
8 |
9 | rosbuild_add_library(orcdchomp
10 | src/orcdchomp.cpp
11 | src/orcdchomp_mod.cpp
12 | src/orcdchomp_kdata.cpp
13 | src/orcwrap.cpp
14 | src/libcd/chomp.c
15 | src/libcd/grid.c
16 | src/libcd/grid_flood.c
17 | src/libcd/kin.c
18 | src/libcd/mat.c
19 | src/libcd/os.c
20 | src/libcd/spatial.c
21 | src/libcd/util.c
22 | src/libcd/util_shparse.c)
23 | target_link_libraries(orcdchomp blas lapacke lapack gsl)
24 |
--------------------------------------------------------------------------------
/scripts/barrettwam_withspheres.robot.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | wam7
12 |
13 |
14 | wam7
15 | handbase
16 | 0 0
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 | wam0
52 | wam7
53 | WAM7ikfast 0.05
54 | 0 0 0.22
55 | JF1 JF2 JF3 JF4
56 | 1 1 1 0
57 | 0 0 1
58 |
59 |
60 |
--------------------------------------------------------------------------------
/scripts/test_wam7.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | import atexit
3 | import math
4 | import numpy
5 | import openravepy
6 | import orcdchomp.orcdchomp
7 |
8 | # start openrave
9 | openravepy.RaveInitialize(True, level=openravepy.DebugLevel.Info)
10 | atexit.register(openravepy.RaveDestroy)
11 | e = openravepy.Environment()
12 | atexit.register(e.Destroy)
13 |
14 | e.SetViewer('qtcoin')
15 |
16 | # load the orcdchomp module
17 | m_chomp = openravepy.RaveCreateModule(e, 'orcdchomp')
18 | if not m_chomp:
19 | raise RuntimeError('no chomp module found!')
20 | orcdchomp.orcdchomp.bind(m_chomp)
21 |
22 | # table
23 | table = e.ReadKinBodyXMLFile('models/furniture/rolly-table.iv')
24 | e.Add(table)
25 | table.SetTransform([0.70711,0.70711,0,0,0,0,0])
26 |
27 | # bottle (and its grasp)
28 | mug = e.ReadKinBodyXMLFile('models/objects/mug3.iv')
29 | e.Add(mug)
30 | mug.SetTransform([1,0,0,0,0,0,0.7])
31 | T_mug_palm = numpy.array(
32 | [[ 0, -1, 0, 0.000 ],
33 | [ 0, 0, -1, 0.075 ],
34 | [ 1, 0, 0, 0.100 ],
35 | [ 0, 0, 0, 1 ]])
36 |
37 | # robot
38 | r = e.ReadRobotXMLFile('barrettwam_withspheres.robot.xml')
39 | e.Add(r)
40 | r.SetTransform([0.70711,0,0.70711,0,-1.0,0,1.0])
41 |
42 | # set up active manip, active dofs
43 | r.SetActiveManipulator('arm')
44 | m = r.GetActiveManipulator()
45 | ikmodel = openravepy.databases.inversekinematics.InverseKinematicsModel(r,
46 | iktype=openravepy.IkParameterization.Type.Transform6D)
47 | if not ikmodel.load():
48 | ikmodel.autogenerate()
49 | r.SetActiveDOFs(m.GetArmIndices())
50 | T_palm_ee = numpy.array(
51 | [[ 1., 0., 0., 0. ],
52 | [ 0., 1., 0., 0. ],
53 | [ 0., 0., 1., 0.125 ],
54 | [ 0., 0., 0., 1. ]])
55 |
56 | # get IK solution for bottle
57 | T_ee = reduce(numpy.dot, [
58 | mug.GetTransform(),
59 | numpy.linalg.inv(T_mug_palm),
60 | T_palm_ee])
61 |
62 | q_goal = m.FindIKSolution(T_ee, 0)
63 | print('q_goal:', q_goal)
64 |
65 | # set starting arm configuration
66 | r.SetActiveDOFValues([2.5,-1.8,0.0,2.0,0.0,0.2,0.0])
67 |
68 | raw_input('Press [Enter] to view spheres ...')
69 | m_chomp.viewspheres(robot=r)
70 | raw_input('Press [Enter] to clear spheres ...')
71 | for b in e.GetBodies():
72 | if b.GetName().startswith('orcdchomp_sphere_'):
73 | e.Remove(b)
74 |
75 | # disable the robot to compute the distance field for all other objects ...
76 | raw_input('Press [Enter] compute robot distance field ...')
77 | r.Enable(False)
78 | m_chomp.computedistancefield(kinbody=r,cache_filename='sdf_tablemug.dat')
79 | r.Enable(True)
80 |
81 | raw_input('Press [Enter] run chomp ...')
82 | try:
83 | t = m_chomp.runchomp(robot=r, n_iter=100, lambda_=100.0, obs_factor=500.0,
84 | adofgoal=q_goal, no_collision_exception=True)
85 | except RuntimeError as ex:
86 | print ex
87 | t = None
88 |
89 | try:
90 | while t is not None:
91 | raw_input('Press [Enter] to run the trajectory, [Ctrl]+[C] to quit ...')
92 | with e:
93 | r.GetController().SetPath(t)
94 | except KeyboardInterrupt:
95 | print
96 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | from distutils.core import setup
3 | from catkin_pkg.python_setup import generate_distutils_setup
4 |
5 | d = generate_distutils_setup(
6 | packages=['orcdchomp'],
7 | package_dir={'': 'pythonsrc'},
8 | )
9 | setup(**d)
10 |
--------------------------------------------------------------------------------
/src/libcd/chomp.c:
--------------------------------------------------------------------------------
1 | /** \file chomp.c
2 | * \brief Implementation of cd_chomp, a version of CHOMP (Covariant
3 | * Hamiltonian Optimization for Motion Planning), a trajectory
4 | * optimizer developed by Nathan Ratliff, Matthew Zucker,
5 | * J. Andrew Bagnell, and Siddhartha Srinivasa.
6 | * \author Christopher Dellin
7 | * \date 2011-02-21 CD: File created.
8 | */
9 |
10 | /* (C) Copyright 2011-2013 Carnegie Mellon University */
11 |
12 | /* This module (cd_chomp) is part of libcd.
13 | *
14 | * This module of libcd is free software: you can redistribute it
15 | * and/or modify it under the terms of the GNU General Public License as
16 | * published by the Free Software Foundation, either version 3 of the
17 | * License, or (at your option) any later version.
18 | *
19 | * This module of libcd is distributed in the hope that it will be
20 | * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 | * GNU General Public License for more details.
23 | *
24 | * A copy of the GNU General Public License is provided with libcd
25 | * (license-gpl.txt) and is also available at .
26 | */
27 |
28 | //#define DEBUG_TIMING
29 |
30 | #include
31 | #include
32 | #include
33 | #include /* requires POSIX.1b struct timespec */
34 | #include
35 | #include
36 | #include "mat.h"
37 | #include "os.h"
38 | #include "chomp.h"
39 |
40 | int cd_chomp_create(struct cd_chomp ** cp, int m, int n, int D, double * T, int ldt)
41 | {
42 | struct cd_chomp * c;
43 | int i;
44 |
45 | /* Allocate structure */
46 | c = (struct cd_chomp *) malloc(sizeof(struct cd_chomp));
47 | if (!c) return -1;
48 | c->n = n;
49 | c->m = m;
50 | c->lambda = 1.0;
51 | c->dt = 1.0/(m+1);
52 | c->T = T;
53 | c->ldt = ldt;
54 | c->T_points = 0;
55 | c->G = 0;
56 | c->G_points = 0;
57 | c->AG = 0;
58 | c->AG_points = 0;
59 | c->D = D;
60 | c->wds = 0;
61 | c->inits = 0;
62 | c->finals = 0;
63 | c->A = 0;
64 | c->Ainv = 0;
65 | c->B = 0;
66 | c->jlimit_lower = 0;
67 | c->jlimit_upper = 0;
68 | c->cost_nxn = 0;
69 | c->cost_mxn = 0;
70 | c->Kvels = 0;
71 | c->Evels = 0;
72 | c->vels = 0;
73 | c->Gjlimit = 0;
74 | c->GjlimitAinv = 0;
75 | c->cptr = 0;
76 | c->cost_pre = 0;
77 | c->cost = 0;
78 | c->cost_extra = 0;
79 | c->use_momentum = 0;
80 | c->leapfrog_first = 1;
81 | cd_os_timespec_set_zero(&c->ticks_vels);
82 | cd_os_timespec_set_zero(&c->ticks_callback_pre);
83 | cd_os_timespec_set_zero(&c->ticks_callbacks);
84 | cd_os_timespec_set_zero(&c->ticks_smoothgrad);
85 | cd_os_timespec_set_zero(&c->ticks_smoothcost);
86 | /* constraint stuff */
87 | c->cons = 0;
88 | c->cons_k = 0;
89 | c->cons_h = 0;
90 | c->cons_Jcol = 0;
91 | c->cons_JAJT = 0;
92 | c->cons_ipiv = 0;
93 | c->cons_delta = 0;
94 |
95 | /* Allocate T_points pointers */
96 | c->T_points = (double **) malloc(m * sizeof(double *));
97 | if (!c->T_points) { cd_chomp_free(c); return -1; }
98 | for (i=0; iT_points[i] = &c->T[i*ldt];
100 |
101 | /* Allocate gradient */
102 | c->G = (double *) malloc(m * n * sizeof(double));
103 | c->G_points = (double **) malloc(m * sizeof(double *));
104 | if (!c->G || !c->G_points) { cd_chomp_free(c); return -1; }
105 | for (i=0; iG_points[i] = &c->G[i*n];
107 |
108 | /* Allocate Ainv-spread gradient (also momentum) */
109 | c->AG = (double *) malloc(m * n * sizeof(double));
110 | c->AG_points = (double **) malloc(m * sizeof(double *));
111 | if (!c->AG || !c->AG_points) { cd_chomp_free(c); return -1; }
112 | for (i=0; iAG_points[i] = &c->AG[i*n];
114 | for (i=0; iAG[i] = 0.0;
116 |
117 | /* wds SHOULD BE CALCULATED IN init! */
118 |
119 | /* Allocate wds */
120 | if (D)
121 | {
122 | c->wds = (double *) malloc(D*sizeof(double));
123 | if (!c->wds) { cd_chomp_free(c); return -1; }
124 | /* The resulting K[d]*T+E[d] yields a vector of d-derivatives;
125 | * when we dot-product them (i.e. V^T V) we'll get sum-squared-derivatives;
126 | * set wd to be 1/number of points in order to get average deriv value */
127 | for (i=0; iwds[i] = (iinitsfinals = (double *) malloc((2*D)*n*sizeof(double *));
133 | c->inits = (double **) malloc(D * sizeof(double *));
134 | c->finals = (double **) malloc(D * sizeof(double *));
135 | if (!c->initsfinals || !c->inits || !c->finals) { cd_chomp_free(c); return -1; }
136 | cd_mat_set_zero(c->initsfinals, 2*D, n);
137 | for (i=0; iinits[i] = &c->initsfinals[(2*i)*n];
140 | c->finals[i] = &c->initsfinals[(2*i+1)*n];
141 | }
142 |
143 | /* Allocate A and Ainv */
144 | c->A = (double *) malloc(m * m * sizeof(double));
145 | c->Ainv = (double *) malloc(m * m * sizeof(double));
146 | c->B = (double *) malloc(m * n * sizeof(double));
147 | c->cost_nxn = (double *) malloc(n * n * sizeof(double));
148 | c->cost_mxn = (double *) malloc(m * n * sizeof(double));
149 | c->vels = (double *) malloc(m * n * sizeof(double));
150 | if (!c->A || !c->Ainv || !c->B || !c->cost_nxn || !c->cost_mxn || !c->vels)
151 | { cd_chomp_free(c); return -1; }
152 | /* A, B, and trC start at 0.0;
153 | * before init, the user can fill them with whatever they want */
154 | cd_mat_set_zero(c->A, m, m);
155 | cd_mat_set_zero(c->B, m, n);
156 | c->trC = 0.0;
157 |
158 | /* allocate joint limit stuff */
159 | c->jlimit_lower = (double *) malloc(n * sizeof(double));
160 | c->jlimit_upper = (double *) malloc(n * sizeof(double));
161 | c->Gjlimit = (double *) malloc(m * n * sizeof(double));
162 | c->GjlimitAinv = (double *) malloc(m * n * sizeof(double));
163 | if (!c->jlimit_lower || !c->jlimit_upper || !c->Gjlimit || !c->GjlimitAinv)
164 | { cd_chomp_free(c); return -1; }
165 | for (i=0; ijlimit_lower[i] = -HUGE_VAL;
168 | c->jlimit_upper[i] = HUGE_VAL;
169 | }
170 |
171 | /* Allocate Kvels and Evels */
172 | c->Kvels = (double *) malloc(m * m * sizeof(double));
173 | c->Evels = (double *) malloc(m * n * sizeof(double));
174 | if (!c->Kvels || !c->Evels) { cd_chomp_free(c); return -1; }
175 |
176 | *cp = c;
177 | return 0;
178 | }
179 |
180 | void cd_chomp_free(struct cd_chomp * c)
181 | {
182 | struct cd_chomp_con * con;
183 | if (!c) return;
184 | free(c->cons_h);
185 | free(c->cons_Jcol);
186 | free(c->cons_JAJT);
187 | free(c->cons_ipiv);
188 | free(c->cons_delta);
189 | while (c->cons)
190 | {
191 | con = c->cons;
192 | c->cons = c->cons->next;
193 | free(con);
194 | }
195 | free(c->wds);
196 | free(c->initsfinals);
197 | free(c->inits);
198 | free(c->finals);
199 | free(c->A);
200 | free(c->Ainv);
201 | free(c->B);
202 | free(c->jlimit_lower);
203 | free(c->jlimit_upper);
204 | free(c->Gjlimit);
205 | free(c->GjlimitAinv);
206 | free(c->cost_nxn);
207 | free(c->cost_mxn);
208 | free(c->Kvels);
209 | free(c->Evels);
210 | free(c->vels);
211 | free(c->G);
212 | free(c->G_points);
213 | free(c->AG);
214 | free(c->AG_points);
215 | free(c->T_points);
216 | free(c);
217 | }
218 |
219 | int cd_chomp_add_constraint(struct cd_chomp * c, int k, int i, void * cptr,
220 | int (*con_eval)(void * cptr, struct cd_chomp * c, int i, double * point, double * con_val, double * con_jacobian))
221 | {
222 | struct cd_chomp_con * con;
223 | con = (struct cd_chomp_con *) malloc(sizeof(struct cd_chomp_con));
224 | if (!con) return -1;
225 | con->k = k;
226 | con->i = i;
227 | con->cptr = cptr;
228 | con->con_eval = con_eval;
229 | con->h = 0;
230 | con->J = 0;
231 | con->next = c->cons;
232 | c->cons = con;
233 | return 0;
234 | }
235 |
236 | /* this adds the default KEs for this chomp to A, B, and trC;
237 | * this also calculates D0 and E0 even if D is 0,
238 | * because we need it to compute velocities later */
239 | int cd_chomp_add_KEs(struct cd_chomp * c)
240 | {
241 | int ret;
242 | int i;
243 | int d;
244 | int * num_derivs_alloc;
245 | int * num_derivs;
246 | double ** Ks;
247 | double ** Es;
248 | double * diff; /* Temp suitable-sized finite-differencing matrix */
249 |
250 | ret = 0;
251 |
252 | /*c->wds[i] = 1.0 / (c->m+1+i)*/
253 |
254 | /* Allocate space for Ks, Es */
255 | num_derivs_alloc = (int *) malloc((c->D+1) * sizeof(int));
256 | Ks = (double **) malloc(c->D * sizeof(double *));
257 | Es = (double **) malloc(c->D * sizeof(double *));
258 | if (!num_derivs_alloc || !Ks || !Es) { free(num_derivs_alloc); free(Ks); free(Es); return -1; }
259 | num_derivs_alloc[0] = c->m;
260 | num_derivs = &num_derivs_alloc[1];
261 | for (d=0; dD; d++) { Ks[d] = 0; Es[d] = 0; }
262 |
263 | /* Allocate and set each K, E */
264 | for (d=0; dD; d++)
265 | {
266 | num_derivs[d] = num_derivs[d-1] - 1 + (c->inits[d]?1:0) + (c->finals[d]?1:0);
267 | Ks[d] = (double *) malloc(num_derivs[d] * c->m * sizeof(double));
268 | Es[d] = (double *) malloc(num_derivs[d] * c->n * sizeof(double));
269 | if (!Ks[d] || !Es[d]) { ret = -1; goto error; }
270 |
271 | /* Create suitable finite-differencing matrix */
272 | diff = (double *) malloc(num_derivs[d] * num_derivs[d-1] * sizeof(double));
273 | if (!diff) { ret = -1; goto error; }
274 | cd_mat_set_zero(diff, num_derivs[d], num_derivs[d-1]);
275 | cd_mat_set_zero(Es[d], num_derivs[d], c->n);
276 |
277 | /* potential first row */
278 | if (c->inits[d])
279 | {
280 | diff[0*num_derivs[d-1]+0] = 1.0/c->dt;
281 | cblas_daxpy(c->n, -1.0/c->dt, c->inits[d],1, &Es[d][0],1);
282 | }
283 |
284 | /* fill each row of the middle */
285 | for (i=0; iinits[d]?1:0)+i)*num_derivs[d-1]+i] = -1.0/c->dt;
288 | diff[((c->inits[d]?1:0)+i)*num_derivs[d-1]+i+1] = 1.0/c->dt;
289 | }
290 |
291 | /* potential last row */
292 | if (c->finals[d])
293 | {
294 | diff[(num_derivs[d]-1)*num_derivs[d-1]+(num_derivs[d-1]-1)] = -1.0/c->dt;
295 | cblas_daxpy(c->n, 1.0/c->dt, c->finals[d],1, &Es[d][(num_derivs[d]-1)*(c->n)],1);
296 | }
297 |
298 | /* Set K */
299 | if (d==0)
300 | cd_mat_memcpy(Ks[d], diff, num_derivs[d], num_derivs[d-1]);
301 | else
302 | cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, num_derivs[d], c->m, num_derivs[d-1],
303 | 1.0, diff,num_derivs[d-1], Ks[d-1],c->m, 0.0,Ks[d],c->m);
304 |
305 | /* Add in from prior Es */
306 | if (d > 0)
307 | cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, num_derivs[d], c->n, num_derivs[d-1],
308 | 1.0, diff,num_derivs[d-1], Es[d-1],c->n, 1.0,Es[d],c->n);
309 |
310 | free(diff);
311 | }
312 |
313 | /* Calculate A as weighted sum of K^T K's */
314 | cd_mat_set_zero(c->A, c->m, c->m);
315 | for (d=0; dD; d++)
316 | cblas_dgemm(CblasRowMajor, CblasTrans, CblasNoTrans, c->m, c->m, num_derivs[d],
317 | c->wds[d]/num_derivs[d], Ks[d],c->m, Ks[d],c->m, 1.0,c->A,c->m);
318 |
319 | /* Calculate B = weighed K^T E */
320 | cd_mat_set_zero(c->B, c->m, c->n);
321 | for (d=0; dD; d++)
322 | cblas_dgemm(CblasRowMajor, CblasTrans, CblasNoTrans, c->m, c->n, num_derivs[d],
323 | c->wds[d]/num_derivs[d], Ks[d],c->m, Es[d],c->n, 1.0,c->B,c->n);
324 |
325 | /* Calculate trC = 0.5 * weighted tr(E^T E) */
326 | cd_mat_set_zero(c->cost_nxn, c->n, c->n);
327 | for (d=0; dD; d++)
328 | cblas_dgemm(CblasRowMajor, CblasTrans, CblasNoTrans, c->n, c->n, num_derivs[d],
329 | c->wds[d]/num_derivs[d], Es[d],c->n, Es[d],c->n, 1.0,c->cost_nxn,c->n);
330 | c->trC = 0.5 * cd_mat_trace(c->cost_nxn, c->n, c->n);
331 |
332 | error:
333 | /* note that we're not freeing K0 or E0 */
334 | for (d=0; dD; d++) free(Ks[d]);
335 | for (d=0; dD; d++) free(Es[d]);
336 | free(Ks);
337 | free(Es);
338 | free(num_derivs_alloc);
339 | return ret;
340 | }
341 |
342 | int cd_chomp_init(struct cd_chomp * c)
343 | {
344 | int i;
345 | int err;
346 | struct cd_chomp_con * con;
347 |
348 | /* compute Kvels and Evels (note that inits[0] and finals[0] might be 0! */
349 | cd_mat_set_zero(c->Kvels, c->m, c->m);
350 | cd_mat_set_zero(c->Evels, c->m, c->n);
351 | for (i=0; im; i++)
352 | {
353 | if (i==0)
354 | {
355 | if (c->inits[0])
356 | {
357 | c->Kvels[0*c->m+1] = 0.5 / c->dt;
358 | cd_mat_memcpy(&c->Evels[0*c->n], c->inits[0], c->n, 1);
359 | cd_mat_scale(&c->Evels[0*c->n], c->n, 1, -0.5/c->dt);
360 | }
361 | else
362 | {
363 | c->Kvels[0*c->m+1] = 1.0 / c->dt;
364 | c->Kvels[0*c->m+0] = -1.0 / c->dt;
365 | }
366 | }
367 | else if (i < c->m-1)
368 | {
369 | c->Kvels[i*c->m+i+1] = 0.5 / c->dt;
370 | c->Kvels[i*c->m+i-1] = -0.5 / c->dt;
371 | }
372 | else
373 | {
374 | if (c->finals[0])
375 | {
376 | cd_mat_memcpy(&c->Evels[i*c->n], c->finals[0], c->n, 1);
377 | cd_mat_scale(&c->Evels[i*c->n], c->n, 1, 0.5/c->dt);
378 | c->Kvels[i*c->m+i-1] = -0.5 / c->dt;
379 | }
380 | else
381 | {
382 | c->Kvels[i*c->m+i-0] = 1.0 / c->dt;
383 | c->Kvels[i*c->m+i-1] = -1.0 / c->dt;
384 | }
385 | }
386 | }
387 |
388 | /* if D is nonzero, add into A the default KEs using inits, weights, dt, etc */
389 | err = cd_chomp_add_KEs(c);
390 | if (err) return -1;
391 |
392 | /* Calculate A^-1 from A */
393 | {
394 | int * ipiv;
395 | ipiv = (int *) malloc(c->m * sizeof(int));
396 | if (!ipiv) return -1;
397 | memcpy(c->Ainv, c->A, c->m * c->m * sizeof(double));
398 | err = LAPACKE_dgetrf(LAPACK_ROW_MAJOR, c->m, c->m, c->Ainv, c->m, ipiv);
399 | if (err) { free(ipiv); return -2; }
400 | err = LAPACKE_dgetri(LAPACK_ROW_MAJOR, c->m, c->Ainv, c->m, ipiv);
401 | if (err) { free(ipiv); return -2; }
402 | free(ipiv);
403 | }
404 |
405 | /* allocate constraint stuff from c->cons list */
406 | c->cons_k = 0;
407 | for (con=c->cons; con; con=con->next)
408 | c->cons_k += con->k;
409 | if (c->cons_k)
410 | {
411 | printf("cd_chomp_init: total per-point constraint dimensionality: %d\n", c->cons_k);
412 | c->cons_h = (double *) malloc(c->cons_k * sizeof(double));
413 | c->cons_Jcol = (double *) malloc(c->cons_k * c->n * sizeof(double));
414 | c->cons_JAJT = (double *) malloc(c->cons_k * c->cons_k * sizeof(double));
415 | c->cons_ipiv = (int *) malloc(c->cons_k * sizeof(int));
416 | c->cons_delta = (double *) malloc(c->n * sizeof(double));
417 | if (!c->cons_h || !c->cons_Jcol || !c->cons_JAJT || !c->cons_ipiv || !c->cons_delta) return -1;
418 | c->cons_k = 0;
419 | for (con=c->cons; con; con=con->next)
420 | {
421 | con->h = c->cons_h + c->cons_k;
422 | con->J = c->cons_Jcol + (c->cons_k * c->n);
423 | c->cons_k += con->k;
424 | }
425 | }
426 |
427 | return 0;
428 | }
429 |
430 | int cd_chomp_iterate(struct cd_chomp * c, int do_iteration, double * costp_total, double * costp_obs, double * costp_smooth)
431 | {
432 | int i;
433 | int j;
434 | int err;
435 | double cost_point;
436 | double cost_obs = 0.0;
437 | double cost_smooth = 0.0;
438 | #ifdef DEBUG_TIMING
439 | struct timespec tic;
440 | struct timespec toc;
441 | #endif
442 | int num_limadjs;
443 |
444 | /* compute average velocities at each point,
445 | * using precomputed Kvels matrix */
446 | #ifdef DEBUG_TIMING
447 | clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tic);
448 | #endif
449 | cd_mat_memcpy(c->vels, c->Evels, c->m, c->n);
450 | cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, c->m, c->n, c->m,
451 | 1.0, c->Kvels,c->m, c->T,c->ldt, 1.0,c->vels,c->n);
452 | #ifdef DEBUG_TIMING
453 | clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &toc);
454 | cd_os_timespec_sub(&toc, &tic);
455 | cd_os_timespec_add(&c->ticks_vels, &toc);
456 | #endif
457 |
458 | /* get obstacle costs and/or gradients from user's callback
459 | * saves gradients in G (gradients point uphill) */
460 | #ifdef DEBUG_TIMING
461 | clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tic);
462 | #endif
463 | if (c->cost_pre)
464 | c->cost_pre(c->cptr, c, c->m, c->T_points);
465 | #ifdef DEBUG_TIMING
466 | clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &toc);
467 | cd_os_timespec_sub(&toc, &tic);
468 | cd_os_timespec_add(&c->ticks_callback_pre, &toc);
469 | #endif
470 |
471 | #ifdef DEBUG_TIMING
472 | clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tic);
473 | #endif
474 | if (do_iteration) cd_mat_set_zero(c->G, c->m, c->n);
475 | if (c->cost) for (i=0; im; i++)
476 | {
477 | /* cost callback */
478 | /* compute obstacle costs (weighted by body-point Cartesian velocities) */
479 | /* compute obstacle cost gradients for each internal trajectory point */
480 | c->cost(c->cptr, c, i, c->T_points[i], &c->vels[i*(c->n)],
481 | ((costp_total || costp_obs) ? &cost_point : 0),
482 | (do_iteration ? c->G_points[i] : 0));
483 | /* accumulate obstacle cost */
484 | if (costp_total || costp_obs)
485 | cost_obs += cost_point;
486 | }
487 |
488 | /* divide by number of points (so you're getting average obstacle cost,
489 | * w.r.t. workspace arc length */
490 | if (costp_total || costp_obs)
491 | cost_obs /= c->m;
492 | cd_mat_scale(c->G, c->m, c->n, 1.0/c->m);
493 |
494 | /* add in extra cost/gradient */
495 | if (c->cost_extra)
496 | {
497 | c->cost_extra(c->cptr, c, c->T,
498 | ((costp_total || costp_obs) ? &cost_point : 0),
499 | (do_iteration ? c->G : 0));
500 | cost_obs += cost_point;
501 | }
502 | #ifdef DEBUG_TIMING
503 | clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &toc);
504 | cd_os_timespec_sub(&toc, &tic);
505 | cd_os_timespec_add(&c->ticks_callbacks, &toc);
506 | #endif
507 |
508 | /* do chomp iteration itself */
509 | if (do_iteration)
510 | {
511 | /* add on prior (smoothness) gradient, G += A T + B */
512 | #ifdef DEBUG_TIMING
513 | clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tic);
514 | #endif
515 | cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, c->m, c->n, c->m,
516 | 1.0, c->A,c->m, c->T,c->ldt, 1.0,c->G,c->n);
517 | #ifdef DEBUG_TIMING
518 | clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &toc);
519 | cd_os_timespec_sub(&toc, &tic);
520 | cd_os_timespec_add(&c->ticks_smoothgrad, &toc);
521 | #endif
522 | cd_mat_add(c->G, c->B, c->m, c->n);
523 |
524 | /* map gradient through the A inverse matrix to get AG */
525 | if (!c->use_momentum)
526 | {
527 | /* COMP */
528 | /* apply this trajectory gradient through Ainv to the trajectory */
529 | cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, c->m, c->n, c->m,
530 | 1.0, c->Ainv,c->m, c->G,c->n, 0.0,c->AG,c->n);
531 | }
532 | else
533 | {
534 | /* hamiltonian simulation (with velocity) */
535 |
536 | /* apply this trajectory gradient through Ainv to the momentum */
537 | if (c->leapfrog_first)
538 | {
539 | cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, c->m, c->n, c->m,
540 | 0.5/c->lambda, c->Ainv,c->m, c->G,c->n, 1.0,c->AG,c->n);
541 | c->leapfrog_first = 0;
542 | }
543 | else
544 | {
545 | cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, c->m, c->n, c->m,
546 | 1.0/c->lambda, c->Ainv,c->m, c->G,c->n, 1.0,c->AG,c->n);
547 | }
548 | }
549 |
550 | /* do the constraint math;
551 | * this takes as input the unconstrained update AG,
552 | * and modifies the trajectory itself */
553 | if (c->cons_k)
554 | {
555 | struct cd_chomp_con * con1;
556 | struct cd_chomp_con * con2;
557 |
558 | /* evaluate each point constraint into h and Jcol */
559 | for (con1=c->cons; con1; con1=con1->next)
560 | con1->con_eval(con1->cptr, c, con1->i, c->T_points[con1->i], con1->h, con1->J);
561 |
562 | /* add into cons_h the gradient component C AG (scaled by -1.0/c->lambda) */
563 | for (con1=c->cons; con1; con1=con1->next)
564 | cblas_dgemv(CblasRowMajor, CblasNoTrans, con1->k, c->n,
565 | -1.0/c->lambda, con1->J,c->n, c->AG_points[con1->i],1, 1.0,con1->h,1);
566 |
567 | /* build c->cons_JAJT */
568 | for (con1=c->cons; con1; con1=con1->next)
569 | for (con2=c->cons; con2; con2=con2->next)
570 | {
571 | cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasTrans, con1->k, con2->k, c->n,
572 | c->Ainv[con1->i * c->m + con2->i],
573 | con1->J, c->n, con2->J, c->n,
574 | 0.0, &c->cons_JAJT[((con1->h)-(c->cons_h))*c->cons_k + ((con2->h)-(c->cons_h))], c->cons_k);
575 | }
576 |
577 | /* linear algebra solve, using lapack dgesv driver routine
578 | * (double general Ax=b solver using PLU factorization) */
579 | err = LAPACKE_dgesv(LAPACK_ROW_MAJOR, c->cons_k, 1,
580 | c->cons_JAJT, c->cons_k, c->cons_ipiv,
581 | c->cons_h, 1);
582 | if (err)
583 | {
584 | #if 0
585 | int ii;
586 | for (ii=0; iicons_k; ii++)
587 | cd_mat_vec_print("c->cons_JAJT: ", &c->cons_JAJT[ii*c->cons_k], c->cons_k);
588 | #endif
589 | printf("constraint inversion error!\n");
590 | }
591 |
592 | /* push the updates back through Ainv to the trajectory! */
593 | for (con1=c->cons; con1; con1=con1->next)
594 | {
595 | cblas_dgemv(CblasRowMajor, CblasTrans, con1->k, c->n,
596 | 1.0, con1->J,c->n, con1->h,1, 0.0,c->cons_delta,1);
597 | cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, c->m, c->n, 1,
598 | -1.0, &c->Ainv[con1->i],c->m, c->cons_delta,c->n, 1.0,c->T,c->ldt);
599 | }
600 | }
601 |
602 | /* add AG into the trajectory (from non-constraint part);
603 | * note thet minus sign, as we are doing gradient descent */
604 | for (i=0; im; i++)
605 | cblas_daxpy(c->n, -1.0/c->lambda, &c->AG[i*c->n],1, &c->T[i*c->ldt],1);
606 |
607 | /* handle joint limit violations */
608 | for (num_limadjs=0; num_limadjs<1000; num_limadjs++)
609 | {
610 | double largest_violation;
611 | size_t largest_idx;
612 |
613 | /* find largest violation, and build Gjlimit matrix */
614 | largest_violation = 0.0;
615 | largest_idx = 0;
616 | cd_mat_set_zero(c->Gjlimit, c->m, c->n);
617 | for (i=0; im; i++)
618 | for (j=0; jn; j++)
619 | {
620 | if (c->T_points[i][j] < c->jlimit_lower[j])
621 | {
622 | c->Gjlimit[i*c->n+j] = c->jlimit_lower[j] - c->T_points[i][j];
623 | if (fabs(c->Gjlimit[i*c->n+j]) > largest_violation)
624 | {
625 | largest_violation = fabs(c->Gjlimit[i*c->n+j]);
626 | largest_idx = i*c->n+j;
627 | }
628 | }
629 | if (c->T_points[i][j] > c->jlimit_upper[j])
630 | {
631 | c->Gjlimit[i*c->n+j] = c->jlimit_upper[j] - c->T_points[i][j];
632 | if (fabs(c->Gjlimit[i*c->n+j]) > largest_violation)
633 | {
634 | largest_violation = fabs(c->Gjlimit[i*c->n+j]);
635 | largest_idx = i*c->n+j;
636 | }
637 | }
638 | }
639 | if (largest_violation == 0.0) break;
640 |
641 | /* pre-multiply by Ainv */
642 | /*printf("num_limadjs: %d\n", num_limadjs);*/
643 | cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, c->m, c->n, c->m,
644 | 1.0, c->Ainv,c->m, c->Gjlimit,c->n, 0.0, c->GjlimitAinv,c->n);
645 |
646 | /* compute scalar necessary to make trajectory satisfy limit at largest_idx */
647 | cblas_daxpy(c->m * c->n,
648 | 1.01 * c->Gjlimit[largest_idx] / c->GjlimitAinv[largest_idx],
649 | c->GjlimitAinv,1, c->T,1);
650 | }
651 | if (!(num_limadjs<1000))
652 | {
653 | printf("ran too many joint limit fixes! aborting ...\n");
654 | return -1;
655 | }
656 | }
657 |
658 | /* compute smoothness cost (if we're asked to);
659 | * uses the new updated trajectory T */
660 | if (costp_total || costp_smooth)
661 | {
662 | #ifdef DEBUG_TIMING
663 | clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tic);
664 | #endif
665 | cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, c->m, c->n, c->m,
666 | 1.0, c->A,c->m, c->T,c->ldt, 0.0,c->cost_mxn,c->n);
667 | cblas_dgemm(CblasRowMajor, CblasTrans, CblasNoTrans, c->n, c->n, c->m,
668 | 0.5, c->T,c->ldt, c->cost_mxn,c->n, 0.0,c->cost_nxn,c->n);
669 | cblas_dgemm(CblasRowMajor, CblasTrans, CblasNoTrans, c->n, c->n, c->m,
670 | 1.0, c->B,c->n, c->T,c->ldt, 1.0,c->cost_nxn,c->n);
671 | cost_smooth = cd_mat_trace(c->cost_nxn, c->n, c->n) + c->trC;
672 | #ifdef DEBUG_TIMING
673 | clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &toc);
674 | cd_os_timespec_sub(&toc, &tic);
675 | cd_os_timespec_add(&c->ticks_smoothcost, &toc);
676 | #endif
677 | }
678 |
679 | if (costp_total) *costp_total = cost_obs + cost_smooth;
680 | if (costp_obs) *costp_obs = cost_obs;
681 | if (costp_smooth) *costp_smooth = cost_smooth;
682 | return 0;
683 | }
684 |
--------------------------------------------------------------------------------
/src/libcd/chomp.h:
--------------------------------------------------------------------------------
1 | /** \file chomp.h
2 | * \brief Interface to cd_chomp, a version of CHOMP (Covariant
3 | * Hamiltonian Optimization for Motion Planning), a trajectory
4 | * optimizer developed by Nathan Ratliff, Matthew Zucker,
5 | * J. Andrew Bagnell, and Siddhartha Srinivasa.
6 | * \author Christopher Dellin
7 | * \date 2011-02-21 CD: File created.
8 | */
9 |
10 | /* (C) Copyright 2011-2013 Carnegie Mellon University */
11 |
12 | /* This module (cd_chomp) is part of libcd.
13 | *
14 | * This module of libcd is free software: you can redistribute it
15 | * and/or modify it under the terms of the GNU General Public License as
16 | * published by the Free Software Foundation, either version 3 of the
17 | * License, or (at your option) any later version.
18 | *
19 | * This module of libcd is distributed in the hope that it will be
20 | * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 | * GNU General Public License for more details.
23 | *
24 | * A copy of the GNU General Public License is provided with libcd
25 | * (license-gpl.txt) and is also available at .
26 | */
27 |
28 | /* requires time.h
29 | * (with POSIX.1b Real-time extensions (IEEE Std 1003.1b-1993))
30 | * for struct timespec
31 | * you can get this in gcc with #define _POSIX_C_SOURCE (199309L) */
32 |
33 | /* todo: test this with m=1, m=2, m=0 even? */
34 |
35 | struct cd_chomp_con;
36 |
37 | /* This is a simple waypoint-based implementation of CHOMP without the H. */
38 | struct cd_chomp
39 | {
40 | int n; /* dimension of (configuration) space */
41 | int m; /* number of internal waypoints (excluding endpoints) */
42 | double lambda; /* -1/lambda is update rate, see chomp paper */
43 | double dt; /* set by default so traj lasts 1.0 second; used to calc wds in init_KEs_default */
44 | /* Trajectory */
45 | double * T; /* mxn; pointer to externally-managed memory */
46 | int ldt;
47 | double ** T_points; /* pointers to each point */
48 | /* Temporary space to store trajectory gradient (wrt external cost) */
49 | double * G; /* format equivalent to traj above, mxn */
50 | double ** G_points; /* array of m pointers */
51 | double * AG; /* mxn, holds Ainv-spread trajectory gradient; akin to M (momentum) */
52 | double ** AG_points; /* array of m pointers */
53 | /* Smoothness metrics */
54 | int D; /* D from chomp, the number of finite differencing matrices K used */
55 | double * wds; /* K weights (length D) */
56 | double ** inits; /* the first of these point into T_ext, the rest are malloc'ed */
57 | double ** finals;
58 | double * initsfinals; /* alloc'ed arrays used by default */
59 | /* Smoothness metric inverse (recompute with cd_chomp_init_recalc()) */
60 | double * A; /* mxm */
61 | double * Ainv; /* mxm */
62 | double * B; /* mxn */
63 | double trC; /* C is nxn */
64 | /* joint limits */
65 | double * jlimit_lower;
66 | double * jlimit_upper;
67 | /* Temporaries used for obs cost and its gradient */
68 | double * Kvels;
69 | double * Evels;
70 | double * vels;
71 | /* Temporaries used to calculate the trajectory cost */
72 | double * cost_nxn;
73 | double * cost_mxn;
74 | /* temporaries for joint limits */
75 | double * Gjlimit;
76 | double * GjlimitAinv;
77 | /* External cost function (e.g. obstacles) */
78 | void * cptr;
79 | int (*cost_pre)(void * cptr, struct cd_chomp * c, int m, double ** T_points); /* internal points only */
80 | int (*cost)(void * cptr, struct cd_chomp * c, int ti, double * point, double * vel, double * costp, double * grad);
81 | /* for some reason, this should set the cost, and increment the gradient! */
82 | int (*cost_extra)(void * cptr, struct cd_chomp * c, double * T, double * costp, double * G);
83 | /* Momentum (optional) */
84 | int use_momentum;
85 | int leapfrog_first;
86 | /* Hard constraint (from goal set paper) */
87 | struct cd_chomp_con * cons;
88 | /* the following are allocated on init() */
89 | int cons_k;
90 | double * cons_h;
91 | double * cons_Jcol; /* stacked parts of J specific to each point; k_cons x n */
92 | double * cons_JAJT;
93 | int * cons_ipiv;
94 | double * cons_delta;
95 | /* for timing */
96 | struct timespec ticks_vels;
97 | struct timespec ticks_callback_pre;
98 | struct timespec ticks_callbacks;
99 | struct timespec ticks_smoothgrad;
100 | struct timespec ticks_smoothcost;
101 | };
102 |
103 | /* Step 1: create a problem of the correct dimension
104 | * set D=0 if you want to set up your own A, B, and trC;
105 | * otherwise, init() will calculate default KEs itself given your weights */
106 | int cd_chomp_create(struct cd_chomp ** cp, int m, int n, int D, double * T, int ldt);
107 | void cd_chomp_free(struct cd_chomp * c);
108 |
109 | /* After create, but before init, you should do the following:
110 | * - set up inits and finals; you could, for example, point them
111 | * above and below the trajectory array T passed to create()
112 | * (note that setting them to 0 means leave them free!)
113 | * - seed the trajectory (if you have not already done so)
114 | * - set dt (if you want something other than the default)
115 | * - alloc your own Ks and Es if you dont like the defaults
116 | * - add constraints (as below) */
117 |
118 | struct cd_chomp_con
119 | {
120 | struct cd_chomp_con * next;
121 | int k;
122 | int i;
123 | void * cptr;
124 | int (*con_eval)(void * cptr, struct cd_chomp * c, int i, double * point, double * con_val, double * con_jacobian);
125 | /* pointers to cd_chomp's allocations */
126 | double * h;
127 | double * J;
128 | };
129 |
130 | int cd_chomp_add_constraint(struct cd_chomp * c, int k, int i, void * cptr,
131 | int (*con_eval)(void * cptr, struct cd_chomp * c, int i, double * point, double * con_val, double * con_jacobian));
132 |
133 | /* this calls the two below in succession */
134 | /* for KEs, this takes into account the value of dt (and m) and inits and finals,
135 | * and sets the KE matrices to their default average-squared-derivatives form */
136 | /* this calculates A (from Ks and Es) and Ainv and constraint stuff
137 | * this also calculates K0 and E0 for calculating velocities, from dt */
138 | int cd_chomp_init(struct cd_chomp * c);
139 |
140 | int cd_chomp_iterate(struct cd_chomp * c, int do_iteration, double * costp_total, double * costp_obs, double * costp_smooth);
141 |
--------------------------------------------------------------------------------
/src/libcd/grid.c:
--------------------------------------------------------------------------------
1 | /** \file grid.c
2 | * \brief Implementation of cd_grid, a multidimensional grid of values.
3 | * \author Christopher Dellin
4 | * \date 2011-2012
5 | */
6 |
7 | /* (C) Copyright 2011-2013 Carnegie Mellon University */
8 |
9 | /* This module (cd_grid) is part of libcd.
10 | *
11 | * This module of libcd is free software: you can redistribute it
12 | * and/or modify it under the terms of the GNU General Public License as
13 | * published by the Free Software Foundation, either version 3 of the
14 | * License, or (at your option) any later version.
15 | *
16 | * This module of libcd is distributed in the hope that it will be
17 | * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 | * GNU General Public License for more details.
20 | *
21 | * A copy of the GNU General Public License is provided with libcd
22 | * (license-gpl.txt) and is also available at .
23 | */
24 |
25 | #include
26 | #include
27 | #include
28 | #include
29 | #include "grid.h"
30 |
31 | /* Rectgrid, standard c-ordered indexing into nd grid:
32 | * grid(x,y,z) = grid[x][y][z] = grid[x*NY*NZ + y*NZ + z] */
33 | int cd_grid_create(struct cd_grid ** gp,
34 | void * cell_init, int cell_size, int n, ...)
35 | {
36 | size_t i;
37 | va_list argp;
38 | int * sizes;
39 |
40 | /* Fill sizes from n variadic arguments */
41 | sizes = (int *) malloc(n * sizeof(int));
42 | if (!sizes) { return -1; }
43 | va_start(argp, n);
44 | for (i=0; in = n;
70 | g->sizes = sizes;
71 | g->ncells = 0;
72 | g->cell_size = cell_size;
73 | g->data = 0;
74 | g->lengths = 0;
75 |
76 | /* Allocate cell data */
77 | g->ncells = 1;
78 | for (i=0; incells *= g->sizes[i];
80 | if (cell_size > 0)
81 | {
82 | g->data = (char *) malloc(g->ncells * cell_size);
83 | if (!g->data) { cd_grid_destroy(g); return -2; }
84 |
85 | /* Initialize cell data */
86 | for (i=0; incells; i++)
87 | memcpy(g->data + i*cell_size, cell_init, cell_size);
88 | }
89 |
90 | /* Allocate lengths vector */
91 | g->lengths = (double *) malloc(n*sizeof(double));
92 | if (!g->lengths) { cd_grid_destroy(g); return -1; }
93 | for (i=0; ilengths[i] = 1.0;
94 |
95 | *gp = g;
96 | return 0;
97 | }
98 |
99 | int cd_grid_create_copy(struct cd_grid ** gp,
100 | struct cd_grid * gsrc)
101 | {
102 | struct cd_grid * g;
103 |
104 | g = (struct cd_grid *) malloc(sizeof(struct cd_grid));
105 | if (!g) return -1;
106 | g->n = gsrc->n;
107 | g->sizes = 0;
108 | g->ncells = gsrc->ncells;
109 | g->cell_size = gsrc->cell_size;
110 | g->data = 0;
111 |
112 | /* Fill sizes from n variadic arguments */
113 | g->sizes = (int *) malloc(gsrc->n * sizeof(int));
114 | if (!g->sizes) { cd_grid_destroy(g); return -1; }
115 | memcpy(g->sizes, gsrc->sizes, gsrc->n * sizeof(int));
116 |
117 | /* Allocate cell data */
118 | if (g->cell_size > 0)
119 | {
120 | g->data = (char *) malloc(g->ncells * g->cell_size);
121 | if (!g->data) { cd_grid_destroy(g); return -2; }
122 | memcpy(g->data, gsrc->data, g->ncells * g->cell_size);
123 | }
124 |
125 | /* Allocate lengths vector */
126 | g->lengths = (double *) malloc(gsrc->n*sizeof(double));
127 | if (!g->lengths) { cd_grid_destroy(g); return -1; }
128 | memcpy(g->lengths, gsrc->lengths, gsrc->n*sizeof(double));
129 |
130 | *gp = g;
131 | return 0;
132 | }
133 |
134 | int cd_grid_destroy(struct cd_grid * g)
135 | {
136 | if (!g)
137 | return 0;
138 | free(g->data);
139 | free(g->sizes);
140 | free(g->lengths);
141 | free(g);
142 | return 0;
143 | }
144 |
145 | int cd_grid_index_to_subs(struct cd_grid * g, size_t index, int * subs)
146 | {
147 | int ni;
148 | size_t index_remain;
149 |
150 | index_remain = index;
151 | for (ni=g->n-1; ni>=0; ni--)
152 | {
153 | subs[ni] = index_remain % g->sizes[ni];
154 | index_remain = index_remain / g->sizes[ni];
155 | }
156 |
157 | return 0;
158 | }
159 |
160 | int cd_grid_index_from_subs(struct cd_grid * g, size_t * index, int * subs)
161 | {
162 | int ni;
163 | *index = subs[0];
164 | for (ni=1; nin; ni++)
165 | {
166 | *index *= g->sizes[ni];
167 | *index += subs[ni];
168 | }
169 | return 0;
170 | }
171 |
172 | int cd_grid_center_index(struct cd_grid * g,
173 | size_t index, double * center)
174 | {
175 | int ni;
176 | int sub;
177 | size_t index_remain;
178 |
179 | index_remain = index;
180 | for (ni=g->n-1; ni>=0; ni--)
181 | {
182 | sub = index_remain % g->sizes[ni];
183 | index_remain = index_remain / g->sizes[ni];
184 | center[ni] = (0.5 + sub) / g->sizes[ni];
185 | }
186 |
187 | for (ni=0; nin; ni++) center[ni] *= g->lengths[ni];
188 | return 0;
189 | }
190 |
191 | int cd_grid_lookup_index(struct cd_grid * g,
192 | double * p, size_t * index)
193 | {
194 | int ni;
195 | double x;
196 | int sub;
197 | *index = 0;
198 | for (ni=0; nin; ni++)
199 | {
200 | x = p[ni] / g->lengths[ni];
201 | if (x < 0.0) return 1;
202 | if (x > 1.0) return 1;
203 | sub = (int) floor(x * g->sizes[ni]);
204 | if (sub == g->sizes[ni]) sub--;
205 | *index *= g->sizes[ni];
206 | *index += sub;
207 | }
208 | return 0;
209 | }
210 |
211 | int cd_grid_lookup_subs(struct cd_grid * g,
212 | double * p, int * subs)
213 | {
214 | int ni;
215 | int sub;
216 | double x;
217 | for (ni=0; nin; ni++)
218 | {
219 | x = p[ni] / g->lengths[ni];
220 | if (x < 0.0) return 1;
221 | if (x > 1.0) return 1;
222 | sub = (int) floor(x * g->sizes[ni]);
223 | if (sub == g->sizes[ni]) sub--;
224 | subs[ni] = sub;
225 | }
226 | return 0;
227 | }
228 |
229 | void * cd_grid_get_index(struct cd_grid * g, size_t index)
230 | {
231 | return g->data + index*g->cell_size;
232 | }
233 |
234 | void * cd_grid_get_subs(struct cd_grid * g, int * subs)
235 | {
236 | int ni;
237 | size_t index;
238 | index = subs[0];
239 | for (ni=1; nin; ni++)
240 | {
241 | index *= g->sizes[ni];
242 | index += subs[ni];
243 | }
244 | return g->data + index*g->cell_size;
245 | }
246 |
247 | void * cd_grid_get(struct cd_grid * g, ...)
248 | {
249 | int ni;
250 | va_list argp;
251 | size_t index;
252 | va_start(argp, g);
253 | index = va_arg(argp, int);
254 | for (ni=1; nin; ni++)
255 | {
256 | index *= g->sizes[ni];
257 | index += va_arg(argp, int);
258 | }
259 | va_end(argp);
260 | return g->data + index*g->cell_size;
261 | }
262 |
263 |
264 | /* func: intput, length n
265 | * trans: output, length n
266 | * v: temp, length n
267 | * z: temp, length n+1
268 | */
269 | static int sedt_onedim(int n, double * func, double * trans, int trans_stride,
270 | int * v, double * z)
271 | {
272 | int i;
273 | int np; /* np = num parabolas = k+1 */
274 | int q;
275 | double s;
276 |
277 | np = 0;
278 |
279 | /* Consider each cell, compute lower envelope */
280 | for (q=0; qn-1; ni>=0; ni--)
353 | {
354 | /* Get subscript, decumulate index_remain */
355 | sub = index_remain % g->sizes[ni];
356 | index_remain = index_remain / g->sizes[ni];
357 | /* Decide whether to use previous or next cell */
358 | if (sub == 0) goto use_next;
359 | if (sub == g->sizes[ni]-1) goto use_previous;
360 | /* Get center location */
361 | center = (0.5 + sub) / g->sizes[ni] * g->lengths[ni];
362 | if (p[ni] < center)
363 | goto use_previous;
364 | else
365 | goto use_next;
366 | /* Calculate the difference */
367 | use_previous:
368 | /* Use previous cell for gradient */
369 | diff = *(double *)cd_grid_get_index(g,index);
370 | diff -= *(double *)cd_grid_get_index(g,index - stride);
371 | goto save_continue;
372 | use_next:
373 | /* Use next cell for gradient */
374 | diff = *(double *)cd_grid_get_index(g,index + stride);
375 | diff -= *(double *)cd_grid_get_index(g,index);
376 | goto save_continue;
377 | /* Save to the grad vector, accumulate the stride */
378 | save_continue:
379 | grad[ni] = diff * g->sizes[ni] / g->lengths[ni];
380 | stride *= g->sizes[ni];
381 | }
382 |
383 | return 0;
384 | }
385 |
386 | int cd_grid_double_interp(struct cd_grid * g, double * p, double * valuep)
387 | {
388 | int err;
389 | int ni;
390 | size_t stride;
391 | size_t index;
392 | size_t index_remain;
393 | int sub;
394 | double center;
395 | double diff;
396 | double value;
397 | double grad;
398 | double value_after;
399 | double value_before;
400 |
401 | /* First, look up the value at the nearest center */
402 | err = cd_grid_lookup_index(g, p, &index);
403 | if (err) return err;
404 | value = *(double *)cd_grid_get_index(g,index);
405 | if (value == HUGE_VAL)
406 | { *valuep = HUGE_VAL; return 0; }
407 |
408 | /* This is identical to the gradient algorithm from above */
409 | stride = 1;
410 | index_remain = index;
411 | for (ni=g->n-1; ni>=0; ni--)
412 | {
413 | /* Get subscript, decumulate index_remain */
414 | sub = index_remain % g->sizes[ni];
415 | index_remain = index_remain / g->sizes[ni];
416 | /* Get center location */
417 | center = (0.5 + sub) / g->sizes[ni] * g->lengths[ni];
418 | /* Decide whether to use previous or next cell */
419 | if (sub == 0) goto use_next;
420 | if (sub == g->sizes[ni]-1) goto use_previous;
421 | if (p[ni] < center)
422 | goto use_previous;
423 | else
424 | goto use_next;
425 | /* Calculate the difference */
426 | use_previous:
427 | /* Use previous cell for gradient */
428 | value_after = *(double *)cd_grid_get_index(g,index);
429 | value_before = *(double *)cd_grid_get_index(g,index - stride);
430 | if (value_after == HUGE_VAL || value_before == HUGE_VAL)
431 | { *valuep = HUGE_VAL; return 0; }
432 | diff = value_after;
433 | diff -= value_before;
434 | goto save_continue;
435 | use_next:
436 | /* Use next cell for gradient */
437 | value_after = *(double *)cd_grid_get_index(g,index + stride);
438 | value_before = *(double *)cd_grid_get_index(g,index);
439 | if (value_after == HUGE_VAL || value_before == HUGE_VAL)
440 | { *valuep = HUGE_VAL; return 0; }
441 | diff = value_after;
442 | diff -= value_before;
443 | goto save_continue;
444 | /* Save to the grad vector, accumulate the stride */
445 | save_continue:
446 | /* Adjust the value based on the gradient */
447 | grad = diff * g->sizes[ni] / g->lengths[ni];
448 | value += grad * (p[ni] - center);
449 | stride *= g->sizes[ni];
450 | }
451 |
452 | *valuep = value;
453 | return 0;
454 | }
455 |
456 |
457 | int cd_grid_double_sedt(struct cd_grid ** gp_dt, struct cd_grid * g_func)
458 | {
459 | return cd_grid_double_dt_sqeuc(gp_dt, g_func);
460 | }
461 |
462 | int cd_grid_double_dt_sqeuc(struct cd_grid ** gp_dt, struct cd_grid * g_func)
463 | {
464 | int i;
465 | int ret;
466 | int n;
467 | int err;
468 | int ni;
469 | struct cd_grid * g;
470 | int * subs;
471 | int ni2;
472 | int * v;
473 | double * z;
474 | double * func;
475 | int dim_n;
476 | int dim_stride;
477 | double dim_res2;
478 | double * trans;
479 |
480 | ret = 0;
481 |
482 | n = g_func->n;
483 |
484 | subs = 0;
485 | v = 0;
486 | z = 0;
487 | func = 0;
488 |
489 | /* Allocate space to keep n+1 subscripts
490 | * (the msb flips from 0 to 1 when we're done) */
491 | subs = (int *) malloc((n+1) * sizeof(int));
492 | if (!subs) { ret = -1; goto error; }
493 |
494 | /* Start with copy of sampled function */
495 | err = cd_grid_create_copy(&g, g_func);
496 | if (err) { ret = -1; goto error; }
497 |
498 | /* Operate the 1-dimensional squared euclidean distance transform
499 | * over each dimension in turn, updating the values for each slice */
500 | for (ni=0; nisizes[ni];
507 |
508 | /* Calculate slice stride (product of all smaller dimension sizes) */
509 | dim_stride = 1;
510 | for (ni2=ni+1; ni2sizes[ni2];
512 |
513 | /* Grab extent for this dimension */
514 | dim_res2 = pow(g_func->lengths[ni]/g->sizes[ni], 2.0);
515 |
516 | /* Set up temp arrays for the 1d transform */
517 | v = (int *) malloc(dim_n * sizeof(int));
518 | z = (double *) malloc((dim_n + 1) * sizeof(double));
519 | func = (double *) malloc(dim_n*sizeof(double));
520 | if (!v || !z || !func) { ret = -1; goto error; }
521 |
522 | /* Loop until we're done (the msb subscript flips) */
523 | while (subs[n]==0)
524 | {
525 | /* Get slice data pointer (first element) */
526 | trans = (double *)cd_grid_get_subs(g, subs);
527 |
528 | /* Perform 1d transform (scale by extent) */
529 | /* XXX BUG:
530 | * Scaling HUGE_VAL is not guarenteed to maintain HUGE_VAL
531 | * (e.g. on systems with no IEEE infinitiy) */
532 | for (i=0; isizes[ni2]))
542 | {
543 | subs[ni2+1]++;
544 | subs[ni2] = 0;
545 | }
546 | }
547 |
548 | /* Continue! */
549 | }
550 |
551 | free(v);
552 | free(z);
553 | free(func);
554 | v = 0;
555 | z = 0;
556 | func = 0;
557 | }
558 |
559 | error:
560 | free(func);
561 | free(v);
562 | free(z);
563 | free(subs);
564 | if (ret == 0)
565 | *gp_dt = g;
566 | else if (g)
567 | cd_grid_destroy(g);
568 | return ret;
569 | }
570 |
571 | int cd_grid_double_dt_sgneuc(struct cd_grid ** gp_dt, struct cd_grid * g_binobs)
572 | {
573 | int ret;
574 | int err;
575 | struct cd_grid * g_vox_emp = 0;
576 | struct cd_grid * g_vox_obs = 0;
577 | struct cd_grid * g_sedt_emp = 0;
578 | struct cd_grid * g_sedt_obs = 0;
579 | struct cd_grid * g_dt = 0;
580 | double dval;
581 | size_t index;
582 |
583 | if (g_binobs->cell_size != sizeof(char))
584 | return -2;
585 |
586 | ret = 0;
587 |
588 | /* g_vox_emp is 0.0 in free space, HUGE_VAL elsewhere */
589 | dval = 0.0;
590 | err = cd_grid_create_sizearray(&g_vox_emp, &dval, sizeof(dval), g_binobs->n, g_binobs->sizes);
591 | if (err) { ret = -1; goto error; }
592 | err = cd_grid_create_sizearray(&g_vox_obs, &dval, sizeof(dval), g_binobs->n, g_binobs->sizes);
593 | if (err) { ret = -1; goto error; }
594 | memcpy(g_vox_emp->lengths, g_binobs->lengths, g_binobs->n*sizeof(double));
595 | memcpy(g_vox_emp->lengths, g_binobs->lengths, g_binobs->n*sizeof(double));
596 |
597 | /* g_vox_obs is 0.0 in obstacles, HUGE_VAL elsewhere */
598 | for (index=0; indexncells; index++)
599 | {
600 | if (*(char *)cd_grid_get_index(g_binobs,index)) /* in obstacle */
601 | {
602 | *(double *)cd_grid_get_index(g_vox_emp,index) = HUGE_VAL;
603 | *(double *)cd_grid_get_index(g_vox_obs,index) = 0.0;
604 | }
605 | else /* free space */
606 | {
607 | *(double *)cd_grid_get_index(g_vox_emp,index) = 0.0;
608 | *(double *)cd_grid_get_index(g_vox_obs,index) = HUGE_VAL;
609 | }
610 | }
611 |
612 | /* Compute the Squared Euclidean Distance Transform of each voxel grid */
613 | err = cd_grid_double_sedt(&g_sedt_emp, g_vox_emp);
614 | if (err) { ret = -1; goto error; }
615 | err = cd_grid_double_sedt(&g_sedt_obs, g_vox_obs);
616 | if (err) { ret = -1; goto error; }
617 |
618 | /* Create signed distance field grid (obs-emp) */
619 | err = cd_grid_create_copy(&g_dt, g_sedt_obs);
620 | if (err) { ret = -1; goto error; }
621 | for (index=0; indexncells; index++)
622 | {
623 | *(double *)cd_grid_get_index(g_dt, index) =
624 | sqrt(*(double *)cd_grid_get_index(g_dt, index)) -
625 | sqrt(*(double *)cd_grid_get_index(g_sedt_emp, index));
626 | }
627 |
628 | error:
629 | cd_grid_destroy(g_vox_emp);
630 | cd_grid_destroy(g_vox_obs);
631 | cd_grid_destroy(g_sedt_emp);
632 | cd_grid_destroy(g_sedt_obs);
633 | if (ret == 0) *gp_dt = g_dt;
634 | return ret;
635 | }
636 |
637 | int cd_grid_double_bin_sdf(struct cd_grid ** gp_dt, struct cd_grid * g_emp)
638 | {
639 | int ret;
640 | int err;
641 | struct cd_grid * g_vox_emp;
642 | struct cd_grid * g_vox_obs = 0;
643 | struct cd_grid * g_sedt_emp = 0;
644 | struct cd_grid * g_sedt_obs = 0;
645 | struct cd_grid * g_dt = 0;
646 | size_t index;
647 |
648 | if (g_emp->cell_size != sizeof(double))
649 | return -2;
650 |
651 | ret = 0;
652 |
653 | /* g_vox_emp is 0.0 in free space, HUGE_VAL elsewhere */
654 | g_vox_emp = g_emp;
655 |
656 | /* g_vox_obs is 0.0 in obstacles, HUGE_VAL elsewhere */
657 | err = cd_grid_create_copy(&g_vox_obs, g_vox_emp);
658 | if (err) { ret = -1; goto error; }
659 | for (index=0; indexncells; index++)
660 | {
661 | *(double *)cd_grid_get_index(g_vox_obs,index) =
662 | (*(double *)cd_grid_get_index(g_vox_emp,index) == 0.0) ? HUGE_VAL : 0.0;
663 | }
664 |
665 | /* Compute the Squared Euclidean Distance Transform of each voxel grid */
666 | err = cd_grid_double_sedt(&g_sedt_emp, g_vox_emp);
667 | if (err) { ret = -1; goto error; }
668 | err = cd_grid_double_sedt(&g_sedt_obs, g_vox_obs);
669 | if (err) { ret = -1; goto error; }
670 |
671 | /* Create signed distance field grid (obs-emp) */
672 | err = cd_grid_create_copy(&g_dt, g_sedt_obs);
673 | if (err) { ret = -1; goto error; }
674 | for (index=0; indexncells; index++)
675 | {
676 | *(double *)cd_grid_get_index(g_dt, index) =
677 | sqrt(*(double *)cd_grid_get_index(g_dt, index)) -
678 | sqrt(*(double *)cd_grid_get_index(g_sedt_emp, index));
679 | }
680 |
681 | error:
682 | cd_grid_destroy(g_vox_obs);
683 | cd_grid_destroy(g_sedt_emp);
684 | cd_grid_destroy(g_sedt_obs);
685 | if (ret == 0) *gp_dt = g_dt;
686 | return ret;
687 | }
688 |
--------------------------------------------------------------------------------
/src/libcd/grid.h:
--------------------------------------------------------------------------------
1 | /** \file grid.h
2 | * \brief Interface to cd_grid, a multidimensional grid of values.
3 | * \author Christopher Dellin
4 | * \date 2011-2012
5 | */
6 |
7 | /* (C) Copyright 2011-2013 Carnegie Mellon University */
8 |
9 | /* This module (cd_grid) is part of libcd.
10 | *
11 | * This module of libcd is free software: you can redistribute it
12 | * and/or modify it under the terms of the GNU General Public License as
13 | * published by the Free Software Foundation, either version 3 of the
14 | * License, or (at your option) any later version.
15 | *
16 | * This module of libcd is distributed in the hope that it will be
17 | * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 | * GNU General Public License for more details.
20 | *
21 | * A copy of the GNU General Public License is provided with libcd
22 | * (license-gpl.txt) and is also available at .
23 | */
24 |
25 | /* requires:
26 | * #include (for size_t)
27 | */
28 |
29 | struct cd_grid
30 | {
31 | /* Dimensionality of space */
32 | int n;
33 | /* Grid parameters */
34 | int * sizes;
35 | size_t ncells;
36 | /* The actual data */
37 | int cell_size;
38 | char * data;
39 | /* Actual grid side lengths (1x1x1x... by default) */
40 | double * lengths;
41 | };
42 |
43 | int cd_grid_create(struct cd_grid ** gp, void * cell_init, int cell_size, int n, ...);
44 | int cd_grid_create_sizearray(struct cd_grid ** gp, void * cell_init, int cell_size, int n, int * sizes);
45 |
46 | /* note - this takes ownership of sizes, and will free it when the grid is destroyed! */
47 | int cd_grid_create_sizeown(struct cd_grid ** gp, void * cell_init, int cell_size, int n, int * sizes);
48 |
49 | int cd_grid_create_copy(struct cd_grid ** gp, struct cd_grid * gsrc);
50 | int cd_grid_destroy(struct cd_grid * g);
51 |
52 | /* convert between index and subs */
53 | int cd_grid_index_to_subs(struct cd_grid * g, size_t index, int * subs);
54 | int cd_grid_index_from_subs(struct cd_grid * g, size_t * index, int * subs);
55 |
56 | /* Get center from index */
57 | int cd_grid_center_index(struct cd_grid * g, size_t index, double * center);
58 |
59 | /* Lookup cell index, subs from location
60 | * these will return 1 if it's out of range! */
61 | int cd_grid_lookup_index(struct cd_grid * g, double * p, size_t * index);
62 | int cd_grid_lookup_subs(struct cd_grid * g, double * p, int * subs);
63 |
64 |
65 | /* Get cell from index, subs */
66 | void * cd_grid_get_index(struct cd_grid * g, size_t index);
67 | void * cd_grid_get_subs(struct cd_grid * g, int * subs);
68 | void * cd_grid_get(struct cd_grid * g, ...);
69 |
70 |
71 | /* Simple multilinear interpolation / discontinuous gradient
72 | * these will return 1 if the point is out of range! */
73 | int cd_grid_double_interp(struct cd_grid * g, double * p, double * valuep);
74 | int cd_grid_double_grad(struct cd_grid * g, double * p, double * grad);
75 |
76 |
77 |
78 | /* Squared Euclidean Distance Transform
79 | * (see http://www.cs.cornell.edu/~dph/papers/dt.pdf)
80 | * Uses doubles!
81 | * Given a double grid funcg,
82 | * computes the sedt grid (same size),
83 | * with 0 -> 0, and + -> squared distance to smallest value */
84 | int cd_grid_double_dt_sqeuc(struct cd_grid ** gp_dt, struct cd_grid * g_func);
85 | /* legacy */
86 | int cd_grid_double_sedt(struct cd_grid ** gp_dt, struct cd_grid * g_func);
87 |
88 | /* signed euclidean distance transform, aka signed distance field
89 | * g_binobs is type(char) with 0 in free space, !=0 in obstacles
90 | * output is + inside obstacles, - in free space */
91 | int cd_grid_double_dt_sgneuc(struct cd_grid ** gp_dt, struct cd_grid * g_binobs);
92 | /* legacy (g_emp is HUGE_VAL in obstacles, and 0.0 in free space) */
93 | int cd_grid_double_bin_sdf(struct cd_grid ** gp_dt, struct cd_grid * g_emp);
94 |
--------------------------------------------------------------------------------
/src/libcd/grid_flood.c:
--------------------------------------------------------------------------------
1 | /** \file grid_flood.c
2 | * \brief Implementation of cd_grid_flood, a flood-fill implementation.
3 | * \author Christopher Dellin
4 | * \date 2011-11-21: Initial implementation (from orikgroup)
5 | * \date 2012-07-15: Incorporated into libcd
6 | */
7 |
8 | /* (C) Copyright 2011-2013 Carnegie Mellon University */
9 |
10 | /* This module (cd_grid_flood) is part of libcd.
11 | *
12 | * This module of libcd is free software: you can redistribute it
13 | * and/or modify it under the terms of the GNU General Public License as
14 | * published by the Free Software Foundation, either version 3 of the
15 | * License, or (at your option) any later version.
16 | *
17 | * This module of libcd is distributed in the hope that it will be
18 | * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 | * GNU General Public License for more details.
21 | *
22 | * A copy of the GNU General Public License is provided with libcd
23 | * (license-gpl.txt) and is also available at .
24 | */
25 |
26 | #include
27 | #include "grid.h"
28 | #include "grid_flood.h"
29 |
30 | int cd_grid_flood_fill(struct cd_grid * g, size_t index_start,
31 | int * wrap_dim,
32 | int (*replace)(void *, void *), void * rptr)
33 | {
34 | /* we maintain a stack of yet-to-be-visited adjacent cells */
35 | struct stack
36 | {
37 | struct stack * next;
38 | size_t index;
39 | };
40 |
41 | int ret;
42 | struct stack * s;
43 | struct stack * popped;
44 | size_t index;
45 | int ni;
46 | int pm;
47 | int * subs;
48 | int sub_save;
49 |
50 | subs = (int *) malloc(g->n * sizeof(int));
51 | if (!subs) return -1;
52 |
53 | /* Start with a stack with one node */
54 | s = (struct stack *) malloc(sizeof(struct stack));
55 | if (!s) { free(subs); return -1; }
56 | s->next = 0;
57 | s->index = index_start;
58 |
59 | /* Flood fill! */
60 | ret = 0;
61 | while (s)
62 | {
63 | /* Pop */
64 | popped = s;
65 | s = s->next;
66 | index = popped->index;
67 | free(popped);
68 |
69 | /* Attempt replace (continue if failed) */
70 | if (!replace(cd_grid_get_index(g,index), rptr)) continue;
71 |
72 | cd_grid_index_to_subs(g, index, subs);
73 |
74 | /* Add neighbors to stack */
75 | for (ni=0; nin; ni++)
76 | for (pm=0; pm<2; pm++)
77 | {
78 | sub_save = subs[ni];
79 | subs[ni] += pm==0 ? -1 : 1;
80 | /* bail if over the edge and not wrapping this dim */
81 | if ((subs[ni] < 0 || subs[ni] >= g->sizes[ni]) && (!wrap_dim || !wrap_dim[ni]))
82 | {
83 | subs[ni] = sub_save;
84 | continue;
85 | }
86 | /* wrap if necessary */
87 | if (subs[ni] < 0) subs[ni] += g->sizes[ni];
88 | if (subs[ni] >= g->sizes[ni]) subs[ni] -= g->sizes[ni];
89 | cd_grid_index_from_subs(g, &index, subs);
90 | subs[ni] = sub_save;
91 |
92 | popped = (struct stack *) malloc(sizeof(struct stack));
93 | if (!popped) { ret = -1; goto do_return; }
94 | popped->next = s;
95 | popped->index = index;
96 | s = popped;
97 | }
98 | }
99 |
100 | do_return:
101 | /* free any remaining stack elements */
102 | while (s)
103 | {
104 | popped = s;
105 | s = s->next;
106 | free(popped);
107 | }
108 |
109 | free(subs);
110 | return ret;
111 | }
112 |
--------------------------------------------------------------------------------
/src/libcd/grid_flood.h:
--------------------------------------------------------------------------------
1 | /** \file grid_flood.h
2 | * \brief Interface to cd_grid_flood, a flood-fill implementation.
3 | * \author Christopher Dellin
4 | * \date 2011-2012
5 | */
6 |
7 | /* (C) Copyright 2011-2013 Carnegie Mellon University */
8 |
9 | /* This module (cd_grid_flood) is part of libcd.
10 | *
11 | * This module of libcd is free software: you can redistribute it
12 | * and/or modify it under the terms of the GNU General Public License as
13 | * published by the Free Software Foundation, either version 3 of the
14 | * License, or (at your option) any later version.
15 | *
16 | * This module of libcd is distributed in the hope that it will be
17 | * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 | * GNU General Public License for more details.
20 | *
21 | * A copy of the GNU General Public License is provided with libcd
22 | * (license-gpl.txt) and is also available at .
23 | */
24 |
25 | /* requires:
26 | * #include
27 | * #include
28 | */
29 |
30 | /* Modify the grid by performing a flood-fill starting with the given index.
31 | * Diagonal cells are considered adjacent (e.g. 8-connected in 2D).
32 | * By default, the grid does not wrap; if wrap_dim is passed, it should
33 | * have length grid.n, with non-zero elements denoting a wrapped dimension. */
34 | int cd_grid_flood_fill(struct cd_grid * g, size_t index_start,
35 | int * wrap_dim,
36 | int (*replace)(void *, void *), void * rptr);
37 |
--------------------------------------------------------------------------------
/src/libcd/kin.c:
--------------------------------------------------------------------------------
1 | /** \file kin.c
2 | * \brief Implementation of cd_kin, a collection of useful routines for
3 | * kinematics.
4 | * \author Christopher Dellin
5 | * \date 2010-2012
6 | */
7 |
8 | /* (C) Copyright 2010-2013 Carnegie Mellon University */
9 |
10 | /* This module (cd_kin) is part of libcd.
11 | *
12 | * This module of libcd is free software: you can redistribute it
13 | * and/or modify it under the terms of the GNU General Public License as
14 | * published by the Free Software Foundation, either version 3 of the
15 | * License, or (at your option) any later version.
16 | *
17 | * This module of libcd is distributed in the hope that it will be
18 | * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 | * GNU General Public License for more details.
21 | *
22 | * A copy of the GNU General Public License is provided with libcd
23 | * (license-gpl.txt) and is also available at .
24 | */
25 |
26 | #include
27 | #include
28 | #include "mat.h"
29 | #include "kin.h"
30 |
31 | #define TAU (6.2831853071795864769252867665590057683943387987502116)
32 |
33 | int cd_kin_quat_identity(double quat[4])
34 | {
35 | quat[0] = 0.0;
36 | quat[1] = 0.0;
37 | quat[2] = 0.0;
38 | quat[3] = 1.0;
39 | return 0;
40 | }
41 |
42 | int cd_kin_pose_identity(double pose[7])
43 | {
44 | pose[0] = 0.0;
45 | pose[1] = 0.0;
46 | pose[2] = 0.0;
47 | pose[3] = 0.0;
48 | pose[4] = 0.0;
49 | pose[5] = 0.0;
50 | pose[6] = 1.0;
51 | return 0;
52 | }
53 |
54 | /* Note - should we check for len = 0.0? */
55 | int cd_kin_quat_normalize(double quat[4])
56 | {
57 | double len;
58 | len = cblas_dnrm2(4, quat, 1);
59 | cblas_dscal(4, 1.0/len, quat, 1);
60 | return 0;
61 | }
62 |
63 | /* Note - should we check for len = 0.0? */
64 | int cd_kin_pose_normalize(double pose[7])
65 | {
66 | double len;
67 | len = cblas_dnrm2(4, pose+3, 1);
68 | cblas_dscal(4, 1.0/len, pose+3, 1);
69 | return 0;
70 | }
71 |
72 | int cd_kin_quat_flip_closerto(double quat[4], const double target[4])
73 | {
74 | int i;
75 | double orig_diff;
76 | double flipped_diff;
77 | double orig_sumsq = 0.0;
78 | double flipped_sumsq = 0.0;
79 | for (i=0; i<4; i++)
80 | {
81 | orig_diff = quat[i] - target[i];
82 | flipped_diff = - quat[i] - target[i];
83 | orig_sumsq += orig_diff * orig_diff;
84 | flipped_sumsq += flipped_diff * flipped_diff;
85 | }
86 | if (flipped_sumsq < orig_sumsq)
87 | {
88 | for (i=0; i<4; i++)
89 | quat[i] *= -1.0;
90 | }
91 | return 0;
92 | }
93 |
94 | int cd_kin_pose_flip_closerto(double pose[7], const double target[7])
95 | {
96 | int i;
97 | double orig_diff;
98 | double flipped_diff;
99 | double orig_sumsq = 0.0;
100 | double flipped_sumsq = 0.0;
101 | for (i=3; i<7; i++)
102 | {
103 | orig_diff = pose[i] - target[i];
104 | flipped_diff = - pose[i] - target[i];
105 | orig_sumsq += orig_diff * orig_diff;
106 | flipped_sumsq += flipped_diff * flipped_diff;
107 | }
108 | if (flipped_sumsq < orig_sumsq)
109 | {
110 | for (i=3; i<7; i++)
111 | pose[i] *= -1.0;
112 | }
113 | return 0;
114 | }
115 |
116 | int cd_kin_quat_compose(const double quat_ab[4], const double quat_bc[4], double quat_ac[4])
117 | {
118 | double qabx, qaby, qabz, qabw;
119 | double qbcx, qbcy, qbcz, qbcw;
120 | qabx = quat_ab[0];
121 | qaby = quat_ab[1];
122 | qabz = quat_ab[2];
123 | qabw = quat_ab[3];
124 | qbcx = quat_bc[0];
125 | qbcy = quat_bc[1];
126 | qbcz = quat_bc[2];
127 | qbcw = quat_bc[3];
128 | /* Quaternion part is simple composition */
129 | quat_ac[0] = qabw*qbcx + qabx*qbcw + qaby*qbcz - qabz*qbcy;
130 | quat_ac[1] = qabw*qbcy - qabx*qbcz + qaby*qbcw + qabz*qbcx;
131 | quat_ac[2] = qabw*qbcz + qabx*qbcy - qaby*qbcx + qabz*qbcw;
132 | quat_ac[3] = qabw*qbcw - qabx*qbcx - qaby*qbcy - qabz*qbcz;
133 | return 0;
134 | }
135 |
136 | int cd_kin_pose_compose(const double pose_ab[7], const double pose_bc[7], double pose_ac[7])
137 | {
138 | double qabx, qaby, qabz, qabw;
139 | double qbcx, qbcy, qbcz, qbcw;
140 | double x_in, y_in, z_in;
141 | double x_out, y_out, z_out;
142 | double qx2, qy2, qz2, qw2, qxqy, qxqz, qxqw, qyqz, qyqw, qzqw;
143 | qabx = pose_ab[3];
144 | qaby = pose_ab[4];
145 | qabz = pose_ab[5];
146 | qabw = pose_ab[6];
147 | qbcx = pose_bc[3];
148 | qbcy = pose_bc[4];
149 | qbcz = pose_bc[5];
150 | qbcw = pose_bc[6];
151 | /* Quaternion part is simple composition */
152 | pose_ac[3] = qabw*qbcx + qabx*qbcw + qaby*qbcz - qabz*qbcy;
153 | pose_ac[4] = qabw*qbcy - qabx*qbcz + qaby*qbcw + qabz*qbcx;
154 | pose_ac[5] = qabw*qbcz + qabx*qbcy - qaby*qbcx + qabz*qbcw;
155 | pose_ac[6] = qabw*qbcw - qabx*qbcx - qaby*qbcy - qabz*qbcz;
156 | /* Rotate xyz_bc into a frame, rotate by qab */
157 | x_in = pose_bc[0];
158 | y_in = pose_bc[1];
159 | z_in = pose_bc[2];
160 | qx2 = qabx*qabx;
161 | qy2 = qaby*qaby;
162 | qz2 = qabz*qabz;
163 | qw2 = qabw*qabw;
164 | qxqy = qabx*qaby;
165 | qxqz = qabx*qabz;
166 | qxqw = qabx*qabw;
167 | qyqz = qaby*qabz;
168 | qyqw = qaby*qabw;
169 | qzqw = qabz*qabw;
170 | x_out = x_in*(qx2-qy2-qz2+qw2) + 2*y_in*(qxqy-qzqw) + 2*z_in*(qxqz+qyqw);
171 | y_out = 2*x_in*(qxqy+qzqw) + y_in*(-qx2+qy2-qz2+qw2) + 2*z_in*(qyqz-qxqw);
172 | z_out = 2*x_in*(qxqz-qyqw) + 2*y_in*(qyqz+qxqw) + z_in*(-qx2-qy2+qz2+qw2);
173 | /* xyz part is the above rotated xyc_bc plus xyz_ab */
174 | pose_ac[0] = x_out + pose_ab[0];
175 | pose_ac[1] = y_out + pose_ab[1];
176 | pose_ac[2] = z_out + pose_ab[2];
177 | return 0;
178 | }
179 |
180 | int cd_kin_pose_compos(const double pose_ab[7], const double pos_bc[3], double pos_ac[3])
181 | {
182 | double qabx, qaby, qabz, qabw;
183 | double x_in, y_in, z_in;
184 | double x_out, y_out, z_out;
185 | double qx2, qy2, qz2, qw2, qxqy, qxqz, qxqw, qyqz, qyqw, qzqw;
186 | qabx = pose_ab[3];
187 | qaby = pose_ab[4];
188 | qabz = pose_ab[5];
189 | qabw = pose_ab[6];
190 | /* Rotate xyz_bc into a frame, rotate by qab */
191 | x_in = pos_bc[0];
192 | y_in = pos_bc[1];
193 | z_in = pos_bc[2];
194 | qx2 = qabx*qabx;
195 | qy2 = qaby*qaby;
196 | qz2 = qabz*qabz;
197 | qw2 = qabw*qabw;
198 | qxqy = qabx*qaby;
199 | qxqz = qabx*qabz;
200 | qxqw = qabx*qabw;
201 | qyqz = qaby*qabz;
202 | qyqw = qaby*qabw;
203 | qzqw = qabz*qabw;
204 | x_out = x_in*(qx2-qy2-qz2+qw2) + 2*y_in*(qxqy-qzqw) + 2*z_in*(qxqz+qyqw);
205 | y_out = 2*x_in*(qxqy+qzqw) + y_in*(-qx2+qy2-qz2+qw2) + 2*z_in*(qyqz-qxqw);
206 | z_out = 2*x_in*(qxqz-qyqw) + 2*y_in*(qyqz+qxqw) + z_in*(-qx2-qy2+qz2+qw2);
207 | /* xyz part is the above rotated xyc_bc plus xyz_ab */
208 | pos_ac[0] = x_out + pose_ab[0];
209 | pos_ac[1] = y_out + pose_ab[1];
210 | pos_ac[2] = z_out + pose_ab[2];
211 | return 0;
212 | }
213 |
214 | int cd_kin_quat_compose_vec(const double quat_ab[4], const double vec_bc[3], double vec_ac[3])
215 | {
216 | double qabx, qaby, qabz, qabw;
217 | double x_in, y_in, z_in;
218 | double qx2, qy2, qz2, qw2, qxqy, qxqz, qxqw, qyqz, qyqw, qzqw;
219 | qabx = quat_ab[0];
220 | qaby = quat_ab[1];
221 | qabz = quat_ab[2];
222 | qabw = quat_ab[3];
223 | /* Rotate xyz_bc into a frame, rotate by qab */
224 | x_in = vec_bc[0];
225 | y_in = vec_bc[1];
226 | z_in = vec_bc[2];
227 | qx2 = qabx*qabx;
228 | qy2 = qaby*qaby;
229 | qz2 = qabz*qabz;
230 | qw2 = qabw*qabw;
231 | qxqy = qabx*qaby;
232 | qxqz = qabx*qabz;
233 | qxqw = qabx*qabw;
234 | qyqz = qaby*qabz;
235 | qyqw = qaby*qabw;
236 | qzqw = qabz*qabw;
237 | vec_ac[0] = x_in*(qx2-qy2-qz2+qw2) + 2*y_in*(qxqy-qzqw) + 2*z_in*(qxqz+qyqw);
238 | vec_ac[1] = 2*x_in*(qxqy+qzqw) + y_in*(-qx2+qy2-qz2+qw2) + 2*z_in*(qyqz-qxqw);
239 | vec_ac[2] = 2*x_in*(qxqz-qyqw) + 2*y_in*(qyqz+qxqw) + z_in*(-qx2-qy2+qz2+qw2);
240 | return 0;
241 | }
242 |
243 | /* Do the same, but just rotate a 3d vector (vel,acc), not a position vector */
244 | int cd_kin_pose_compose_vec(const double pose_ab[7], const double vec_bc[3], double vec_ac[3])
245 | {
246 | double qabx, qaby, qabz, qabw;
247 | double x_in, y_in, z_in;
248 | double qx2, qy2, qz2, qw2, qxqy, qxqz, qxqw, qyqz, qyqw, qzqw;
249 | qabx = pose_ab[3];
250 | qaby = pose_ab[4];
251 | qabz = pose_ab[5];
252 | qabw = pose_ab[6];
253 | /* Rotate xyz_bc into a frame, rotate by qab */
254 | x_in = vec_bc[0];
255 | y_in = vec_bc[1];
256 | z_in = vec_bc[2];
257 | qx2 = qabx*qabx;
258 | qy2 = qaby*qaby;
259 | qz2 = qabz*qabz;
260 | qw2 = qabw*qabw;
261 | qxqy = qabx*qaby;
262 | qxqz = qabx*qabz;
263 | qxqw = qabx*qabw;
264 | qyqz = qaby*qabz;
265 | qyqw = qaby*qabw;
266 | qzqw = qabz*qabw;
267 | vec_ac[0] = x_in*(qx2-qy2-qz2+qw2) + 2*y_in*(qxqy-qzqw) + 2*z_in*(qxqz+qyqw);
268 | vec_ac[1] = 2*x_in*(qxqy+qzqw) + y_in*(-qx2+qy2-qz2+qw2) + 2*z_in*(qyqz-qxqw);
269 | vec_ac[2] = 2*x_in*(qxqz-qyqw) + 2*y_in*(qyqz+qxqw) + z_in*(-qx2-qy2+qz2+qw2);
270 | return 0;
271 | }
272 |
273 | int cd_kin_quat_invert(const double quat_in[4], double quat_out[4])
274 | {
275 | double qx, qy, qz, qw;
276 | /* Invert quaternion (assume normalized) */
277 | qx = -quat_in[0];
278 | qy = -quat_in[1];
279 | qz = -quat_in[2];
280 | qw = quat_in[3];
281 | quat_out[0] = qx;
282 | quat_out[1] = qy;
283 | quat_out[2] = qz;
284 | quat_out[3] = qw;
285 | return 0;
286 | }
287 |
288 | int cd_kin_pose_invert(const double pose_in[7], double pose_out[7])
289 | {
290 | double x_in, y_in, z_in;
291 | double x_out, y_out, z_out;
292 | double qx, qy, qz, qw;
293 | double qx2, qy2, qz2, qw2, qxqy, qxqz, qxqw, qyqz, qyqw, qzqw;
294 | /* Get from input */
295 | x_in = pose_in[0];
296 | y_in = pose_in[1];
297 | z_in = pose_in[2];
298 | /* Invert quaternion (assume normalized) */
299 | qx = -pose_in[3];
300 | qy = -pose_in[4];
301 | qz = -pose_in[5];
302 | qw = pose_in[6];
303 | /* Apply inverted quaternion to xyz_in */
304 | qx2 = qx*qx;
305 | qy2 = qy*qy;
306 | qz2 = qz*qz;
307 | qw2 = qw*qw;
308 | qxqy = qx*qy;
309 | qxqz = qx*qz;
310 | qxqw = qx*qw;
311 | qyqz = qy*qz;
312 | qyqw = qy*qw;
313 | qzqw = qz*qw;
314 | x_out = x_in*(qx2-qy2-qz2+qw2) + 2*y_in*(qxqy-qzqw) + 2*z_in*(qxqz+qyqw);
315 | y_out = 2*x_in*(qxqy+qzqw) + y_in*(-qx2+qy2-qz2+qw2) + 2*z_in*(qyqz-qxqw);
316 | z_out = 2*x_in*(qxqz-qyqw) + 2*y_in*(qyqz+qxqw) + z_in*(-qx2-qy2+qz2+qw2);
317 | /* Apply negative x_out to output */
318 | pose_out[0] = -x_out;
319 | pose_out[1] = -y_out;
320 | pose_out[2] = -z_out;
321 | pose_out[3] = qx;
322 | pose_out[4] = qy;
323 | pose_out[5] = qz;
324 | pose_out[6] = qw;
325 | return 0;
326 | }
327 |
328 | /* Taken from http:/www.j3d.org/matrix_faq/matrfaq_latest.html#Q54
329 | * Author: matrix_faq@j3d.org, hexapod@(no-spam)netcom.com
330 | * Formerly ftp://ftp.netcom.com/pub/he/hexapod/index.html,
331 | * http://www.glue.umd.edu/~rsrodger;
332 | * Checked (and modified) against
333 | * http://en.wikipedia.org/wiki/Rotation_representation_(mathematics)
334 | *
335 | * Further Note, from http://en.wikipedia.org/wiki/Rotation_matrix:
336 | * Efficient computation:
337 | *
338 | * Nq = w^2 + x^2 + y^2 + z^2
339 | * if Nq > 0.0 then s = 2/Nq else s = 0.0
340 | * X = x*s; Y = y*s; Z = z*s
341 | * wX = w*X; wY = w*Y; wZ = w*Z
342 | * xX = x*X; xY = x*Y; xZ = x*Z
343 | * yY = y*Y; yZ = y*Z; zZ = z*Z
344 | * [ 1.0-(yY+zZ) xY-wZ xZ+wY ]
345 | * [ xY+wZ 1.0-(xX+zZ) yZ-wX ]
346 | * [ xZ-wY yZ+wX 1.0-(xX+yY) ]
347 | */
348 | int cd_kin_quat_to_R(const double quat[4], double R[3][3])
349 | {
350 | double xx, xy, xz, xw, yy, yz, yw, zz, zw;
351 | xx = quat[0] * quat[0];
352 | xy = quat[0] * quat[1];
353 | xz = quat[0] * quat[2];
354 | xw = quat[0] * quat[3];
355 | yy = quat[1] * quat[1];
356 | yz = quat[1] * quat[2];
357 | yw = quat[1] * quat[3];
358 | zz = quat[2] * quat[2];
359 | zw = quat[2] * quat[3];
360 | R[0][0] = 1 - 2 * (yy + zz);
361 | R[0][1] = 2 * (xy - zw);
362 | R[0][2] = 2 * (xz + yw);
363 | R[1][0] = 2 * (xy + zw);
364 | R[1][1] = 1 - 2 * (xx + zz);
365 | R[1][2] = 2 * (yz - xw);
366 | R[2][0] = 2 * (xz - yw);
367 | R[2][1] = 2 * (yz + xw);
368 | R[2][2] = 1 - 2 * (xx + yy);
369 | return 0;
370 | }
371 |
372 | int cd_kin_pose_to_H(const double pose[7], double H[4][4], int fill_bottom)
373 | {
374 | double xx, xy, xz, xw, yy, yz, yw, zz, zw;
375 | xx = pose[3] * pose[3];
376 | xy = pose[3] * pose[4];
377 | xz = pose[3] * pose[5];
378 | xw = pose[3] * pose[6];
379 | yy = pose[4] * pose[4];
380 | yz = pose[4] * pose[5];
381 | yw = pose[4] * pose[6];
382 | zz = pose[5] * pose[5];
383 | zw = pose[5] * pose[6];
384 | H[0][0] = 1 - 2 * (yy + zz);
385 | H[0][1] = 2 * (xy - zw);
386 | H[0][2] = 2 * (xz + yw);
387 | H[1][0] = 2 * (xy + zw);
388 | H[1][1] = 1 - 2 * (xx + zz);
389 | H[1][2] = 2 * (yz - xw);
390 | H[2][0] = 2 * (xz - yw);
391 | H[2][1] = 2 * (yz + xw);
392 | H[2][2] = 1 - 2 * (xx + yy);
393 | H[0][3] = pose[0];
394 | H[1][3] = pose[1];
395 | H[2][3] = pose[2];
396 | if (fill_bottom)
397 | {
398 | H[3][0] = 0.0;
399 | H[3][1] = 0.0;
400 | H[3][2] = 0.0;
401 | H[3][3] = 1.0;
402 | }
403 | return 0;
404 | }
405 |
406 | int cd_kin_pose_to_dR(const double pose[7], double d[3], double R[3][3])
407 | {
408 | cd_kin_quat_to_R(pose+3, R);
409 | d[0] = pose[0];
410 | d[1] = pose[1];
411 | d[2] = pose[2];
412 | return 0;
413 | }
414 |
415 | /* note that we can't easily use const double R[3][3] here,
416 | * due to
417 | */
418 | int cd_kin_quat_from_R(double quat[4], double R[3][3])
419 | {
420 | double xx4, yy4, zz4, ww4; /* 4 times each component */
421 | double v4; /* 4/v with v the biggest of x, y, z, w */
422 | xx4 = 1.0 + R[0][0] - R[1][1] - R[2][2];
423 | yy4 = 1.0 - R[0][0] + R[1][1] - R[2][2];
424 | zz4 = 1.0 - R[0][0] - R[1][1] + R[2][2];
425 | ww4 = 1.0 + R[0][0] + R[1][1] + R[2][2];
426 | if (xx4 > yy4 && xx4 > zz4 && xx4 > ww4)
427 | {
428 | quat[0] = sqrt(0.25*xx4);
429 | v4 = 0.25 / quat[0];
430 | quat[1] = v4 * (R[1][0] + R[0][1]);
431 | quat[2] = v4 * (R[0][2] + R[2][0]);
432 | quat[3] = v4 * (R[2][1] - R[1][2]);
433 | }
434 | else if (yy4 > zz4 && yy4 > ww4)
435 | {
436 | quat[1] = sqrt(0.25*yy4);
437 | v4 = 0.25 / quat[1];
438 | quat[0] = v4 * (R[1][0] + R[0][1]);
439 | quat[2] = v4 * (R[2][1] + R[1][2]);
440 | quat[3] = v4 * (R[0][2] - R[2][0]);
441 | }
442 | else if (zz4 > ww4)
443 | {
444 | quat[2] = sqrt(0.25*zz4);
445 | v4 = 0.25 / quat[2];
446 | quat[0] = v4 * (R[0][2] + R[2][0]);
447 | quat[1] = v4 * (R[2][1] + R[1][2]);
448 | quat[3] = v4 * (R[1][0] - R[0][1]);
449 | }
450 | else
451 | {
452 | quat[3] = sqrt(0.25*ww4);
453 | v4 = 0.25 / quat[3];
454 | quat[0] = v4 * (R[2][1] - R[1][2]);
455 | quat[1] = v4 * (R[0][2] - R[2][0]);
456 | quat[2] = v4 * (R[1][0] - R[0][1]);
457 | }
458 | return 0;
459 | }
460 |
461 | int cd_kin_pose_from_H(double pose[7], double H[3][4])
462 | {
463 | double t, r, s;
464 | t = 1.0 + H[0][0] + H[1][1] + H[2][2];
465 | if (t > 0.000001)
466 | {
467 | r = sqrt(t);
468 | s = 0.5 / r;
469 | pose[3] = (H[2][1] - H[1][2]) * s;
470 | pose[4] = (H[0][2] - H[2][0]) * s;
471 | pose[5] = (H[1][0] - H[0][1]) * s;
472 | pose[6] = 0.5 * r;
473 | }
474 | else if (H[0][0] > H[1][1] && H[0][0] > H[2][2])
475 | {
476 | /* Rxx largest */
477 | r = sqrt(1.0 + H[0][0] - H[1][1] - H[2][2]);
478 | s = 0.5 / r;
479 | pose[3] = 0.5 * r;
480 | pose[4] = (H[0][1] + H[1][0]) * s;
481 | pose[5] = (H[0][2] + H[2][0]) * s;
482 | pose[6] = (H[2][1] - H[1][2]) * s;
483 | }
484 | else if (H[1][1] > H[2][2])
485 | {
486 | /* Ryy largest */
487 | r = sqrt(1.0 - H[0][0] + H[1][1] - H[2][2]);
488 | s = 0.5 / r;
489 | pose[3] = (H[1][0] + H[0][1]) * s;
490 | pose[4] = 0.5 * r;
491 | pose[5] = (H[1][2] + H[2][1]) * s;
492 | pose[6] = (H[0][2] - H[2][0]) * s;
493 | }
494 | else
495 | {
496 | /* Rzz largest */
497 | r = sqrt(1.0 - H[0][0] - H[1][1] + H[2][2]);
498 | s = 0.5 / r;
499 | pose[3] = (H[2][0] + H[0][2]) * s;
500 | pose[4] = (H[2][1] + H[1][2]) * s;
501 | pose[5] = 0.5 * r;
502 | pose[6] = (H[1][0] - H[0][1]) * s;
503 | }
504 | pose[0] = H[0][3];
505 | pose[1] = H[1][3];
506 | pose[2] = H[2][3];
507 | return 0;
508 | }
509 |
510 | int cd_kin_pose_from_dR(double pose[7], const double d[3], double R[3][3])
511 | {
512 | cd_kin_quat_from_R(pose+3, R);
513 | pose[0] = d[0];
514 | pose[1] = d[1];
515 | pose[2] = d[2];
516 | return 0;
517 | }
518 |
519 | int cd_kin_quat_to_axisangle(const double quat[4], double axis[3], double *angle)
520 | {
521 | double a2;
522 | double sina2inv;
523 | a2 = acos(quat[3]);
524 | *angle = 2.0*a2;
525 | sina2inv = 1.0/sin(a2);
526 | axis[0] = sina2inv * quat[0];
527 | axis[1] = sina2inv * quat[1];
528 | axis[2] = sina2inv * quat[2];
529 | return 0;
530 | }
531 |
532 | int cd_kin_quat_from_axisangle(double quat[4], const double axis[3], const double angle)
533 | {
534 | double a2;
535 | double sina2;
536 | a2 = 0.5*angle;
537 | quat[3] = cos(a2);
538 | sina2 = sin(a2);
539 | quat[0] = sina2 * axis[0];
540 | quat[1] = sina2 * axis[1];
541 | quat[2] = sina2 * axis[2];
542 | return 0;
543 | }
544 |
545 | /* using Rodrigues' rotation formula
546 | * http://en.wikipedia.org/wiki/Rodrigues%27_rotation_formula */
547 | int cd_kin_axisangle_rotate(const double axis[3], const double angle,
548 | const double pos_in[3], double pos_out[3])
549 | {
550 | double v[3];
551 | double axisdotv;
552 | cd_mat_memcpy(v, pos_in, 3, 1);
553 | cd_mat_set_zero(pos_out, 3, 1);
554 | cd_mat_cross(axis, v, pos_out);
555 | cd_mat_scale(pos_out, 3, 1, sin(angle));
556 | cblas_daxpy(3, cos(angle), v,1, pos_out,1);
557 | axisdotv = cblas_ddot(3, axis,1, v,1);
558 | cblas_daxpy(3, axisdotv*(1-cos(angle)), axis,1, pos_out,1);
559 | return 0;
560 | }
561 |
562 | /* exponential map, so(3) -> SO(3) */
563 | int cd_kin_axisangle_to_R(const double axis[3], const double angle, double R[3][3])
564 | {
565 | double x, y, z;
566 | double s;
567 | double cm;
568 | s = sin(angle);
569 | cm = 1.0 - cos(angle);
570 | x = axis[0];
571 | y = axis[1];
572 | z = axis[2];
573 | R[0][0] = 1.0 - cm*(y*y + z*z);
574 | R[0][1] = -s*z + cm*x*y;
575 | R[0][2] = s*y + cm*x*z;
576 | R[1][0] = s*z + cm*x*y;
577 | R[1][1] = 1.0 - cm*(x*x + z*z);
578 | R[1][2] = -s*x + cm*y*z;
579 | R[2][0] = -s*y + cm*x*z;
580 | R[2][1] = s*x + cm*y*z;
581 | R[2][2] = 1.0 - cm*(x*x + y*y);
582 | return 0;
583 | }
584 |
585 | int cd_kin_quat_to_ypr(const double quat[4], double ypr[3])
586 | {
587 | double qx, qy, qz, qw;
588 | double sinp2;
589 | qx = quat[0];
590 | qy = quat[1];
591 | qz = quat[2];
592 | qw = quat[3];
593 | sinp2 = qw*qy-qz*qx;
594 | if (sinp2 > 0.49999)
595 | {
596 | ypr[0] = -2.0*atan2(qx,qw);
597 | ypr[1] = 0.25*TAU;
598 | ypr[2] = 0.0;
599 | }
600 | else if (sinp2 < -0.49999)
601 | {
602 | ypr[0] = 2.0*atan2(qx,qw);
603 | ypr[1] = -0.25*TAU;
604 | ypr[2] = 0.0;
605 | }
606 | else
607 | {
608 | ypr[0] = atan2(2.0*(qw*qz+qx*qy), 1.0 - 2.0*(qy*qy+qz*qz));
609 | ypr[1] = asin(2.0*sinp2);
610 | ypr[2] = atan2(2.0*(qw*qx+qy*qz), 1.0 - 2.0*(qx*qx+qy*qy));
611 | }
612 | return 0;
613 | }
614 |
615 | int cd_kin_pose_to_xyzypr(const double pose[7], double xyzypr[6])
616 | {
617 | double qx, qy, qz, qw;
618 | double sinp2;
619 | qx = pose[3];
620 | qy = pose[4];
621 | qz = pose[5];
622 | qw = pose[6];
623 | xyzypr[0] = pose[0];
624 | xyzypr[1] = pose[1];
625 | xyzypr[2] = pose[2];
626 | sinp2 = qw*qy-qz*qx;
627 | if (sinp2 > 0.49999)
628 | {
629 | xyzypr[3] = -2.0*atan2(qx,qw);
630 | xyzypr[4] = 0.25*TAU;
631 | xyzypr[5] = 0.0;
632 | }
633 | else if (sinp2 < -0.49999)
634 | {
635 | xyzypr[3] = 2.0*atan2(qx,qw);
636 | xyzypr[4] = -0.25*TAU;
637 | xyzypr[5] = 0.0;
638 | }
639 | else
640 | {
641 | xyzypr[3] = atan2(2.0*(qw*qz+qx*qy), 1.0 - 2.0*(qy*qy+qz*qz));
642 | xyzypr[4] = asin(2.0*sinp2);
643 | xyzypr[5] = atan2(2.0*(qw*qx+qy*qz), 1.0 - 2.0*(qx*qx+qy*qy));
644 | }
645 | return 0;
646 | }
647 |
648 | /* for now, dont deal with gimbal lock! */
649 | int cd_kin_quat_to_ypr_J(const double quat[4], double J[3][4])
650 | {
651 | double qx, qy, qz, qw;
652 | double nu, de; /* numerator, denominator */
653 | double as; /* argsin arg */
654 | qx = quat[0];
655 | qy = quat[1];
656 | qz = quat[2];
657 | qw = quat[3];
658 | /* yaw */
659 | nu = 2.0*(qw*qz+qx*qy);
660 | de = 1.0 - 2.0*(qy*qy+qz*qz);
661 | J[0][0] = de/(de*de+nu*nu)*(2.0*qy);
662 | J[0][1] = de/(de*de+nu*nu)*(2.0*qx) - nu/(de*de+nu*nu)*(-2.0*2.0*qy);
663 | J[0][2] = de/(de*de+nu*nu)*(2.0*qw) - nu/(de*de+nu*nu)*(-2.0*2.0*qz);
664 | J[0][3] = de/(de*de+nu*nu)*(2.0*qz);
665 | /* pitch */
666 | as = 2.0 * (qw*qy-qz*qx);
667 | J[1][0] = 1.0/sqrt(1.0-as*as)*2.0*(-qz);
668 | J[1][1] = 1.0/sqrt(1.0-as*as)*2.0*( qw);
669 | J[1][2] = 1.0/sqrt(1.0-as*as)*2.0*(-qx);
670 | J[1][3] = 1.0/sqrt(1.0-as*as)*2.0*( qy);
671 | /* roll */
672 | nu = 2.0*(qw*qx+qy*qz);
673 | de = 1.0 - 2.0*(qx*qx+qy*qy);
674 | J[2][0] = de/(de*de+nu*nu)*(2.0*qw) - nu/(de*de+nu*nu)*(-2.0*2.0*qx);
675 | J[2][1] = de/(de*de+nu*nu)*(2.0*qz) - nu/(de*de+nu*nu)*(-2.0*2.0*qy);
676 | J[2][2] = de/(de*de+nu*nu)*(2.0*qy);
677 | J[2][3] = de/(de*de+nu*nu)*(2.0*qx);
678 | return 0;
679 | }
680 |
681 | /* for now, dont deal with gimbal lock! */
682 | int cd_kin_pose_to_xyzypr_J(const double pose[7], double J[6][7])
683 | {
684 | double qx, qy, qz, qw;
685 | double nu, de; /* numerator, denominator */
686 | double as; /* argsin arg */
687 | qx = pose[3];
688 | qy = pose[4];
689 | qz = pose[5];
690 | qw = pose[6];
691 | /* position part */
692 | cd_mat_set_zero(*J, 6, 7);
693 | J[0][0] = 1.0;
694 | J[1][1] = 1.0;
695 | J[2][2] = 1.0;
696 | /* yaw */
697 | nu = 2.0*(qw*qz+qx*qy);
698 | de = 1.0 - 2.0*(qy*qy+qz*qz);
699 | J[3][3] = de/(de*de+nu*nu)*(2.0*qy);
700 | J[3][4] = de/(de*de+nu*nu)*(2.0*qx) - nu/(de*de+nu*nu)*(-2.0*2.0*qy);
701 | J[3][5] = de/(de*de+nu*nu)*(2.0*qw) - nu/(de*de+nu*nu)*(-2.0*2.0*qz);
702 | J[3][6] = de/(de*de+nu*nu)*(2.0*qz);
703 | /* pitch */
704 | as = 2.0 * (qw*qy-qz*qx);
705 | J[4][3] = 1.0/sqrt(1.0-as*as)*2.0*(-qz);
706 | J[4][4] = 1.0/sqrt(1.0-as*as)*2.0*( qw);
707 | J[4][5] = 1.0/sqrt(1.0-as*as)*2.0*(-qx);
708 | J[4][6] = 1.0/sqrt(1.0-as*as)*2.0*( qy);
709 | /* roll */
710 | nu = 2.0*(qw*qx+qy*qz);
711 | de = 1.0 - 2.0*(qx*qx+qy*qy);
712 | J[5][3] = de/(de*de+nu*nu)*(2.0*qw) - nu/(de*de+nu*nu)*(-2.0*2.0*qx);
713 | J[5][4] = de/(de*de+nu*nu)*(2.0*qz) - nu/(de*de+nu*nu)*(-2.0*2.0*qy);
714 | J[5][5] = de/(de*de+nu*nu)*(2.0*qy);
715 | J[5][6] = de/(de*de+nu*nu)*(2.0*qx);
716 | return 0;
717 | }
718 |
719 | int cd_kin_quat_from_ypr(double quat[4], const double ypr[3])
720 | {
721 | double cy2, sy2, cp2, sp2, cr2, sr2;
722 | cy2 = cos(0.5 * ypr[0]);
723 | sy2 = sin(0.5 * ypr[0]);
724 | cp2 = cos(0.5 * ypr[1]);
725 | sp2 = sin(0.5 * ypr[1]);
726 | cr2 = cos(0.5 * ypr[2]);
727 | sr2 = sin(0.5 * ypr[2]);
728 | quat[0] = -sy2*sp2*cr2 + cy2*cp2*sr2; /* qx */
729 | quat[1] = cy2*sp2*cr2 + sy2*cp2*sr2; /* qy */
730 | quat[2] = -cy2*sp2*sr2 + sy2*cp2*cr2; /* qz */
731 | quat[3] = sy2*sp2*sr2 + cy2*cp2*cr2; /* qw */
732 | return 0;
733 | }
734 |
735 | int cd_kin_pose_from_xyzypr(double pose[7], const double xyzypr[6])
736 | {
737 | double cy2, sy2, cp2, sp2, cr2, sr2;
738 | cy2 = cos(0.5 * xyzypr[3]);
739 | sy2 = sin(0.5 * xyzypr[3]);
740 | cp2 = cos(0.5 * xyzypr[4]);
741 | sp2 = sin(0.5 * xyzypr[4]);
742 | cr2 = cos(0.5 * xyzypr[5]);
743 | sr2 = sin(0.5 * xyzypr[5]);
744 | pose[0] = xyzypr[0];
745 | pose[1] = xyzypr[1];
746 | pose[2] = xyzypr[2];
747 | pose[3] = -sy2*sp2*cr2 + cy2*cp2*sr2; /* qx */
748 | pose[4] = cy2*sp2*cr2 + sy2*cp2*sr2; /* qy */
749 | pose[5] = -cy2*sp2*sr2 + sy2*cp2*cr2; /* qz */
750 | pose[6] = sy2*sp2*sr2 + cy2*cp2*cr2; /* qw */
751 | return 0;
752 | }
753 |
754 | int cd_kin_pose_to_pos_quat(const double pose[7], double pos[3], double quat[4])
755 | {
756 | int i;
757 | if (pos) for (i=0; i<3; i++) pos[i] = pose[i];
758 | if (quat) for (i=0; i<4; i++) quat[i] = pose[3+i];
759 | return 0;
760 | }
761 |
762 | int cd_kin_pose_from_pos_quat(double pose[7], const double pos[3], const double quat[4])
763 | {
764 | int i;
765 | if (pos) for (i=0; i<3; i++) pose[i] = pos[i];
766 | else for (i=0; i<3; i++) pose[i] = 0.0;
767 | if (quat) for (i=0; i<4; i++) pose[3+i] = quat[i];
768 | else for (i=0; i<4; i++) pose[3+i] = i==3 ? 1.0 : 0.0;
769 | return 0;
770 | }
771 |
772 | int cd_kin_pose_from_op(double pose[7], const double from[3], const double to[3], double * const lenp)
773 | {
774 | double to_diff[3];
775 | to_diff[0] = to[0];
776 | to_diff[1] = to[1];
777 | to_diff[2] = to[2];
778 | if (from)
779 | {
780 | to_diff[0] -= from[0];
781 | to_diff[1] -= from[1];
782 | to_diff[2] -= from[2];
783 | }
784 | cd_kin_pose_from_op_diff(pose, from, to_diff, lenp);
785 | return 0;
786 | }
787 |
788 | int cd_kin_pose_from_op_diff(double pose[7], const double from[3], const double to_diff[3], double * const lenp)
789 | {
790 | double d[3];
791 | double R[3][3];
792 | double len;
793 |
794 | if (from)
795 | {
796 | d[0] = from[0];
797 | d[1] = from[1];
798 | d[2] = from[2];
799 | }
800 | else
801 | {
802 | d[0] = 0.0;
803 | d[1] = 0.0;
804 | d[2] = 0.0;
805 | }
806 |
807 | /* Define Z axis in direction of arrow */
808 | len = cblas_dnrm2(3, to_diff, 1);
809 | if (lenp) *lenp = len;
810 | R[0][2] = to_diff[0] / len;
811 | R[1][2] = to_diff[1] / len;
812 | R[2][2] = to_diff[2] / len;
813 |
814 | /* Define other axes */
815 | if (fabs(R[0][2]) > 0.9)
816 | {
817 | /* Z is too close to e1, but sufficiently far from e2;
818 | * cross e2 with Z to get X (and normalize) */
819 | len = sqrt(R[2][2]*R[2][2] + R[0][2]*R[0][2]);
820 | R[0][0] = R[2][2] / len;
821 | R[1][0] = 0.0;
822 | R[2][0] = -R[0][2] / len;
823 | /* Then Y = Z x X */
824 | R[0][1] = R[1][2] * R[2][0] - R[2][2] * R[1][0];
825 | R[1][1] = R[2][2] * R[0][0] - R[0][2] * R[2][0];
826 | R[2][1] = R[0][2] * R[1][0] - R[1][2] * R[0][0];
827 | }
828 | else
829 | {
830 | /* Z is sufficiently far from e1;
831 | * cross Z with e1 to get Y (and normalize) */
832 | len = sqrt(R[2][2]*R[2][2] + R[1][2]*R[1][2]);
833 | R[0][1] = 0.0;
834 | R[1][1] = R[2][2] / len;
835 | R[2][1] = -R[1][2] / len;
836 | /* Then X = Y x Z */
837 | R[0][0] = R[1][1] * R[2][2] - R[2][1] * R[1][2];
838 | R[1][0] = R[2][1] * R[0][2] - R[0][1] * R[2][2];
839 | R[2][0] = R[0][1] * R[1][2] - R[1][1] * R[0][2];
840 | }
841 |
842 | cd_kin_pose_from_dR(pose, d, R);
843 | return 0;
844 | }
845 |
--------------------------------------------------------------------------------
/src/libcd/kin.h:
--------------------------------------------------------------------------------
1 | /** \file kin.h
2 | * \brief Interface to cd_kin, a collection of useful routines for
3 | * kinematics.
4 | * \author Christopher Dellin
5 | * \date 2010-2012
6 | */
7 |
8 | /* (C) Copyright 2010-2013 Carnegie Mellon University */
9 |
10 | /* This module (cd_kin) is part of libcd.
11 | *
12 | * This module of libcd is free software: you can redistribute it
13 | * and/or modify it under the terms of the GNU General Public License as
14 | * published by the Free Software Foundation, either version 3 of the
15 | * License, or (at your option) any later version.
16 | *
17 | * This module of libcd is distributed in the hope that it will be
18 | * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 | * GNU General Public License for more details.
21 | *
22 | * A copy of the GNU General Public License is provided with libcd
23 | * (license-gpl.txt) and is also available at .
24 | */
25 |
26 | #ifndef CD_KIN_H
27 | #define CD_KIN_H
28 |
29 |
30 | int cd_kin_quat_identity(double quat[4]);
31 | int cd_kin_pose_identity(double pose[7]);
32 |
33 | int cd_kin_quat_normalize(double quat[4]);
34 | int cd_kin_pose_normalize(double pose[7]);
35 |
36 | int cd_kin_quat_flip_closerto(double quat[4], const double target[4]);
37 | int cd_kin_pose_flip_closerto(double pose[7], const double target[7]);
38 |
39 |
40 | /* composition */
41 | /* qab * qbc = qac
42 | * aka Hamilton product;
43 | * it's OK if output is either of the inputs */
44 | int cd_kin_quat_compose(const double quat_ab[4], const double quat_bc[4], double quat_ac[4]);
45 | int cd_kin_pose_compose(const double pose_ab[7], const double pose_bc[7], double pose_ac[7]);
46 |
47 | /* Do the same, but for a 3d pos, not a full pose */
48 | int cd_kin_pose_compos(const double pose_ab[7], const double pos_bc[3], double pos_ac[3]);
49 |
50 | /* this is rotation, vac = q vbc q* */
51 | int cd_kin_quat_compose_vec(const double quat_ab[4], const double vec_bc[3], double vec_ac[3]);
52 | /* Do the same, but just rotate a 3d vector (vel,acc), not a position vector */
53 | int cd_kin_pose_compose_vec(const double pose_ab[7], const double vec_bc[3], double vec_ac[3]);
54 |
55 | /* note conf equals inverse for unit quaternions */
56 | int cd_kin_quat_invert(const double quat_in[4], double quat_out[4]);
57 | int cd_kin_pose_invert(const double pose_in[7], double pose_out[7]);
58 |
59 |
60 | /* conversion to/from rotation matrices */
61 | int cd_kin_quat_to_R(const double quat[4], double R[3][3]);
62 | int cd_kin_pose_to_H(const double pose[7], double H[4][4], int fill_bottom);
63 | int cd_kin_pose_to_dR(const double pose[7], double d[3], double R[3][3]);
64 |
65 | int cd_kin_quat_from_R(double quat[4], double R[3][3]);
66 | int cd_kin_pose_from_H(double pose[7], double H[3][4]);
67 | int cd_kin_pose_from_dR(double pose[7], const double d[3], double R[3][3]);
68 |
69 |
70 | /* conversion to/from axis-angle */
71 | int cd_kin_quat_to_axisangle(const double quat[4], double axis[3], double *angle);
72 | int cd_kin_quat_from_axisangle(double quat[4], const double axis[3], const double angle);
73 |
74 | /* this is the equivalent of cd_kin_quat_compose_vecs above */
75 | int cd_kin_axisangle_rotate(const double axis[3], const double angle,
76 | const double pos_in[3], double pos_out[3]);
77 |
78 | int cd_kin_axisangle_to_R(const double axis[3], const double angle, double R[3][3]);
79 |
80 |
81 | /* conversion to/from yaw-pitch-roll airplane euler angles */
82 | int cd_kin_quat_to_ypr(const double quat[4], double ypr[3]);
83 | int cd_kin_pose_to_xyzypr(const double pose[7], double xyzypr[6]);
84 |
85 | int cd_kin_quat_to_ypr_J(const double quat[4], double J[3][4]);
86 | int cd_kin_pose_to_xyzypr_J(const double pose[7], double J[6][7]);
87 |
88 | int cd_kin_quat_from_ypr(double quat[4], const double ypr[3]);
89 | int cd_kin_pose_from_xyzypr(double pose[7], const double xyzypr[6]);
90 |
91 |
92 | /* convert between pose and pos+quat */
93 | int cd_kin_pose_to_pos_quat(const double pose[7], double pos[3], double quat[4]);
94 | int cd_kin_pose_from_pos_quat(double pose[7], const double pos[3], const double quat[4]);
95 |
96 |
97 | /* get an arbitrary pose from specification */
98 | int cd_kin_pose_from_op(double pose[7], const double from[3], const double to[3], double * const lenp);
99 | int cd_kin_pose_from_op_diff(double pose[7], const double from[3], const double to_diff[3], double * const lenp);
100 |
101 | #endif /* CD_KIN_H */
102 |
--------------------------------------------------------------------------------
/src/libcd/mat.c:
--------------------------------------------------------------------------------
1 | /** \file mat.h
2 | * \brief Interface to cd_mat, a collection of useful matrix routines.
3 | * \author Christopher Dellin
4 | * \date 2011-2012
5 | */
6 |
7 | /* (C) Copyright 2011-2013 Carnegie Mellon University */
8 |
9 | /* This module (cd_mat) is part of libcd.
10 | *
11 | * This module of libcd is free software: you can redistribute it
12 | * and/or modify it under the terms of the GNU General Public License as
13 | * published by the Free Software Foundation, either version 3 of the
14 | * License, or (at your option) any later version.
15 | *
16 | * This module of libcd is distributed in the hope that it will be
17 | * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 | * GNU General Public License for more details.
20 | *
21 | * A copy of the GNU General Public License is provided with libcd
22 | * (license-gpl.txt) and is also available at .
23 | */
24 |
25 | #include
26 | #include
27 | #include
28 | #include "mat.h"
29 |
30 | int cd_mat_set_zero(double * A, int m, int n)
31 | {
32 | int i, j;
33 | for (i=0; i");
144 | return buf;
145 | }
146 |
147 | int cd_mat_vec_fprintf(FILE * stream, const char * prefix,
148 | const double * a, int n, const char * start, const char * dblfmt,
149 | const char * sep, const char * end, const char * suffix)
150 | {
151 | int j;
152 | FILE * x_stream = stream ? stream : stdout;
153 | const char * x_prefix = prefix ? prefix : "";
154 | const char * x_start = start ? start : "< ";
155 | const char * x_dblfmt = dblfmt ? dblfmt : "%8.4f";
156 | const char * x_sep = sep ? sep : ", ";
157 | const char * x_end = end ? end : " >";
158 | const char * x_suffix = suffix ? suffix : "\n";
159 | fputs(x_prefix, x_stream);
160 | fputs(x_start, x_stream);
161 | for (j=0; j0) fputs(x_sep, x_stream);
164 | fprintf(x_stream, x_dblfmt, a[j]);
165 | }
166 | fputs(x_end, x_stream);
167 | fputs(x_suffix, x_stream);
168 | return 0;
169 | }
170 |
171 |
172 | int cd_mat_vec_print(const char * prefix, const double * a, int n)
173 | {
174 | cd_mat_vec_fprintf(0, prefix, a, n, 0, 0, 0, 0, 0);
175 | return 0;
176 | }
177 |
--------------------------------------------------------------------------------
/src/libcd/mat.h:
--------------------------------------------------------------------------------
1 | /** \file mat.h
2 | * \brief Interface to cd_mat, a collection of useful matrix routines.
3 | * \author Christopher Dellin
4 | * \date 2011-2012
5 | */
6 |
7 | /* (C) Copyright 2011-2013 Carnegie Mellon University */
8 |
9 | /* This module (cd_mat) is part of libcd.
10 | *
11 | * This module of libcd is free software: you can redistribute it
12 | * and/or modify it under the terms of the GNU General Public License as
13 | * published by the Free Software Foundation, either version 3 of the
14 | * License, or (at your option) any later version.
15 | *
16 | * This module of libcd is distributed in the hope that it will be
17 | * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 | * GNU General Public License for more details.
20 | *
21 | * A copy of the GNU General Public License is provided with libcd
22 | * (license-gpl.txt) and is also available at .
23 | */
24 |
25 | #ifndef CD_MAT_H
26 | #define CD_MAT_H
27 |
28 | #include
29 |
30 | int cd_mat_set_zero(double * A, int m, int n);
31 | int cd_mat_set_diag(double * A, int m, int n, double value);
32 | int cd_mat_transpose(double * A, int mn);
33 | int cd_mat_fill(double * A, int m, int n, ...);
34 | int cd_mat_memcpy(double * dst, const double * src, const int m, const int n);
35 | int cd_mat_memcpy_transpose(double * dst, const double * src, int m, int n);
36 | int cd_mat_add(double * dst, const double * src, int m, int n);
37 | int cd_mat_sub(double * dst, const double * src, int m, int n);
38 | int cd_mat_scale(double * A, int m, int n, double fac);
39 |
40 | double cd_mat_trace(double * A, int m, int n);
41 |
42 | int cd_mat_cross(const double a[3], const double b[3], double res[3]);
43 |
44 | /* THIS IS UGLY! */
45 | char * cd_mat_vec_sprintf(char * buf, double * a, int n);
46 |
47 | int cd_mat_vec_fprintf(FILE * stream, const char * prefix,
48 | const double * a, int n, const char * start, const char * dblfmt,
49 | const char * sep, const char * end, const char * suffix);
50 |
51 | int cd_mat_vec_print(const char * prefix, const double * a, int n);
52 |
53 | #endif /* CD_MAT_H */
54 |
--------------------------------------------------------------------------------
/src/libcd/os.c:
--------------------------------------------------------------------------------
1 | /** \file os.c
2 | * \brief Implementation of cd_os, a collection of os routines.
3 | * \author Christopher Dellin
4 | * \date 2012
5 | */
6 |
7 | /* (C) Copyright 2012-2013 Carnegie Mellon University */
8 |
9 | /* This module (cd_os) is part of libcd.
10 | *
11 | * This module of libcd is free software: you can redistribute it
12 | * and/or modify it under the terms of the GNU General Public License as
13 | * published by the Free Software Foundation, either version 3 of the
14 | * License, or (at your option) any later version.
15 | *
16 | * This module of libcd is distributed in the hope that it will be
17 | * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 | * GNU General Public License for more details.
20 | *
21 | * A copy of the GNU General Public License is provided with libcd
22 | * (license-gpl.txt) and is also available at .
23 | */
24 |
25 | /* note: we need POSIX.1b support in time.h */
26 | #include
27 | #include "os.h"
28 |
29 | int cd_os_timespec_set_zero(struct timespec * t)
30 | {
31 | t->tv_sec = 0;
32 | t->tv_nsec = 0;
33 | return 0;
34 | }
35 |
36 | int cd_os_timespec_add(struct timespec * dst, const struct timespec * src)
37 | {
38 | dst->tv_sec += src->tv_sec;
39 | dst->tv_nsec += src->tv_nsec;
40 | if (dst->tv_nsec > 999999999)
41 | {
42 | dst->tv_sec += 1;
43 | dst->tv_nsec -= 1000000000;
44 | }
45 | return 0;
46 | }
47 |
48 | int cd_os_timespec_sub(struct timespec * dst, const struct timespec * src)
49 | {
50 | dst->tv_sec -= src->tv_sec;
51 | dst->tv_nsec -= src->tv_nsec;
52 | if (dst->tv_nsec < 0)
53 | {
54 | dst->tv_sec -= 1;
55 | dst->tv_nsec += 1000000000;
56 | }
57 | return 0;
58 | }
59 |
60 | double cd_os_timespec_double(const struct timespec * src)
61 | {
62 | return src->tv_sec + ((double)(src->tv_nsec))/1000000000.0;
63 | }
64 |
--------------------------------------------------------------------------------
/src/libcd/os.h:
--------------------------------------------------------------------------------
1 | /** \file os.h
2 | * \brief Interface to cd_os, a collection of os routines.
3 | * \author Christopher Dellin
4 | * \date 2012
5 | */
6 |
7 | /* (C) Copyright 2012-2013 Carnegie Mellon University */
8 |
9 | /* This module (cd_os) is part of libcd.
10 | *
11 | * This module of libcd is free software: you can redistribute it
12 | * and/or modify it under the terms of the GNU General Public License as
13 | * published by the Free Software Foundation, either version 3 of the
14 | * License, or (at your option) any later version.
15 | *
16 | * This module of libcd is distributed in the hope that it will be
17 | * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 | * GNU General Public License for more details.
20 | *
21 | * A copy of the GNU General Public License is provided with libcd
22 | * (license-gpl.txt) and is also available at .
23 | */
24 |
25 | /* requires time.h (with POSIX.1b) */
26 |
27 | /* elapsed time functions (to be moved to cd_os)
28 | * useful for timing code;
29 | * see clock_gettime();
30 | * we use struct timespec, from the 1993 edition of the POSIX.1b standard
31 | * (IEEE Standard 1003.1b-1993)
32 | * note how these functions mirror those from cd_mat (-: */
33 |
34 | int cd_os_timespec_set_zero(struct timespec * t);
35 | int cd_os_timespec_add(struct timespec * dst, const struct timespec * src);
36 | int cd_os_timespec_sub(struct timespec * dst, const struct timespec * src);
37 | double cd_os_timespec_double(const struct timespec * src);
38 |
39 | /* ugh, I should really get inlining working
40 | * (see http://gcc.gnu.org/onlinedocs/gcc/Inline.html) */
41 |
42 | #define CD_OS_TIMESPEC_SET_ZERO(t) do { (t)->tv_sec = 0; (t)->tv_nsec = 0; } while (0)
43 |
44 | #define CD_OS_TIMESPEC_ADD(dst, src) do { (dst)->tv_sec += (src)->tv_sec; (dst)->tv_nsec += (src)->tv_nsec; \
45 | if ((dst)->tv_nsec > 999999999) { (dst)->tv_sec += 1; (dst)->tv_nsec -= 1000000000; } } while (0)
46 |
47 | #define CD_OS_TIMESPEC_SUB(dst, src) do { (dst)->tv_sec -= (src)->tv_sec; (dst)->tv_nsec -= (src)->tv_nsec; \
48 | if ((dst)->tv_nsec < 0) { (dst)->tv_sec -= 1; (dst)->tv_nsec += 1000000000; } } while (0)
49 |
50 | #define CD_OS_TIMESPEC_DOUBLE(src) ((src)->tv_sec + ((double)((src)->tv_nsec))/1000000000.0)
51 |
--------------------------------------------------------------------------------
/src/libcd/spatial.c:
--------------------------------------------------------------------------------
1 | /** \file spatial.c
2 | * \brief Implementation of cd_spatial, a collection of useful routines for
3 | * spatial vector algrbra.
4 | * \author Christopher Dellin
5 | * \date 2010-2012
6 | */
7 |
8 | /* (C) Copyright 2010-2013 Carnegie Mellon University */
9 |
10 | /* This module (cd_spatial) is part of libcd.
11 | *
12 | * This module of libcd is free software: you can redistribute it
13 | * and/or modify it under the terms of the GNU General Public License as
14 | * published by the Free Software Foundation, either version 3 of the
15 | * License, or (at your option) any later version.
16 | *
17 | * This module of libcd is distributed in the hope that it will be
18 | * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 | * GNU General Public License for more details.
21 | *
22 | * A copy of the GNU General Public License is provided with libcd
23 | * (license-gpl.txt) and is also available at .
24 | */
25 |
26 | #include
27 | #include
28 |
29 | #include "kin.h"
30 | #include "mat.h"
31 | #include "spatial.h"
32 |
33 | int cd_spatial_xm_to_pose(double xm[6][6], double pose[7])
34 | {
35 | int i, j;
36 | double temp3x3[3][3];
37 |
38 | cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasTrans, 3, 3, 3,
39 | 1.0, &xm[3][0],6, &xm[0][0],6, 0.0,&temp3x3[0][0],3);
40 | pose[0] = temp3x3[2][1];
41 | pose[1] = temp3x3[0][2];
42 | pose[2] = temp3x3[1][0];
43 |
44 | for (i=0; i<3; i++)
45 | for (j=0; j<3; j++)
46 | temp3x3[i][j] = xm[i][j];
47 | cd_kin_quat_from_R(pose+3, temp3x3);
48 |
49 | return 0;
50 | }
51 |
52 | int cd_spatial_xf_to_pose(double xf[6][6], double pose[7])
53 | {
54 | int i, j;
55 | double temp3x3[3][3];
56 |
57 | cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasTrans, 3, 3, 3,
58 | 1.0, &xf[0][3],6, &xf[0][0],6, 0.0,&temp3x3[0][0],3);
59 | pose[0] = temp3x3[2][1];
60 | pose[1] = temp3x3[0][2];
61 | pose[2] = temp3x3[1][0];
62 |
63 | for (i=0; i<3; i++)
64 | for (j=0; j<3; j++)
65 | temp3x3[i][j] = xf[i][j];
66 | cd_kin_quat_from_R(pose+3, temp3x3);
67 |
68 | return 0;
69 | }
70 |
71 | int cd_spatial_xm_from_pose(double xm[6][6], double pose[7])
72 | {
73 | int i, j;
74 | double R[3][3];
75 | double rx[3][3];
76 |
77 | cd_mat_set_zero(&xm[0][0], 6, 6);
78 |
79 | /* Fill rotation matrices */
80 | cd_kin_quat_to_R(pose+3, R);
81 | for (i=0; i<3; i++)
82 | for (j=0; j<3; j++)
83 | {
84 | xm[i][j] = R[i][j];
85 | xm[3+i][3+j] = R[i][j];
86 | }
87 |
88 | /* Get [rx], then fill [rx]R */
89 | rx[0][0] = 0.0;
90 | rx[0][1] = -pose[2];
91 | rx[0][2] = pose[1];
92 | rx[1][0] = pose[2];
93 | rx[1][1] = 0.0;
94 | rx[1][2] = -pose[0];
95 | rx[2][0] = -pose[1];
96 | rx[2][1] = pose[0];
97 | rx[2][2] = 0.0;
98 | cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, 3, 3, 3,
99 | 1.0, &rx[0][0],3, &R[0][0],3, 0.0,&xm[3][0],6);
100 |
101 | return 0;
102 | }
103 |
104 | int cd_spatial_xf_from_pose(double xf[6][6], double pose[7])
105 | {
106 | int i, j;
107 | double R[3][3];
108 | double rx[3][3];
109 |
110 | cd_mat_set_zero(&xf[0][0], 6, 6);
111 |
112 | /* Fill rotation matrices */
113 | cd_kin_quat_to_R(pose+3, R);
114 | for (i=0; i<3; i++)
115 | for (j=0; j<3; j++)
116 | {
117 | xf[i][j] = R[i][j];
118 | xf[3+i][3+j] = R[i][j];
119 | }
120 |
121 | /* Get [rx], then fill [rx]R */
122 | rx[0][0] = 0.0;
123 | rx[0][1] = -pose[2];
124 | rx[0][2] = pose[1];
125 | rx[1][0] = pose[2];
126 | rx[1][1] = 0.0;
127 | rx[1][2] = -pose[0];
128 | rx[2][0] = -pose[1];
129 | rx[2][1] = pose[0];
130 | rx[2][2] = 0.0;
131 | cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, 3, 3, 3,
132 | 1.0, &rx[0][0],3, &R[0][0],3, 0.0,&xf[0][3],6);
133 |
134 | return 0;
135 | }
136 |
137 | int cd_spatial_inertia_x(double pose_ab[7], double inertia_b[6][6], double inertia_a[6][6])
138 | {
139 | double pose_ba[7];
140 | double xm_ba[6][6];
141 | double i_x[6][6];
142 | cd_kin_pose_invert(pose_ab, pose_ba);
143 | cd_spatial_xm_from_pose(xm_ba, pose_ba);
144 | cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, 6, 6, 6,
145 | 1.0, &inertia_b[0][0],6, &xm_ba[0][0],6, 0.0,&i_x[0][0],6);
146 | cblas_dgemm(CblasRowMajor, CblasTrans, CblasNoTrans, 6, 6, 6,
147 | 1.0, &xm_ba[0][0],6, &i_x[0][0],6, 0.0,&inertia_a[0][0],6);
148 | return 0;
149 | }
150 |
151 |
152 | int cd_spatial_pose_from_spavel_unittime(double pose[7], double spavel[6])
153 | {
154 | double wdotv;
155 | double w2;
156 | double w;
157 | double c_cross;
158 | double c_v;
159 | double c_w;
160 | double axis[3];
161 | w2 = spavel[0]*spavel[0]+spavel[1]*spavel[1]+spavel[2]*spavel[2];
162 | wdotv = spavel[0]*spavel[3]+spavel[1]*spavel[4]+spavel[2]*spavel[5];
163 | if (w2 < 0.0000001)
164 | {
165 | /* what is the orientation stuff here? */
166 | cd_kin_quat_identity(pose+3);
167 | cblas_daxpy(3, 0.5-w2/48.0+w2*w2/3840.0-w2*w2*w2/645120.0,
168 | spavel,1, pose+3,1);
169 | pose[6] = 1.0 - w2/8.0 + w2*w2/384.0 - w2*w2*w2/46080.0;
170 | /* position coefficients */
171 | c_cross = 1.0/2.0 - w2/24.0 + w2*w2/720.0 - w2*w2*w2/40320.0;
172 | c_v = 1.0 - w2/6.0 + w2*w2/120.0 - w2*w2*w2/5040.0;
173 | c_w = 1.0/6.0 - w2/120.0 + w2*w2/5040.0 - w2*w2*w2/362880.0;
174 | c_w *= wdotv;
175 | }
176 | else
177 | {
178 | w = sqrt(w2);
179 | /* the orientation stuff is pretty easy */
180 | axis[0] = spavel[0] / w;
181 | axis[1] = spavel[1] / w;
182 | axis[2] = spavel[2] / w;
183 | cd_kin_quat_from_axisangle(pose+3, axis, w);
184 | /* position coefficients */
185 | c_cross = (1.0 - cos(w))/w2;
186 | c_v = sin(w)/w;
187 | c_w = (1.0 - c_v) * wdotv / w2;
188 | }
189 | /* do the position stuff */
190 | cd_mat_set_zero(pose, 3, 1);
191 | cd_mat_cross(spavel, spavel+3, pose);
192 | cd_mat_scale(pose, 3, 1, c_cross);
193 | cblas_daxpy(3, c_v, spavel+3,1, pose,1);
194 | cblas_daxpy(3, c_w, spavel,1, pose,1);
195 | return 0;
196 | }
197 |
198 | /* This is the exponential map from se(3) to SE(3)
199 | * spavel is twist coordinates of the pose
200 | * the H gives the pose of the body-fixed frame
201 | * originally at the origin */
202 | int cd_spatial_H_from_spavel_unittime(double H[4][4], double spavel[6])
203 | {
204 | double S[4][4];
205 | double S2[4][4];
206 | double wx, wy, wz, vx, vy, vz;
207 | double w2;
208 | double w;
209 | double s2;
210 | double s3;
211 | wx = spavel[0];
212 | wy = spavel[1];
213 | wz = spavel[2];
214 | vx = spavel[3];
215 | vy = spavel[4];
216 | vz = spavel[5];
217 | /* w */
218 | w2 = wx*wx + wy*wy + wz*wz;
219 | if (w2 < 0.0000001)
220 | {
221 | s2 = 1.0/2.0 - w2/24.0 + w2*w2/720.0 - w2*w2*w2/40320.0;
222 | s3 = 1.0/6.0 - w2/120.0 + w2*w2/5040.0 - w2*w2*w2/362880.0;
223 | }
224 | else
225 | {
226 | w = sqrt(w2);
227 | s2 = (1.0-cos(w)) / w2;
228 | s3 = (w-sin(w)) / (w*w2);
229 | }
230 | /* set S */
231 | S[0][0] = 0.0; S[0][1] = -wz; S[0][2] = wy; S[0][3] = vx;
232 | S[1][0] = wz; S[1][1] = 0.0; S[1][2] = -wx; S[1][3] = vy;
233 | S[2][0] = -wy; S[2][1] = wx; S[2][2] = 0.0; S[2][3] = vz;
234 | S[3][0] = 0.0; S[3][1] = 0.0; S[3][2] = 0.0; S[3][3] = 0.0;
235 | /* get S2 */
236 | cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, 4, 4, 4,
237 | 1.0, *S,4, *S,4, 0.0, *S2,4);
238 | /* set identity */
239 | cd_mat_set_diag(*H, 4, 4, 1.0);
240 | /* add in S (4x4 screw matrix) */
241 | cd_mat_add(*H, *S, 4, 4);
242 | /* Add in S^2 component */
243 | cblas_daxpy(12, s2, *S2,1, *H,1);
244 | /* Add in S^3 component */
245 | cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, 4, 4, 4,
246 | s3, *S,4, *S2,4, 1.0, *H,4);
247 | return 0;
248 | }
249 |
250 |
251 | /* Inverting transposes each 3x3 block individually */
252 | int cd_spatial_x_invert(double x[6][6])
253 | {
254 | double temp;
255 |
256 | #define SW(i,j,a,b) temp=x[i][j]; x[i][j]=x[a][b]; x[a][b]=temp;
257 | #define T3(i,j) SW(i,j+1, i+1,j) SW(i,j+2, i+2,j) SW(i+1,j+2, i+2,j+1)
258 |
259 | T3(0,0)
260 | T3(3,0)
261 | T3(0,3)
262 | T3(3,3)
263 |
264 | #undef SW
265 | #undef T3
266 |
267 | return 0;
268 | }
269 |
270 | int cd_spatial_v_to_pos(double vel[6], double pos[3])
271 | {
272 | cd_mat_cross(vel, pos, vel+3);
273 | return 0;
274 | }
275 |
276 | int cd_spatial_v_from_pos(double vel[6], double pos[3])
277 | {
278 | cd_mat_cross(pos, vel, vel+3);
279 | return 0;
280 | }
281 |
282 | int cd_spatial_f_to_pos(double force[6], double pos[3])
283 | {
284 | cd_mat_cross(force+3, pos, force);
285 | return 0;
286 | }
287 |
288 | int cd_spatial_f_from_pos(double force[6], double pos[3])
289 | {
290 | cd_mat_cross(pos, force+3, force);
291 | return 0;
292 | }
293 |
294 |
295 | int cd_spatial_pose_jac(double pose[7], double jac[6][7])
296 | {
297 | double x, y, z, qxt2, qyt2, qzt2, qwt2;
298 | x = pose[0];
299 | y = pose[1];
300 | z = pose[2];
301 | qxt2 = 2.0 * pose[3];
302 | qyt2 = 2.0 * pose[4];
303 | qzt2 = 2.0 * pose[5];
304 | qwt2 = 2.0 * pose[6];
305 | cd_mat_set_zero(&jac[0][0], 6, 7);
306 | /* Bottom left */
307 | jac[3][0] = 1.0;
308 | jac[4][1] = 1.0;
309 | jac[5][2] = 1.0;
310 | /* Top right */
311 | jac[0][3] = qwt2;
312 | jac[0][4] = -qzt2;
313 | jac[0][5] = qyt2;
314 | jac[0][6] = -qxt2;
315 | jac[1][3] = qzt2;
316 | jac[1][4] = qwt2;
317 | jac[1][5] = -qxt2;
318 | jac[1][6] = -qyt2;
319 | jac[2][3] = -qyt2;
320 | jac[2][4] = qxt2;
321 | jac[2][5] = qwt2;
322 | jac[2][6] = -qzt2;
323 | /* Bottom right */
324 | jac[3][3] = -z*qzt2 -y*qyt2;
325 | jac[3][4] = -z*qwt2 +y*qxt2;
326 | jac[3][5] = z*qxt2 +y*qwt2;
327 | jac[3][6] = z*qyt2 -y*qzt2;
328 | jac[4][3] = z*qwt2 +x*qyt2;
329 | jac[4][4] = -z*qzt2 -x*qxt2;
330 | jac[4][5] = z*qyt2 -x*qwt2;
331 | jac[4][6] = -z*qxt2 +x*qzt2;
332 | jac[5][3] = -y*qwt2 +x*qzt2;
333 | jac[5][4] = y*qzt2 +x*qwt2;
334 | jac[5][5] = -y*qyt2 -x*qxt2;
335 | jac[5][6] = y*qxt2 -x*qyt2;
336 | return 0;
337 | }
338 |
339 | int cd_spatial_pose_jac_inverse(double pose[7], double jac_inverse[7][6])
340 | {
341 | double x, y, z, qxd2, qyd2, qzd2, qwd2;
342 | x = pose[0];
343 | y = pose[1];
344 | z = pose[2];
345 | qxd2 = 0.5 * pose[3];
346 | qyd2 = 0.5 * pose[4];
347 | qzd2 = 0.5 * pose[5];
348 | qwd2 = 0.5 * pose[6];
349 | cd_mat_set_zero(&jac_inverse[0][0], 7, 6);
350 | /* Set upper left */
351 | jac_inverse[0][1] = z;
352 | jac_inverse[0][2] = -y;
353 | jac_inverse[1][0] = -z;
354 | jac_inverse[1][2] = x;
355 | jac_inverse[2][0] = y;
356 | jac_inverse[2][1] = -x;
357 | /* Set upper right */
358 | jac_inverse[0][3] = 1.0;
359 | jac_inverse[1][4] = 1.0;
360 | jac_inverse[2][5] = 1.0;
361 | /* Set lower left */
362 | jac_inverse[3][0] = qwd2;
363 | jac_inverse[3][1] = qzd2;
364 | jac_inverse[3][2] = -qyd2;
365 | jac_inverse[4][0] = -qzd2;
366 | jac_inverse[4][1] = qwd2;
367 | jac_inverse[4][2] = qxd2;
368 | jac_inverse[5][0] = qyd2;
369 | jac_inverse[5][1] = -qxd2;
370 | jac_inverse[5][2] = qwd2;
371 | jac_inverse[6][0] = -qxd2;
372 | jac_inverse[6][1] = -qyd2;
373 | jac_inverse[6][2] = -qzd2;
374 | return 0;
375 | }
376 |
377 | int cd_spatial_inertia_from_com(double inertia[6][6], double mass, double com[3], double Icom[3][3])
378 | {
379 | double x, y, z;
380 | if (com)
381 | {
382 | x = com[0];
383 | y = com[1];
384 | z = com[2];
385 | }
386 | else
387 | {
388 | x = 0.0;
389 | y = 0.0;
390 | z = 0.0;
391 | }
392 | /* Fill inertia matrix */
393 | cd_mat_set_zero(&inertia[0][0], 6, 6);
394 | /* Top left */
395 | inertia[0][0] = Icom[0][0] + mass*y*y + mass*z*z;
396 | inertia[0][1] = Icom[0][1] - mass*x*y;
397 | inertia[0][2] = Icom[0][2] - mass*x*z;
398 | inertia[1][0] = Icom[1][0] - mass*x*y;
399 | inertia[1][1] = Icom[1][1] + mass*x*x + mass*z*z;
400 | inertia[1][2] = Icom[1][2] - mass*y*z;
401 | inertia[2][0] = Icom[2][0] - mass*x*z;
402 | inertia[2][1] = Icom[2][1] - mass*y*z;
403 | inertia[2][2] = Icom[2][2] + mass*x*x + mass*y*y;
404 | /* Top right */
405 | inertia[0][4] = -mass*z;
406 | inertia[0][5] = mass*y;
407 | inertia[1][3] = mass*z;
408 | inertia[1][5] = -mass*x;
409 | inertia[2][3] = -mass*y;
410 | inertia[2][4] = mass*x;
411 | /* Bottom left */
412 | inertia[3][1] = mass*z;
413 | inertia[3][2] = -mass*y;
414 | inertia[4][0] = -mass*z;
415 | inertia[4][2] = mass*x;
416 | inertia[5][0] = mass*y;
417 | inertia[5][1] = -mass*x;
418 | /* Bottom right */
419 | inertia[3][3] = mass;
420 | inertia[4][4] = mass;
421 | inertia[5][5] = mass;
422 | return 0;
423 | }
424 |
425 | int cd_spatial_inertia_to_com(double inertia[6][6], double * massp, double com[3], double Icom[3][3])
426 | {
427 | double x, y, z;
428 | double mass;
429 | /* mass */
430 | mass = (inertia[3][3] + inertia[4][4] + inertia[5][5]) / 3.0;
431 | /* com location */
432 | x = 0.0;
433 | y = 0.0;
434 | z = 0.0;
435 | z -= inertia[0][4]; y += inertia[0][5];
436 | z += inertia[1][3]; x -= inertia[1][5];
437 | y -= inertia[2][3]; x += inertia[2][4];
438 | z += inertia[3][1]; y -= inertia[3][2];
439 | z -= inertia[4][0]; x += inertia[4][2];
440 | y += inertia[5][0]; x -= inertia[5][1];
441 | x /= 4.0 * mass;
442 | y /= 4.0 * mass;
443 | z /= 4.0 * mass;
444 | /* Icom */
445 | Icom[0][0] = inertia[0][0] - mass*y*y-+ mass*z*z;
446 | Icom[0][1] = inertia[0][1] + mass*x*y;
447 | Icom[0][2] = inertia[0][2] + mass*x*z;
448 | Icom[1][0] = inertia[1][0] + mass*x*y;
449 | Icom[1][1] = inertia[1][1] - mass*x*x - mass*z*z;
450 | Icom[1][2] = inertia[1][2] + mass*y*z;
451 | Icom[2][0] = inertia[2][0] + mass*x*z;
452 | Icom[2][1] = inertia[2][1] + mass*y*z;
453 | Icom[2][2] = inertia[2][2] - mass*x*x - mass*y*y;
454 | /* save */
455 | com[0] = x;
456 | com[1] = y;
457 | com[2] = z;
458 | *massp = mass;
459 | return 0;
460 | }
461 |
462 | int cd_spatial_inertia_sphere_solid(double pos[3], double mass, double radius, double inertia[6][6])
463 | {
464 | double Ielem;
465 | double Icom[3][3];
466 | Ielem = 0.4 * mass * radius * radius;
467 | Icom[0][0] = Ielem; Icom[0][1] = 0.0; Icom[0][2] = 0.0;
468 | Icom[1][0] = 0.0; Icom[1][1] = Ielem; Icom[1][2] = 0.0;
469 | Icom[2][0] = 0.0; Icom[2][1] = 0.0; Icom[2][2] = Ielem;
470 | return cd_spatial_inertia_from_com(inertia, mass, pos, Icom);
471 | }
472 |
473 | int cd_spatial_vxIv(double v[6], double I[6][6], double result[6])
474 | {
475 | double Iv[6];
476 | cblas_dgemv(CblasRowMajor, CblasNoTrans, 6, 6,
477 | 1.0, &I[0][0],6, v,1, 0.0,Iv,1);
478 | cd_mat_cross(v, Iv, result);
479 | cd_mat_cross(v+3, Iv+3, result);
480 | cd_mat_cross(v, Iv+3, result+3);
481 | return 0;
482 | }
483 |
484 | int cd_spatial_spring_damper(double pose[7], double vel[6],
485 | double pose_ref[7], double vel_ref[6], double force[6],
486 | double Klin, double Blin, double Kang, double Bang)
487 | {
488 | double cx, cy, cz;
489 | double cqx, cqy, cqz, cqw;
490 | double cwx, cwy, cwz;
491 | double cvx, cvy, cvz;
492 | double rx, ry, rz;
493 | double rqx, rqy, rqz, rqw;
494 | double rwx, rwy, rwz;
495 | double rvx, rvy, rvz;
496 |
497 | double rwqx, rwqy, rwqz, rwqw;
498 | double rcqx, rcqy, rcqz, rcqw;
499 | double angle, denom;
500 | double raax, raay, raaz;
501 | double qx2, qy2, qz2, qw2, qxqy, qxqz, qxqw, qyqz, qyqw, qzqw;
502 | double waax, waay, waaz;
503 |
504 | double fnx, fny, fnz, fx, fy, fz;
505 |
506 | /* Get current position[ orientation[ angular & linear velocity */
507 | cx = pose[0];
508 | cy = pose[1];
509 | cz = pose[2];
510 | cqx = pose[3];
511 | cqy = pose[4];
512 | cqz = pose[5];
513 | cqw = pose[6];
514 | cwx = vel[0];
515 | cwy = vel[1];
516 | cwz = vel[2];
517 | cvx = vel[3] + cz*cwy - cy*cwz;
518 | cvy = vel[4] - cz*cwx + cx*cwz;
519 | cvz = vel[5] + cy*cwx - cx*cwy;
520 |
521 | /* Get reference position[ orientation[ angular & linear velocity */
522 | rx = pose_ref[0];
523 | ry = pose_ref[1];
524 | rz = pose_ref[2];
525 | rqx = pose_ref[3];
526 | rqy = pose_ref[4];
527 | rqz = pose_ref[5];
528 | rqw = pose_ref[6];
529 | if (vel_ref)
530 | {
531 | rwx = vel_ref[0];
532 | rwy = vel_ref[1];
533 | rwz = vel_ref[2];
534 | rvx = vel_ref[3] + rz*rwy - ry*rwz;
535 | rvy = vel_ref[4] - rz*rwx + rx*rwz;
536 | rvz = vel_ref[5] + ry*rwx - rx*rwy;
537 | }
538 | else
539 | {
540 | rwx = 0.0;
541 | rwy = 0.0;
542 | rwz = 0.0;
543 | rvx = 0.0;
544 | rvy = 0.0;
545 | rvz = 0.0;
546 | }
547 |
548 | /* Negate reference orientation (now world orientation in ref frame) */
549 | rwqx = -rqx;
550 | rwqy = -rqy;
551 | rwqz = -rqz;
552 | rwqw = rqw;
553 | /* Compose reference quaternion with current quaternion
554 | * (now is orientation of current in reference frame) */
555 | rcqx = rwqw*cqx + rwqx*cqw + rwqy*cqz - rwqz*cqy;
556 | rcqy = rwqw*cqy - rwqx*cqz + rwqy*cqw + rwqz*cqx;
557 | rcqz = rwqw*cqz + rwqx*cqy - rwqy*cqx + rwqz*cqw;
558 | rcqw = rwqw*cqw - rwqx*cqx - rwqy*cqy - rwqz*cqz;
559 | if (rcqw >= 1.0) rcqw = 1.0; /* This is needed in case input quaternions are not perfectly normalized to avoid nan bug */
560 | /* Convert quaterion to axis/angle */
561 | denom = sqrt(1.0 - rcqw*rcqw);
562 | if (denom == 0.0)
563 | {
564 | raax = 0.0;
565 | raay = 0.0;
566 | raaz = 0.0;
567 | }
568 | else
569 | {
570 | angle = 2.0 * acos(rcqw);
571 | raax = angle * rcqx / denom;
572 | raay = angle * rcqy / denom;
573 | raaz = angle * rcqz / denom;
574 | }
575 | /* Rotate this axis/angle vector to world frame */
576 | /* Rotate xyz_bc into a frame, rotate by rq */
577 | qx2 = rqx*rqx;
578 | qy2 = rqy*rqy;
579 | qz2 = rqz*rqz;
580 | qw2 = rqw*rqw;
581 | qxqy = rqx*rqy;
582 | qxqz = rqx*rqz;
583 | qxqw = rqx*rqw;
584 | qyqz = rqy*rqz;
585 | qyqw = rqy*rqw;
586 | qzqw = rqz*rqw;
587 | waax = raax*(qx2-qy2-qz2+qw2) + 2*raay*(qxqy-qzqw) + 2*raaz*(qxqz+qyqw);
588 | waay = 2*raax*(qxqy+qzqw) + raay*(-qx2+qy2-qz2+qw2) + 2*raaz*(qyqz-qxqw);
589 | waaz = 2*raax*(qxqz-qyqw) + 2*raay*(qyqz+qxqw) + raaz*(-qx2-qy2+qz2+qw2);
590 |
591 | /* Apply spatial force */
592 | fx = -Klin * (cx - rx) - Blin * (cvx - rvx);
593 | fy = -Klin * (cy - ry) - Blin * (cvy - rvy);
594 | fz = -Klin * (cz - rz) - Blin * (cvz - rvz);
595 | fnx = -Kang * (waax) - Bang * (cwx - rwx) - cz*fy + cy*fz;
596 | fny = -Kang * (waay) - Bang * (cwy - rwy) + cz*fx - cx*fz;
597 | fnz = -Kang * (waaz) - Bang * (cwz - rwz) - cy*fx + cx*fy;
598 |
599 | /* Save to force */
600 | force[0] += fnx;
601 | force[1] += fny;
602 | force[2] += fnz;
603 | force[3] += fx;
604 | force[4] += fy;
605 | force[5] += fz;
606 |
607 | return 0;
608 | }
609 |
610 | int cd_spatial_mat_bullet(double m[6][10], double v[6])
611 | {
612 | /* First column */
613 | m[3][0] += v[3];
614 | m[4][0] += v[4];
615 | m[5][0] += v[5];
616 | /* Upper-left 3x3 */
617 | m[0][2] += v[5];
618 | m[0][3] += - v[4];
619 | m[1][1] += - v[5];
620 | m[1][3] += v[3];
621 | m[2][1] += v[4];
622 | m[2][2] += - v[3];
623 | /* Lower-left 3x3 */
624 | m[3][2] += - v[2];
625 | m[3][3] += v[1];
626 | m[4][1] += v[2];
627 | m[4][3] += - v[0];
628 | m[5][1] += - v[1];
629 | m[5][2] += v[0];
630 | /* Upper-right 3x6 */
631 | m[0][4] += v[0];
632 | m[0][5] += v[1];
633 | m[0][6] += v[2];
634 | m[1][5] += v[0];
635 | m[1][7] += v[1];
636 | m[1][8] += v[2];
637 | m[2][6] += v[0];
638 | m[2][8] += v[1];
639 | m[2][9] += v[2];
640 | return 0;
641 | }
642 |
643 | /* aka m = [vx*] */
644 | int cd_spatial_mat_crossf(double m[6][6], double v[6])
645 | {
646 | cd_mat_set_zero(&m[0][0],6,6);
647 | /* Upper Left */
648 | m[0][1] = -v[2];
649 | m[0][2] = v[1];
650 | m[1][0] = v[2];
651 | m[1][2] = -v[0];
652 | m[2][0] = -v[1];
653 | m[2][1] = v[0];
654 | /* Bottom Right */
655 | m[3][4] = -v[2];
656 | m[3][5] = v[1];
657 | m[4][3] = v[2];
658 | m[4][5] = -v[0];
659 | m[5][3] = -v[1];
660 | m[5][4] = v[0];
661 | /* Upper Right */
662 | m[0][4] = -v[5];
663 | m[0][5] = v[4];
664 | m[1][3] = v[5];
665 | m[1][5] = -v[3];
666 | m[2][3] = -v[4];
667 | m[2][4] = v[3];
668 | return 0;
669 | }
670 |
--------------------------------------------------------------------------------
/src/libcd/spatial.h:
--------------------------------------------------------------------------------
1 | /** \file spatial.h
2 | * \brief Interface to cd_spatial, a collection of useful routines for
3 | * spatial vector algrbra.
4 | * \author Christopher Dellin
5 | * \date 2010-2012
6 | */
7 |
8 | /* (C) Copyright 2010-2013 Carnegie Mellon University */
9 |
10 | /* This module (cd_spatial) is part of libcd.
11 | *
12 | * This module of libcd is free software: you can redistribute it
13 | * and/or modify it under the terms of the GNU General Public License as
14 | * published by the Free Software Foundation, either version 3 of the
15 | * License, or (at your option) any later version.
16 | *
17 | * This module of libcd is distributed in the hope that it will be
18 | * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 | * GNU General Public License for more details.
21 | *
22 | * A copy of the GNU General Public License is provided with libcd
23 | * (license-gpl.txt) and is also available at .
24 | */
25 |
26 | #ifndef CD_SPATIAL_H
27 | #define CD_SPATIAL_H
28 |
29 | int cd_spatial_xm_to_pose(double xm[6][6], double pose[7]);
30 | int cd_spatial_xf_to_pose(double xf[6][6], double pose[7]);
31 |
32 | int cd_spatial_xm_from_pose(double xm[6][6], double pose[7]);
33 | int cd_spatial_xf_from_pose(double xf[6][6], double pose[7]);
34 |
35 | /* transform an body inertia from frame b to frame a */
36 | int cd_spatial_inertia_x(double pose_ab[7], double inertia_b[6][6], double inertia_a[6][6]);
37 |
38 | /* where would a body be after moving with constant velocity for
39 | * unit time?
40 | * aka twists, pose (or H) gives the pose of the body-fixed frame
41 | * originally located ato the origin */
42 | int cd_spatial_pose_from_spavel_unittime(double pose[7], double spavel[6]);
43 | int cd_spatial_H_from_spavel_unittime(double H[4][4], double spavel[6]);
44 |
45 | int cd_spatial_x_invert(double x[6][6]);
46 |
47 | int cd_spatial_v_to_pos(double vel[6], double pos[3]);
48 | int cd_spatial_v_from_pos(double vel[6], double pos[3]);
49 | int cd_spatial_f_to_pos(double force[6], double pos[3]);
50 | int cd_spatial_f_from_pos(double force[6], double pos[3]);
51 |
52 | /* v = J \dot{r} */
53 | int cd_spatial_pose_jac(double pose[7], double jac[6][7]);
54 | /* \dot{r} = J^{-1} v */
55 | int cd_spatial_pose_jac_inverse(double pose[7], double jac_inverse[7][6]);
56 |
57 | int cd_spatial_inertia_from_com(double inertia[6][6], double mass, double com[3], double Icom[3][3]);
58 | int cd_spatial_inertia_to_com(double inertia[6][6], double * massp, double com[3], double Icom[3][3]);
59 | int cd_spatial_inertia_sphere_solid(double pos[3], double mass, double radius, double inertia[6][6]);
60 |
61 | int cd_spatial_vxIv(double v[6], double I[6][6], double result[6]);
62 |
63 | int cd_spatial_spring_damper(double pose[7], double vel[6],
64 | double pose_ref[7], double vel_ref[6], double force[6],
65 | double Klin, double Blin, double Kang, double Bang);
66 |
67 | /* Older stuff, used in cd_sdfast_spatial_get_k */
68 | int cd_spatial_mat_bullet(double m[6][10], double v[6]);
69 | int cd_spatial_mat_crossf(double m[6][6], double v[6]);
70 |
71 | #endif /* CD_SPATIAL_H */
72 |
--------------------------------------------------------------------------------
/src/libcd/util.c:
--------------------------------------------------------------------------------
1 | /** \file util.c
2 | * \brief Implementation of cd_util, a set of general utility functions.
3 | * \author Christopher Dellin
4 | * \date 2010-2012
5 | */
6 |
7 | /* (C) Copyright 2010-2013 Carnegie Mellon University */
8 |
9 | /* This module (cd_util) is part of libcd.
10 | *
11 | * This module of libcd is free software: you can redistribute it
12 | * and/or modify it under the terms of the GNU General Public License as
13 | * published by the Free Software Foundation, either version 3 of the
14 | * License, or (at your option) any later version.
15 | *
16 | * This module of libcd is distributed in the hope that it will be
17 | * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 | * GNU General Public License for more details.
20 | *
21 | * A copy of the GNU General Public License is provided with libcd
22 | * (license-gpl.txt) and is also available at .
23 | */
24 |
25 | #include
26 | #include
27 | #include
28 | #include
29 | #include "util.h"
30 |
31 | void cd_util_exitmsg(int status, const char * templ, ...)
32 | {
33 | va_list ap;
34 | va_start(ap, templ);
35 | vfprintf((status==EXIT_SUCCESS)?stdout:stderr, templ, ap);
36 | exit(status);
37 | va_end(ap);
38 | return;
39 | }
40 |
41 | double cd_util_rand_double(double min, double max)
42 | {
43 | return min + (max - min) * ((double) rand() / (double) RAND_MAX);
44 | }
45 |
46 | /* From http://c-faq.com/lib/rand.931117.html
47 | * scs@eskimo.com (Steve Summit)
48 | * Wed, 17 Nov 1993 06:10:36 GMT
49 | * Newsgroups: comp.lang.c
50 | * Subject: Re: help with random #s! */
51 | int cd_util_rand_int(unsigned int n)
52 | {
53 | return (double) rand() / ((double) RAND_MAX + 1) * n;
54 | }
55 |
--------------------------------------------------------------------------------
/src/libcd/util.h:
--------------------------------------------------------------------------------
1 | /** \file util.h
2 | * \brief Interface to cd_util, a set of general utility functions.
3 | * \author Christopher Dellin
4 | * \date 2010-2012
5 | */
6 |
7 | /* (C) Copyright 2010-2013 Carnegie Mellon University */
8 |
9 | /* This module (cd_util) is part of libcd.
10 | *
11 | * This module of libcd is free software: you can redistribute it
12 | * and/or modify it under the terms of the GNU General Public License as
13 | * published by the Free Software Foundation, either version 3 of the
14 | * License, or (at your option) any later version.
15 | *
16 | * This module of libcd is distributed in the hope that it will be
17 | * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 | * GNU General Public License for more details.
20 | *
21 | * A copy of the GNU General Public License is provided with libcd
22 | * (license-gpl.txt) and is also available at .
23 | */
24 |
25 | #ifndef CD_UTIL_H
26 | #define CD_UTIL_H
27 |
28 | #define cd_util_round(in) floor((in) + 0.5)
29 |
30 | void cd_util_exitmsg(int status, const char * templ, ...);
31 |
32 | /* Note: This is inclusive on both ends! */
33 | double cd_util_rand_double(double min, double max);
34 |
35 | int cd_util_rand_int(unsigned int n);
36 |
37 | #endif /* CD_UTIL_H */
38 |
--------------------------------------------------------------------------------
/src/libcd/util_shparse.c:
--------------------------------------------------------------------------------
1 | /** \file util_shparse.c
2 | * \brief Implementation of cd_util_shparse, a simple POSIX shell argument
3 | * parser.
4 | * \author Christopher Dellin
5 | * \date 2012
6 | */
7 |
8 | /* (C) Copyright 2012-2013 Christopher Dellin */
9 |
10 | /* This module (cd_util_shparse) is part of libcd.
11 | *
12 | * This module of libcd is free software: you can redistribute it
13 | * and/or modify it under the terms of the GNU General Public License as
14 | * published by the Free Software Foundation, either version 3 of the
15 | * License, or (at your option) any later version.
16 | *
17 | * This module of libcd is distributed in the hope that it will be
18 | * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 | * GNU General Public License for more details.
21 | *
22 | * A copy of the GNU General Public License is provided with libcd
23 | * (license-gpl.txt) and is also available at .
24 | */
25 |
26 | /* An implementation of simple POSIX shell argument parsing.
27 | * Written by Chris Dellin, 2012-07-03
28 | */
29 |
30 | #include
31 | #include
32 | #include
33 | #include
34 |
35 | #include "util_shparse.h"
36 |
37 | int cd_util_shparse(char * in, int * argcp, char *** argvp)
38 | {
39 | int inarg;
40 | char quot;
41 | int i;
42 | int skipped;
43 | int argc;
44 | int argi;
45 | char ** argv;
46 |
47 | /* first, figure out how many arguments there are */
48 | argc = 0;
49 | inarg = 0;
50 | quot = 0;
51 | skipped = 0;
52 | for (i=0; in[i]; i++)
53 | {
54 | /* swallow spaces inter-arg */
55 | if (!inarg)
56 | {
57 | if (isspace(in[i]))
58 | {
59 | in[i] = 0;
60 | continue;
61 | }
62 | inarg = 1;
63 | argc++;
64 | skipped = 0;
65 | }
66 | /* are we ending an argument? */
67 | if (inarg && !quot && isspace(in[i]))
68 | {
69 | for (; skipped >= 0; skipped--)
70 | in[i-skipped] = 0;
71 | inarg = 0;
72 | continue;
73 | }
74 | /* are we entering / leaving quotes? */
75 | if (inarg && !quot && (in[i] == '"' || in[i] == '\''))
76 | {
77 | quot = in[i];
78 | skipped++;
79 | continue;
80 | }
81 | if (inarg && quot && in[i] == quot)
82 | {
83 | quot = 0;
84 | skipped++;
85 | continue;
86 | }
87 | /* is this a backslash escape? */
88 | if (inarg && (!quot || quot == '"') && in[i] == '\\' && in[i+1])
89 | {
90 | if (in[i+1] == '\n')
91 | {
92 | i++;
93 | skipped += 2;
94 | continue;
95 | }
96 | if (!quot || in[i+1] == '"' || in[i+1] == '\\')
97 | {
98 | i++;
99 | skipped++;
100 | }
101 | }
102 | /* copy the character! */
103 | in[i-skipped] = in[i];
104 | }
105 | /* copy in necessary null at the end */
106 | for (; skipped >= 0; skipped--)
107 | in[i-skipped] = 0;
108 |
109 | argv = (char **) malloc(argc * sizeof(char *));
110 | if (!argv) return -1;
111 |
112 | inarg = 0;
113 | for (argi=0, i=0; argi.
23 | */
24 |
25 | /* Simple POSIX shell argument parsing;
26 | * that is, turns a string like:
27 | * grep -v -e can -e "can't" -e 'Say "Hi!"' -e "do\\don't"
28 | * into an argv array like:
29 | * grep, -v, -e, can, -e, can't, -e, Say "Hi!", -e, do\don't
30 | * Characters that have special meaning are:
31 | * space characters, newline, backslash, double quote, single quote
32 | */
33 |
34 | int cd_util_shparse(char * in, int * argcp, char *** argvp);
35 |
--------------------------------------------------------------------------------
/src/orcdchomp.cpp:
--------------------------------------------------------------------------------
1 | /** \file orcdchomp.cpp
2 | * \brief orcdchomp entry point from OpenRAVE.
3 | * \author Christopher Dellin
4 | * \date 2012
5 | */
6 |
7 | /* (C) Copyright 2012-2013 Carnegie Mellon University */
8 |
9 | /* This module (orcdchomp) is part of libcd.
10 | *
11 | * This module of libcd is free software: you can redistribute it
12 | * and/or modify it under the terms of the GNU General Public License as
13 | * published by the Free Software Foundation, either version 3 of the
14 | * License, or (at your option) any later version.
15 | *
16 | * This module of libcd is distributed in the hope that it will be
17 | * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 | * GNU General Public License for more details.
20 | *
21 | * A copy of the GNU General Public License is provided with libcd
22 | * (license-gpl.txt) and is also available at .
23 | */
24 |
25 | #include
26 | #include
27 | #include
28 |
29 | #include
30 | #include
31 | #include
32 |
33 | #include "orcdchomp_kdata.h"
34 | #include "orcdchomp_mod.h"
35 |
36 | /* globals: we maintain a single kdata xml reader instance */
37 | namespace
38 | {
39 |
40 | static boost::shared_ptr reg_reader;
41 |
42 | static OpenRAVE::BaseXMLReaderPtr rdata_parser_maker(OpenRAVE::InterfaceBasePtr ptr, const OpenRAVE::AttributesList& atts)
43 | {
44 | return OpenRAVE::BaseXMLReaderPtr(new orcdchomp::kdata_parser(boost::shared_ptr(),atts));
45 | }
46 |
47 | } /* anonymous namespace */
48 |
49 |
50 | void GetPluginAttributesValidated(OpenRAVE::PLUGININFO& info)
51 | {
52 | /* create the kdata xml parser interface if it does noet yet exit */
53 | if(!reg_reader)
54 | reg_reader = OpenRAVE::RaveRegisterXMLReader(OpenRAVE::PT_KinBody,"orcdchomp",rdata_parser_maker);
55 |
56 | info.interfacenames[OpenRAVE::PT_Module].push_back("orcdchomp");
57 |
58 | return;
59 | }
60 |
61 |
62 | OpenRAVE::InterfaceBasePtr CreateInterfaceValidated(OpenRAVE::InterfaceType type, const std::string& interfacename, std::istream& sinput, OpenRAVE::EnvironmentBasePtr penv)
63 | {
64 | if((type == OpenRAVE::PT_Module)&&(interfacename == "orcdchomp"))
65 | return OpenRAVE::InterfaceBasePtr(new orcdchomp::mod(penv));
66 |
67 | return OpenRAVE::InterfaceBasePtr();
68 | }
69 |
70 | OPENRAVE_PLUGIN_API void DestroyPlugin()
71 | {
72 | RAVELOG_INFO("destroying plugin\n");
73 | return;
74 | }
75 |
--------------------------------------------------------------------------------
/src/orcdchomp_kdata.cpp:
--------------------------------------------------------------------------------
1 | /** \file orcdchomp_kdata.cpp
2 | * \brief Implementation of orcdchomp_rdata, a parser for sphere data
3 | * provided with an OpenRAVE kinbody XML file.
4 | * \author Christopher Dellin
5 | * \date 2012
6 | */
7 |
8 | /* (C) Copyright 2012-2013 Carnegie Mellon University */
9 |
10 | /* This module (orcdchomp) is part of libcd.
11 | *
12 | * This module of libcd is free software: you can redistribute it
13 | * and/or modify it under the terms of the GNU General Public License as
14 | * published by the Free Software Foundation, either version 3 of the
15 | * License, or (at your option) any later version.
16 | *
17 | * This module of libcd is distributed in the hope that it will be
18 | * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 | * GNU General Public License for more details.
21 | *
22 | * A copy of the GNU General Public License is provided with libcd
23 | * (license-gpl.txt) and is also available at .
24 | */
25 |
26 | #include
27 |
28 | #include "orcdchomp_kdata.h"
29 |
30 | namespace orcdchomp
31 | {
32 |
33 | kdata::kdata() : OpenRAVE::XMLReadable("orcdchomp")
34 | {
35 | this->sphereelems = 0;
36 | }
37 |
38 | kdata::~kdata()
39 | {
40 | struct sphereelem * e;
41 | while (this->sphereelems)
42 | {
43 | e=this->sphereelems->next;
44 | free(this->sphereelems->s);
45 | free(this->sphereelems);
46 | this->sphereelems = e;
47 | }
48 | }
49 |
50 |
51 | kdata_parser::kdata_parser(boost::shared_ptr passed_d, const OpenRAVE::AttributesList& atts)
52 | {
53 | /* save or construct the kdata object */
54 | this->d = passed_d;
55 | if(!this->d) this->d.reset(new kdata());
56 | /* get ready */
57 | this->inside_spheres = false;
58 | }
59 |
60 | OpenRAVE::XMLReadablePtr kdata_parser::GetReadable()
61 | {
62 | return this->d;
63 | }
64 |
65 | OpenRAVE::BaseXMLReader::ProcessElement kdata_parser::startElement(const std::string& name, const OpenRAVE::AttributesList& atts)
66 | {
67 | if (name == "spheres")
68 | {
69 | if (this->inside_spheres) RAVELOG_ERROR("you can't have inside !\n");
70 | this->inside_spheres = true;
71 | return PE_Support;
72 | }
73 | if (name == "sphere")
74 | {
75 | struct sphere * s;
76 | struct sphereelem * e;
77 | if (!this->inside_spheres) { RAVELOG_ERROR("you can't have not inside !\n"); return PE_Pass; }
78 | s = (struct sphere *) malloc(sizeof(struct sphere));
79 | for(OpenRAVE::AttributesList::const_iterator itatt = atts.begin(); itatt != atts.end(); ++itatt)
80 | {
81 | if (itatt->first=="link")
82 | strcpy(s->linkname, itatt->second.c_str());
83 | else if (itatt->first=="radius")
84 | s->radius = strtod(itatt->second.c_str(), 0);
85 | else if (itatt->first=="pos")
86 | sscanf(itatt->second.c_str(), "%lf %lf %lf", &s->pos[0], &s->pos[1], &s->pos[2]);
87 | else
88 | RAVELOG_ERROR("unknown attribute %s=%s!\n",itatt->first.c_str(),itatt->second.c_str());
89 | }
90 | /* insert at head of kdata list */
91 | e = (struct sphereelem *) malloc(sizeof(struct sphereelem));
92 | e->s = s;
93 | e->next = this->d->sphereelems;
94 | this->d->sphereelems = e;
95 | return PE_Support;
96 | }
97 | return PE_Pass;
98 | }
99 |
100 | void kdata_parser::characters(const std::string& ch)
101 | {
102 | return;
103 | }
104 |
105 | bool kdata_parser::endElement(const std::string& name)
106 | {
107 | if (name == "orcdchomp") return true;
108 | if (name == "spheres")
109 | {
110 | if (!this->inside_spheres) RAVELOG_ERROR("you can't have without matching !\n");
111 | this->inside_spheres = false;
112 | }
113 | else if (name == "sphere")
114 | {
115 | if (!this->inside_spheres) RAVELOG_ERROR("you can't have not inside !\n");
116 | }
117 | else
118 | RAVELOG_ERROR("unknown field %s\n", name.c_str());
119 | return false;
120 | }
121 |
122 | } /* namespace orcdchomp */
123 |
--------------------------------------------------------------------------------
/src/orcdchomp_kdata.h:
--------------------------------------------------------------------------------
1 | /** \file orcdchomp_kdata.h
2 | * \brief Interface to orcdchomp_kdata, a parser for sphere data provided
3 | * with an OpenRAVE kinbody XML file.
4 | * \author Christopher Dellin
5 | * \date 2012
6 | */
7 |
8 | /* (C) Copyright 2012-2013 Carnegie Mellon University */
9 |
10 | /* This module (orcdchomp) is part of libcd.
11 | *
12 | * This module of libcd is free software: you can redistribute it
13 | * and/or modify it under the terms of the GNU General Public License as
14 | * published by the Free Software Foundation, either version 3 of the
15 | * License, or (at your option) any later version.
16 | *
17 | * This module of libcd is distributed in the hope that it will be
18 | * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 | * GNU General Public License for more details.
21 | *
22 | * A copy of the GNU General Public License is provided with libcd
23 | * (license-gpl.txt) and is also available at .
24 | */
25 |
26 | /* requires:
27 | * - openrave/openrave.h
28 | * */
29 |
30 | namespace orcdchomp
31 | {
32 |
33 | struct sphereelem
34 | {
35 | struct sphereelem * next;
36 | struct sphere * s;
37 | };
38 |
39 | struct sphere
40 | {
41 | /* parsed from xml */
42 | char linkname[32];
43 | double pos[3];
44 | double radius;
45 | };
46 |
47 |
48 | /* the kinbody-attached data class */
49 | class kdata : public OpenRAVE::XMLReadable
50 | {
51 | public:
52 | struct sphereelem * sphereelems;
53 | kdata();
54 | ~kdata();
55 | };
56 |
57 |
58 | /* the kdata-parser */
59 | class kdata_parser : public OpenRAVE::BaseXMLReader
60 | {
61 | public:
62 | boost::shared_ptr d;
63 | bool inside_spheres;
64 |
65 | kdata_parser(boost::shared_ptr passed_d, const OpenRAVE::AttributesList& atts);
66 | virtual OpenRAVE::XMLReadablePtr GetReadable();
67 | virtual ProcessElement startElement(const std::string& name, const OpenRAVE::AttributesList& atts);
68 | virtual void characters(const std::string& ch);
69 | virtual bool endElement(const std::string& name);
70 | };
71 |
72 | } /* namespace orcdchomp */
73 |
--------------------------------------------------------------------------------
/src/orcdchomp_mod.h:
--------------------------------------------------------------------------------
1 | /** \file orcdchomp_mod.h
2 | * \brief Interface to the orcdchomp module, an implementation of CHOMP
3 | * using libcd.
4 | * \author Christopher Dellin
5 | * \date 2012
6 | */
7 |
8 | /* (C) Copyright 2012-2013 Carnegie Mellon University */
9 |
10 | /* This module (orcdchomp) is part of libcd.
11 | *
12 | * This module of libcd is free software: you can redistribute it
13 | * and/or modify it under the terms of the GNU General Public License as
14 | * published by the Free Software Foundation, either version 3 of the
15 | * License, or (at your option) any later version.
16 | *
17 | * This module of libcd is distributed in the hope that it will be
18 | * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 | * GNU General Public License for more details.
21 | *
22 | * A copy of the GNU General Public License is provided with libcd
23 | * (license-gpl.txt) and is also available at .
24 | */
25 |
26 | /* requires:
27 | * - openrave/openrave.h
28 | * */
29 |
30 | #include "orcwrap.h"
31 |
32 | namespace orcdchomp
33 | {
34 |
35 | struct sdf;
36 |
37 | /* the module itself */
38 | class mod : public OpenRAVE::ModuleBase
39 | {
40 | public:
41 | OpenRAVE::EnvironmentBasePtr e; /* filled on module creation */
42 | int n_sdfs;
43 | struct sdf * sdfs;
44 |
45 | int viewspheres(int argc, char * argv[], std::ostream& sout);
46 | int computedistancefield(int argc, char * argv[], std::ostream& sout);
47 | int addfield_fromobsarray(int argc, char * argv[], std::ostream& sout);
48 | int viewfields(int argc, char * argv[], std::ostream& sout);
49 | int removefield(int argc, char * argv[], std::ostream& sout);
50 | int create(int argc, char * argv[], std::ostream& sout);
51 | int iterate(int argc, char * argv[], std::ostream& sout);
52 | int gettraj(int argc, char * argv[], std::ostream& sout);
53 | int destroy(int argc, char * argv[], std::ostream& sout);
54 |
55 | mod(OpenRAVE::EnvironmentBasePtr penv) : OpenRAVE::ModuleBase(penv)
56 | {
57 | __description = "orcdchomp: implementation chomp using libcd";
58 | RegisterCommand("viewspheres",orcwrap(boost::bind(&mod::viewspheres,this,_1,_2,_3)),"view spheres");
59 | RegisterCommand("computedistancefield",orcwrap(boost::bind(&mod::computedistancefield,this,_1,_2,_3)),"compute distance field");
60 | RegisterCommand("addfield_fromobsarray",orcwrap(boost::bind(&mod::addfield_fromobsarray,this,_1,_2,_3)),"compute distance field");
61 | RegisterCommand("viewfields",orcwrap(boost::bind(&mod::viewfields,this,_1,_2,_3)),"view fields");
62 | RegisterCommand("removefield",orcwrap(boost::bind(&mod::removefield,this,_1,_2,_3)),"remove distance field from kinbody");
63 | RegisterCommand("create",orcwrap(boost::bind(&mod::create,this,_1,_2,_3)),"create a chomp run");
64 | RegisterCommand("iterate",orcwrap(boost::bind(&mod::iterate,this,_1,_2,_3)),"create a chomp run");
65 | RegisterCommand("gettraj",orcwrap(boost::bind(&mod::gettraj,this,_1,_2,_3)),"create a chomp run");
66 | RegisterCommand("destroy",orcwrap(boost::bind(&mod::destroy,this,_1,_2,_3)),"create a chomp run");
67 |
68 | this->e = penv;
69 | this->n_sdfs = 0;
70 | this->sdfs = 0;
71 | }
72 | virtual ~mod() {}
73 | void Destroy() { RAVELOG_INFO("module unloaded from environment\n"); }
74 | /* This is called on e.LoadProblem(m, 'command') */
75 | int main(const std::string& cmd) { RAVELOG_INFO("module init cmd: %s\n", cmd.c_str()); return 0; }
76 | };
77 |
78 | void run_destroy(struct run * r);
79 |
80 | struct tsr
81 | {
82 | int manipindex;
83 | char bodyandlink[32];
84 | double T0w[7];
85 | double Twe[7];
86 | double Bw[6][2];
87 | };
88 |
89 | int tsr_create_parse(struct tsr ** tp, char * str);
90 | void tsr_destroy(struct tsr * t);
91 |
92 | } /* namespace orcdchomp */
93 |
--------------------------------------------------------------------------------
/src/orcwrap.cpp:
--------------------------------------------------------------------------------
1 | /** \file orcwrap.cpp
2 | * \brief Implementation of orcwrap, an OpenRAVE interface command parser.
3 | * \author Christopher Dellin
4 | * \date 2012
5 | */
6 |
7 | /* (C) Copyright 2012-2013 Carnegie Mellon University */
8 |
9 | /* This module (orcdchomp) is part of libcd.
10 | *
11 | * This module of libcd is free software: you can redistribute it
12 | * and/or modify it under the terms of the GNU General Public License as
13 | * published by the Free Software Foundation, either version 3 of the
14 | * License, or (at your option) any later version.
15 | *
16 | * This module of libcd is distributed in the hope that it will be
17 | * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 | * GNU General Public License for more details.
20 | *
21 | * A copy of the GNU General Public License is provided with libcd
22 | * (license-gpl.txt) and is also available at .
23 | */
24 |
25 | #include
26 | #include
27 | #include
28 | #include
29 | #include
30 |
31 | extern "C" {
32 | #include "libcd/util_shparse.h"
33 | }
34 |
35 | #include "orcwrap.h"
36 |
37 | static bool orcwrap_call(
38 | const char * cmd,
39 | boost::function fn,
40 | std::ostream& sout, std::istream& sinput)
41 | {
42 | char * in;
43 | int argc;
44 | char ** argv;
45 | int ret;
46 |
47 | std::ostringstream oss;
48 | oss << cmd << " " << sinput.rdbuf();
49 | in = (char *) malloc(strlen(oss.str().c_str())+1);
50 | if (!in) return false;
51 | strcpy(in, oss.str().c_str());
52 |
53 | cd_util_shparse(in, &argc, &argv);
54 |
55 | try
56 | {
57 | ret = fn(argc, argv, sout);
58 | }
59 | catch (...)
60 | {
61 | free(in);
62 | free(argv);
63 | throw;
64 | }
65 |
66 | free(in);
67 | free(argv);
68 | return (ret == 0) ? true : false;
69 | }
70 |
71 | boost::function
72 | orcwrap(boost::function fn)
73 | {
74 | return boost::bind(orcwrap_call,"openrave_command",fn,_1,_2);
75 | }
76 |
77 | boost::function
78 | orcwrap(const char * cmd, boost::function fn)
79 | {
80 | return boost::bind(orcwrap_call,cmd,fn,_1,_2);
81 | }
82 |
83 |
--------------------------------------------------------------------------------
/src/orcwrap.h:
--------------------------------------------------------------------------------
1 | /** \file orcwrap.h
2 | * \brief Interface to orcwrap, an OpenRAVE interface command parser.
3 | * \author Christopher Dellin
4 | * \date 2012
5 | */
6 |
7 | /* (C) Copyright 2012-2013 Carnegie Mellon University */
8 |
9 | /* This module (orcdchomp) is part of libcd.
10 | *
11 | * This module of libcd is free software: you can redistribute it
12 | * and/or modify it under the terms of the GNU General Public License as
13 | * published by the Free Software Foundation, either version 3 of the
14 | * License, or (at your option) any later version.
15 | *
16 | * This module of libcd is distributed in the hope that it will be
17 | * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 | * GNU General Public License for more details.
20 | *
21 | * A copy of the GNU General Public License is provided with libcd
22 | * (license-gpl.txt) and is also available at .
23 | */
24 |
25 | /* requires:
26 | * #include
27 | * #include
28 | * #include
29 | */
30 |
31 | /* This is a tiny generic library which parses OpenRAVE interface command
32 | * strings into an argument array using shell-like quoting
33 | * (using libcd's util_shparse) */
34 |
35 | boost::function
36 | orcwrap(boost::function fn);
37 |
38 | boost::function
39 | orcwrap(const char * cmd, boost::function fn);
40 |
--------------------------------------------------------------------------------