Tree solver API

Hi,

A while ago I made a tree-fk-solver that would calculate the position
kinematics from the root of the tree to each of the segments in the
tree. However, the fk api provided by kdl does not support calculating
many transforms at once:

virtual int JntToCart(const JntArray& q_in, Frame& p_out, std::string
segmentName);

Instead, I used the following api:

int JntToCart(const std::map<std::string, double>& q_in,
std::map<std::string, Frame>& p_out);

Also as you can see, I used a map to match segment names and joint
values instead of a JntArray that maps on the different segments of
the tree.

So I wanted to use this as a start for a discussion about what the
tree solver api should look like. Are there already plans for what
this api should look like in the next release?

Wim

Tree solver API

On Tue, 30 Jun 2009, Wim Meeussen wrote:

> A while ago I made a tree-fk-solver that would calculate the position
> kinematics from the root of the tree to each of the segments in the
> tree. However, the fk api provided by kdl does not support calculating
> many transforms at once:
>
> virtual int JntToCart(const JntArray& q_in, Frame& p_out, std::string
> segmentName);
>
> Instead, I used the following api:
>
> int JntToCart(const std::map<std::string, double>& q_in,
> std::map<std::string, Frame>& p_out);
>
> Also as you can see, I used a map to match segment names and joint
> values instead of a JntArray that maps on the different segments of
> the tree.
>
>
>
> So I wanted to use this as a start for a discussion about what the
> tree solver api should look like. Are there already plans for what
> this api should look like in the next release?

yes:
SolveError = JntToCart (KinChain, JntParam, CartParam)

as the abstract interface that must be specialised for each particular
"solver": that solver defines what datastructures exactly are used as
"JntParam" and "CartParam", since the efficiency of a solver depends to a
large extent on the appropriate choice of a data structure. So your
suggestion seems appropriate for a tree (or even any kinematic chain, at
least when this kinematic chain is given as an argument), although strings
seem a bit weird as realtime data structure. The return value SolveError is
in itself also a full data structure, since it has to convey all possible
things that could go wrong during the calculation of a solver algorithm.

There could be other (abstract ?) interfaces for generic classes of
kinematic chains, such as fully holonomic tree structures, non-holonomic
base + holonomic torso + arms structure, Stewart-Gough platforms, etc.

Please comment.

Herman

Tree solver API

On Wed, 1 Jul 2009, Herman Bruyninckx wrote:
> On Tue, 30 Jun 2009, Wim Meeussen wrote:
>
>> A while ago I made a tree-fk-solver that would calculate the position
>> kinematics from the root of the tree to each of the segments in the
>> tree. However, the fk api provided by kdl does not support calculating
>> many transforms at once:
>>
>> virtual int JntToCart(const JntArray& q_in, Frame& p_out, std::string
>> segmentName);
>>
>> Instead, I used the following api:
>>
>> int JntToCart(const std::map<std::string, double>& q_in,
>> std::map<std::string, Frame>& p_out);
>>
>> Also as you can see, I used a map to match segment names and joint
>> values instead of a JntArray that maps on the different segments of
>> the tree.
>>
>>
>>
>> So I wanted to use this as a start for a discussion about what the
>> tree solver api should look like. Are there already plans for what
>> this api should look like in the next release?
>
> yes:
> SolveError = JntToCart (KinChain, JntParam, CartParam)
>
> as the abstract interface that must be specialised for each particular
> "solver": that solver defines what datastructures exactly are used as
> "JntParam" and "CartParam", since the efficiency of a solver depends to a
> large extent on the appropriate choice of a data structure. So your
> suggestion seems appropriate for a tree (or even any kinematic chain, at
> least when this kinematic chain is given as an argument), although strings
> seem a bit weird as realtime data structure. The return value SolveError is
> in itself also a full data structure, since it has to convey all possible
> things that could go wrong during the calculation of a solver algorithm.
>
> There could be other (abstract ?) interfaces for generic classes of
> kinematic chains, such as fully holonomic tree structures, non-holonomic
> base + holonomic torso + arms structure, Stewart-Gough platforms, etc.
>
> Please comment.

[OT]
Does this mean that release 1.0.0 from KDL didn't come with the promise of frozen interfaces?
[/OT]

Klaas

Tree solver API

On Wed, 1 Jul 2009, Klaas Gadeyne wrote:

> On Wed, 1 Jul 2009, Herman Bruyninckx wrote:
>> On Tue, 30 Jun 2009, Wim Meeussen wrote:
>>
>>> A while ago I made a tree-fk-solver that would calculate the position
>>> kinematics from the root of the tree to each of the segments in the
>>> tree. However, the fk api provided by kdl does not support calculating
>>> many transforms at once:
>>>
>>> virtual int JntToCart(const JntArray& q_in, Frame& p_out, std::string
>>> segmentName);
>>>
>>> Instead, I used the following api:
>>>
>>> int JntToCart(const std::map<std::string, double>& q_in,
>>> std::map<std::string, Frame>& p_out);
>>>
>>> Also as you can see, I used a map to match segment names and joint
>>> values instead of a JntArray that maps on the different segments of
>>> the tree.
>>>
>>> So I wanted to use this as a start for a discussion about what the
>>> tree solver api should look like. Are there already plans for what
>>> this api should look like in the next release?
>>
>> yes:
>> SolveError = JntToCart (KinChain, JntParam, CartParam)
>>
>> as the abstract interface that must be specialised for each particular
>> "solver": that solver defines what datastructures exactly are used as
>> "JntParam" and "CartParam", since the efficiency of a solver depends to a
>> large extent on the appropriate choice of a data structure. So your
>> suggestion seems appropriate for a tree (or even any kinematic chain, at
>> least when this kinematic chain is given as an argument), although strings
>> seem a bit weird as realtime data structure. The return value SolveError is
>> in itself also a full data structure, since it has to convey all possible
>> things that could go wrong during the calculation of a solver algorithm.
>>
>> There could be other (abstract ?) interfaces for generic classes of
>> kinematic chains, such as fully holonomic tree structures, non-holonomic
>> base + holonomic torso + arms structure, Stewart-Gough platforms, etc.
>>
>> Please comment.
>
> [OT]
> Does this mean that release 1.0.0 from KDL didn't come with the promise of frozen interfaces?
> [/OT]
>
Your comment is not "OT"... The interface I suggested is the _abstract_ one
"to rule them all", while the current 1.0 API will probably survive for the
kinematic chains it applies to. The goal of the abstract one is to "force"
developers to adhere to common naming and structure, while allowing the
versatility in implementations (algorithms and data structures and error
codes) that is necessary in robotics and machine tools, due to the large
variability in devices and use cases.

Herman

Ruben Smits's picture

Tree solver API

On Tue, Jun 30, 2009 at 6:21 PM, Wim Meeussen<meeussen [..] ...> wrote:
> Hi,
>
> A while ago I made a tree-fk-solver that would calculate the position
> kinematics from the root of the tree to each of the segments in the
> tree. However, the fk api provided by kdl does not support calculating
> many transforms at once:
>
> virtual int JntToCart(const JntArray& q_in, Frame& p_out, std::string
> segmentName);
>
> Instead, I used the following api:
>
> int JntToCart(const std::map<std::string, double>& q_in,
> std::map<std::string, Frame>& p_out);
>
> Also as you can see, I used a map to match segment names and joint
> values instead of a JntArray that maps on the different segments of
> the tree.
>

Maybe we could change the api in something like this:

int JntToCart( const Tree::JntArray& q_in, Tree::Frames& p_out)

with typedef std::map<std::string, double> Tree::JntArray
and typedef std::map<std::string, Frame> Tree::Frames

>
> So I wanted to use this as a start for a discussion about what the
> tree solver api should look like. Are there already plans for what
> this api should look like in the next release?

The current api is very limited. I would like the api of the solvers
for the Chain and Tree to be as similar as possible.

Ruben

Tree solver API

On Jul 1, 2009, at 03:02 , Ruben Smits wrote:

> On Tue, Jun 30, 2009 at 6:21 PM, Wim Meeussen<meeussen [..] ...
> > wrote:
>> Hi,
>>
>> A while ago I made a tree-fk-solver that would calculate the position
>> kinematics from the root of the tree to each of the segments in the
>> tree. However, the fk api provided by kdl does not support
>> calculating
>> many transforms at once:
>>
>> virtual int JntToCart(const JntArray& q_in, Frame& p_out, std::string
>> segmentName);
>>
>> Instead, I used the following api:
>>
>> int JntToCart(const std::map<std::string, double>& q_in,
>> std::map<std::string, Frame>& p_out);
>>
>> Also as you can see, I used a map to match segment names and joint
>> values instead of a JntArray that maps on the different segments of
>> the tree.
>>
>
>
> Maybe we could change the api in something like this:
>
> int JntToCart( const Tree::JntArray& q_in, Tree::Frames& p_out)
>
> with typedef std::map<std::string, double> Tree::JntArray
> and typedef std::map<std::string, Frame> Tree::Frames

What are the real-time implications of the above? The q_in parameter
could be setup ahead of time to prevent RT implications during
controller execution, however, what about p_out?

>> So I wanted to use this as a start for a discussion about what the
>> tree solver api should look like. Are there already plans for what
>> this api should look like in the next release?
>
> The current api is very limited. I would like the api of the solvers
> for the Chain and Tree to be as similar as possible.

Stephen

Tree solver API

>> Maybe we could change the api in something like this:
>> int JntToCart( const Tree::JntArray& q_in, Tree::Frames& p_out)
>> with typedef std::map<std::string, double> Tree::JntArray
>> and typedef std::map<std::string, Frame> Tree::Frames

Following Herman's idea of many C++ api's that all match the same
abstract api (did I understand that correctly?), this works. But how
will we do this in practice? Currently we enforce a C++ api by
inheritance, but this is more restrictive than the abstract api.
Should we get rid of the base classes for solvers?

> What are the real-time implications of the above? The q_in parameter
> could be setup ahead of time to prevent RT implications during
> controller execution, however, what about p_out?

As with any vector, you'll need to pre-allocate. For a map I guess
this means specifying all the strings at allocation time. But this
should not be a problem because you have access to all the names that
go in p_out through the tree.

Wim

--
Wim Meeussen
Willow Garage Inc.
<http://www.willowgarage.com)
>

Tree solver API

On Wed, 1 Jul 2009, Wim Meeussen wrote:

>>> Maybe we could change the api in something like this:
>>> int JntToCart( const Tree::JntArray& q_in, Tree::Frames& p_out)
>>> with typedef std::map<std::string, double> Tree::JntArray
>>> and typedef std::map<std::string, Frame> Tree::Frames
>
> Following Herman's idea of many C++ api's that all match the same
> abstract api (did I understand that correctly?), this works. But how
> will we do this in practice? Currently we enforce a C++ api by
> inheritance, but this is more restrictive than the abstract api.
> Should we get rid of the base classes for solvers?

Don't know yet... :-(

We are intensively discussing these things internally, since it is not
obvious to come up with abstract and concrete APIs for all possible use
cases, and for the object, component and service levels... Maybe this
ambition is too high :-)

Will be continued.

Herman

>> What are the real-time implications of the above? The q_in parameter
>> could be setup ahead of time to prevent RT implications during
>> controller execution, however, what about p_out?
>
> As with any vector, you'll need to pre-allocate. For a map I guess
> this means specifying all the strings at allocation time. But this
> should not be a problem because you have access to all the names that
> go in p_out through the tree.
>
>
> Wim
>
> --
> Wim Meeussen
> Willow Garage Inc.
> <http://www.willowgarage.com)
>

Ruben Smits's picture

Tree solver API

On Wed, Jul 1, 2009 at 8:03 PM, Wim Meeussen<meeussen [..] ...> wrote:
>>> Maybe we could change the api in something like this:
>>> int JntToCart( const Tree::JntArray& q_in, Tree::Frames& p_out)
>>> with typedef std::map<std::string, double> Tree::JntArray
>>> and typedef std::map<std::string, Frame> Tree::Frames
>
> Following Herman's idea of many C++ api's that all match the same
> abstract api (did I understand that correctly?), this works. But how
> will we do this in practice? Currently we enforce a C++ api by
> inheritance, but this is more restrictive than the abstract api.
> Should we get rid of the base classes for solvers?
>
>
>> What are the real-time implications of the above? The q_in parameter
>> could be setup ahead of time to prevent RT implications during
>> controller execution, however, what about p_out?
>
> As with any vector, you'll need to pre-allocate. For a map I guess
> this means specifying all the strings at allocation time. But this
> should not be a problem because you have access to all the names that
> go in p_out through the tree.

A tree could have helper-functions to create these for you.

Ruben