wiki:WikiStart/OngoingWork/BaseTypesCleanup/JointState

There has been a discussion about this already on the ML. I am trying to summarize the result here, as a starting point for further discussion.

The description of the kinematics (i.e. what is linked to what) is definitely not part of the data structure(s).

I proposed, at the end, to have one data structure for the state of the kinematics and another one for the state of the actuator itself. This was +1 by Matthias.

Given that we currently still have only a weak support for metadata on ports, I would propose to put the joint/actuator names inside the data structures but make the fact of filling them optional. When metadata support is fully available, these fields won't have to be filled at all anymore. Alternative: implement metadata support on ports quickly, or resort to a MetadataBroadcaster, which would then be used to replace the TransformerBroadcaster as well.

Both actuator state and joint state structures should be able to handle both linear and angular encoders.

A pretty common state is that all encoders / joints are modelled as 1D joints. Does that make sense in general ?

I would cover only the "kinematic" part of the structures so far. Is there a need for a standardized actuator state (with temperatures, current, PWM, ...) ?

Matthias remarked that 'position' is ambiguous for actuators that can turn more than 360degrees (e.g. wheels), and preferred either having a base::Angle with a turn counter or a double renamed to moved_angle_from_initialization.

Proposal: samples

namespace base::samples {
struct JointState
{
  /** Current position of the actuator, in radians for angular joints, in m/s for linear ones
   *
   * For angular joints that can move more than 360 degrees, this
   * accumulates the movement since initialization
   */
  double position;
         
  /** Speed in radians per second for angular actuators, in m/s for linear ones
   * 
   * This is an instantaneous speed. It means that, considering two consecutive
   * JointState samples, (position1 - position0)/(time1 - time0).toSeconds() is
   * not necessarily equal to 'speed'
   */
  double speed;

  /** Torque in N.m for angular joints and N for linear ones.
   * NOTE: this is ill-defined. What effort are we talking about here (who applies it on what) ?
   */
  double effort;
};
struct Joints
{
  base::Time time;
  
  /** The presence of this field is tied to the metadata support in Rock.
   * See comment above
   */
  std::vector<std::string> names;

  /** The joint states at the given time
   */
  std::vector<JointState> states;
};
}

We would then create a class that would ease the estimation of speed from position (e.g. would estimate and filter the speed based on position measurements) so that each actuator driver can make sure that 'speed' is always filled in. Not possible for effort though, which would then be initialized with base::unknown<double> and may be filled by torque measurements and/or inverse dynamics.

Proposal: control

It is a reductive view to think that controllers can control only one type of quantity. For instance, Ajish's PIV can be given both a position and a speed (as feed-forward). It is obviously not a steady-state, but allows to have much more precise trajectory following.

A new control type should also therefore be given. It would actually be the exact same type but typedef'd to a different name:

namespace base {
namespace control {
typedef base::samples::Joints Joints;
typedef base::samples::JointState Setpoint;
}
}

Comments / remarks / questions

  • actuated vs. free joints. How does this work ? In principle, controllers should send commands only for actuated joints, but can then use other joint states as their inputs (e.g. asguard internal/external encoder situation)

double vs. float for the position field

We benchmarked the precision of double vs. float for the position field. The test programs are attached to this page.

First method

Accumulate ticks. The total number of ticks were converted to the floating-point representation and then back to ticks. I was using 1024 ticks per turn, and 20cm wheels to give a feel of how far a robot could go before running into precision problems.

Floats

d=0km error=0
d=6km error=1
d=26km error=2
d=26km error=3
d=52km error=5
d=52km error=6
d=104km error=11
d=104km error=12
d=122km error=12
d=209km error=23
d=209km error=24
d=245km error=24
d=368km error=24
d=419km error=47
d=419km error=48
d=490km error=48
d=613km error=48

Double no error after more than 250000km using a tick-per-tick increment, above 1e7km with a coarser screening.

Second method

Accumulate directly in the floating-point representation. Convert the accumulated value to ticks and compare to the expected tick value.

Note that from a p.o.v. of precision, the test program is the worstcase as we accumulate tick by tick (i.e. it would be the precision if the computer would only register movements of one tick).

Floats

d=0km error=0
d=0km error=1
d=0km error=2
d=0km error=3
d=0km error=4
d=0km error=5
d=0km error=6
d=0km error=7
d=0km error=8
d=0km error=9

Doubles

d=0km error=0
d=122km error=0
d=180km error=1
d=245km error=1
d=368km error=1
d=490km error=1
d=530km error=2
d=574km error=3
d=613km error=3
d=618km error=4
d=662km error=5
d=706km error=6
d=736km error=6
d=750km error=7
d=795km error=8
d=859km error=8
d=981km error=8
d=1104km error=8
d=1227km error=8
d=1272km error=9
d=1298km error=10
d=1323km error=11
d=1349km error=12
d=1349km error=12
d=1374km error=13
d=1400km error=14
d=1425km error=15
d=1451km error=16
d=1472km error=16
d=1477km error=17
d=1502km error=18
d=1528km error=19
d=1553km error=20
d=1579km error=21
d=1595km error=21
d=1604km error=22
d=1630km error=23
d=1655km error=24
d=1718km error=24
d=1840km error=24
Last modified 6 years ago Last modified on 07/01/13 15:08:19

Attachments (1)

Download all attachments as: .zip