Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Add odometry plugin. #706

Closed
wants to merge 66 commits into from
Closed

WIP: Add odometry plugin. #706

wants to merge 66 commits into from

Conversation

jgoppert
Copy link
Member

@jgoppert jgoppert commented May 6, 2017

This adds an odometry plugin that simplifies interaction with ROS based estimators.

@TSC21
@mhkabir

Copy link
Member

@TSC21 TSC21 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is simple and sharp. we just need to clean debug msgs and add co-variance frame tf


void odom_cb(const nav_msgs::Odometry::ConstPtr &odom)
{
//ROS_INFO("odometry callback");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe we can clear this?

size_t i = 0;
for (int row=0; row < 6; row++) {
for (int col=row; col < 6; col++) {
//ROS_INFO("row: %d, col:%d, i:%d", row, col, i);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also this...

i += 1;
}
}
UAS_FCU(m_uas)->send_message_ignore_drop(lpos);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe you can put both msg send on the end?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that not needed. Fill one message + send is fine.

for (int row=0; row < 6; row++) {
for (int col=row; col < 6; col++) {
//ROS_INFO("row: %d, col:%d, i:%d", row, col, i);
lpos.covariance[i] = odom->pose.covariance[row*6 + col];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we need to apply frame transform from ENU to NED. Maybe we can discuss this and add it to frame_tf.h

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think better to finish ftf::transform_frame(Covariance6d) function implementation and use it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah @vooon that's the intention

lpos.ay = 0;
lpos.az = 0;
size_t i = 0;
for (int row=0; row < 6; row++) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably better to create a std::array and use std::copy

att.q[1] = odom->pose.pose.orientation.x;
att.q[2] = odom->pose.pose.orientation.y;
att.q[3] = odom->pose.pose.orientation.z;
for (size_t i=0; i < 9; i++) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

std::copy suits better I think

lpos.z = -odom->pose.pose.position.z;
lpos.vx = odom->twist.twist.linear.y;
lpos.vy = odom->twist.twist.linear.x;
lpos.vz = -odom->twist.twist.linear.z;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use tft::transform_frame_enu_ned() from frame_tf.h

Also i'm more like to use cog.py to generate msg-to-msg copy code.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah forgot that transform also

att.q[0] = odom->pose.pose.orientation.w;
att.q[1] = odom->pose.pose.orientation.x;
att.q[2] = odom->pose.pose.orientation.y;
att.q[3] = odom->pose.pose.orientation.z;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ftf::quaternion_to_mavlink().

// for f in "xyz":
// cog.outl("lpos.v%s = lin_vel_ned.%s();" % (f, f))
// for f in "xyz":
// cog.outl("lpos.a%s = 0.0;" % f)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not:

for a, b in (('', 'pos_ned'), ('v', 'lin_vel_ned'), ('a', 'zero')):
    for f in 'xyz':
        cog.outl("lpos.{a}{f} = {b}.{f}();".format(**locals()))

*add

const auto zero = Eigen::Vector3d::Zero();

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah makes it simples. thanks

// TODO: apply ftf::transform_frame(Covariance9d)
for (size_t i = 0; i < 9; i++) {
att.covariance[i] = odom->pose.covariance[i];
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume that std::copy() shall correctly move array<double, 9> to array<float, 9>, because it uses iterators.

std::copy(odom->pose.covariance.cbegin(), odom->pose.covariance.cend(), att.covariance.begin());

Copy link
Member

@vooon vooon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now looks better. One thing that i'm not sure: maybe call it send_odom?

case StaticTF::AIRCRAFT_TO_BASELINK:
case StaticTF::BASELINK_TO_AIRCRAFT:
Affine6dTf << AIRCRAFT_BASELINK_AFFINE * R, Eigen::MatrixXd::Zero(3, 3),
Eigen::MatrixXd::Zero(3, 3), AIRCRAFT_BASELINK_AFFINE * R;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Uncrustify often breaks indent in eigen matrixes. I think Second line should have identical indent as after <<.

// tf params
_odom_sub = _nh.subscribe("odom", 10, &OdometryPlugin::odom_cb, this);
// general params
odom_nh.param("estimator_type", estimator_type, 3); // defaulted to VIO type
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

using mavlink::common::MAV_ESTIMATOR_TYPE;

// and then

enum_value(MAV_ESTIMATOR_TYPE::VIO);

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I kept it as int so it can be easily received and modified on the yaml file.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can receive int from rosparam, but i think better to store it in it's enum class. But i may be wrong, since we will static_cast several times.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should give the option to set it on rasparam IMO.

ros::Subscriber _odom_sub;

int estimator_type;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why int and not MAV_ESTIMATOR_TYPE?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@@ -49,14 +51,15 @@ class OdometryPlugin : public plugin::PluginBase {
}

private:
ros::NodeHandle _nh;
ros::NodeHandle odom_nh;
ros::Subscriber _odom_sub;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nh is fine. I don't like starting _, prefer m_ instead. But that isn't a problem.


lpos.time_usec = stamp;
lpos.estimator_type = estimator_type;
ROS_DEBUG_STREAM_NAMED("odom", "Odometry: estimator type: " << utils::to_string_enum<mavlink::common::MAV_ESTIMATOR_TYPE>(estimator_type));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why here? I think put that into initialize() is enough.

i += 1;
}
}
UAS_FCU(m_uas)->send_message_ignore_drop(lpos);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that not needed. Fill one message + send is fine.

for (size_t i = 0; i < SIZE; i++) {
covmsg[i] = cov[i];
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why? std::copy() does not work?

@TSC21
Copy link
Member

TSC21 commented May 10, 2017

Now looks better. One thing that i'm not sure: maybe call it send_odom?

As it is I think we could but probably the next set should be add handlers for LOCAL_POSITION_NED_COV and ATTITUDE_QUATERNION_COV and publish those in a ROS Odometry msg.

@TSC21
Copy link
Member

TSC21 commented May 10, 2017

Ok right now there are two things left to be fixed:

  • Understand why is the code giving matrix out of bounds for the covariance
  • Understand how to properly apply the rotation for angular velocity to the body frame

@jgoppert will do some tests on the simulation as soon as I can.

@TSC21 TSC21 modified the milestone: Version 0.20 May 10, 2017
* @brief Auxiliar matrices to Covariance transforms
*/
using Affine6dTF = Eigen::Matrix<double, 6, 6>;
using Affine9dTF = Eigen::Matrix<double, 9, 9>;
Copy link
Member

@TSC21 TSC21 May 14, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I probably have to, instead of creating a affine 6d transform (which seems not being working correctly), apply a Affine3d for each rotation and then build the covariance matrix with the diagonal blocks already rotated - the current output seems that it is just multiplying the matrices (rotation times covariance) but not applying the rotation the main diagonal blocks (which is expected from affine times matrix).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here's an example:

[ INFO] [1494793156.340441773, 8.962000000]: Odometry: Cov URT: 
 4.97062e-10 -1.50062e-57            0            0            0            0            0            0            0
           0  4.97062e-10 -1.26289e-42            0            0            0            0            0            0
           0            0  4.97062e-10            0            0            0            0            0            0
           0            0            0       0.0002 -6.03797e-52            0            0            0            0
           0            0            0            0       0.0002 -5.08144e-37            0            0            0
           0            0            0            0            0       0.0002            0            0            0
           0            0            0            0            0            0            1 -3.01899e-48            0
           0            0            0            0            0            0            0            1 -2.54072e-33
           0            0            0            0            0            0            0            0            1

@mhkabir
Copy link
Member

mhkabir commented May 14, 2017

Hey guys, I can help out with this now that I have some free time. It would be good to get a brief on the open stuff @vooon @TSC21. Also squashing the commits would be nice - the diff looks very clean already.

I did a plugin (not upstreamable) when I developed the API for PX4 (PX4/PX4-Autopilot#6074). You can find that here : https://github.com/ProjectArtemis/mavros/blob/f043fa951657aa74c0219da836329367a395208f/mavros_extras/src/plugins/estimator_bridge.cpp

It does a bunch of things, and the frame transforms are all verified, and it has several hours of GPS-denied flight on it. We have a stable version of that interface running on some of our vehicles out in the field in active service.

@TSC21
Copy link
Member

TSC21 commented May 14, 2017

Thanks for the help @mhkabir. But taking a look at your code seems that you are hardcoding the covariance. The purpose right now is apply the transform over a covariance being received from an external estimator. I already know what to do, so tomorrow I will push the final change so to merge this. Cheers

@TSC21
Copy link
Member

TSC21 commented May 15, 2017

The new URT of the rotated covariance after the new commit:

 1.44017e-27  6.48596e-12  7.94301e-28            0            0            0            0            0            0
           0 -1.44017e-27 -1.59891e-43            0            0            0            0            0            0
           0            0 -6.48596e-12            0            0            0            0            0            0
           0            0            0  4.44089e-20       0.0002  2.44929e-20            0            0            0
           0            0            0            0 -4.44089e-20 -4.93038e-36            0            0            0
           0            0            0            0            0      -0.0002            0            0            0
           0            0            0            0            0            0  2.22045e-16            1  1.22465e-16
           0            0            0            0            0            0            0 -2.22045e-16 -2.46519e-32
           0            0            0            0            0            0            0            0           -1

Seems an acceptable rotation now.
So it lgtm in my opinion.
@jgoppert, @vooon should we merge this then?

@TSC21 TSC21 force-pushed the odom branch 2 times, most recently from 93f2292 to e76d1b2 Compare May 15, 2017 20:21
@TSC21
Copy link
Member

TSC21 commented May 16, 2017

After talking with @jgoppert I came to the conclusion that the first implementation was right. So I remove the last changes and apply a definitive commit.
Here's the latest covariance result after rotation:

[ INFO] [1494943715.279968291, 11.882000000]: Odometry: Cov URT: 
 2.20784e-10 -6.66544e-58            0            0            0            0            0            0            0
           0  2.20784e-10  -5.6095e-43            0            0            0            0            0            0
           0            0  2.20784e-10            0            0            0            0            0            0
           0            0            0       0.0002 -6.03797e-52            0            0            0            0
           0            0            0            0       0.0002 -5.08144e-37            0            0            0
           0            0            0            0            0       0.0002            0            0            0
           0            0            0            0            0            0            1 -3.01899e-48            0
           0            0            0            0            0            0            0            1 -2.54072e-33
           0            0            0            0            0            0            0            0            1

@TSC21
Copy link
Member

TSC21 commented May 16, 2017

In any case we should consider, in the future, rely on tf2 to apply the transforms.

@jgoppert, @vooon lgtm?

@jgoppert
Copy link
Member Author

Yeah, that diagonal looks good now.

/**
* @brief Odometry plugin
* @file odom.cpp
* @author James Goppert <james.goppert8@gmail.com>
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@TSC21 should probably add your name here, and also can you fix my email above, has an extra 8.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mail fixed. No need to add my email. It was your idea and your implementation. I just added some features and robustness ;)

@vooon
Copy link
Member

vooon commented May 16, 2017

Oh, NOOOO! :) I mean in global_position, where huge matrix looks not great.
But in tf that small

r << m, 0, 0,
     0, m, 0,
     0, 0, m;

Way better than:

r.block(0,0) = m;
r.block(1,1) = m;
r.block(2,2) = m;

@TSC21
Copy link
Member

TSC21 commented May 16, 2017

We have 6d and 9d matrices. What do you mean by small?
This avoids creating extra eigen matrices and just use blocks.

@vooon
Copy link
Member

vooon commented May 16, 2017

I mean that m visually hide 9d assign to looks like 3d.
But yes, assigning of blocks should be faster. And in some cases m.setZero() is not needed.

@TSC21
Copy link
Member

TSC21 commented May 16, 2017

@vooon lgtm?

@mhkabir
Copy link
Member

mhkabir commented May 16, 2017

Nuno, lgtm is "Looks Good To Me" :D

@TSC21
Copy link
Member

TSC21 commented May 16, 2017

Nuno, lgtm is "Looks Good To Me" :D

Always learning xD well I was asking looks good to Merge eheh

@TSC21
Copy link
Member

TSC21 commented May 16, 2017

Can we merge this then?

@vooon
Copy link
Member

vooon commented May 17, 2017

Yes, LGTM. But i will manually rebase it to master.

@vooon
Copy link
Member

vooon commented May 17, 2017

@jgoppert merge of @TSC21 changes broke rebase. @TSC21 are you ok if i squash all into single commit?

@TSC21
Copy link
Member

TSC21 commented May 17, 2017

Sure no prob @vooon

@vooon
Copy link
Member

vooon commented May 17, 2017

I will try to apply full patch and then edit history to split lib frame_tf changes and plugin. But it not succeed then i simply squash & commit.

@vooon vooon mentioned this pull request May 17, 2017
@vooon
Copy link
Member

vooon commented May 17, 2017

Rebased to master. @jgoppert, @TSC21 please test because i done some style changes that may result in different math results (but should not!).

@vooon vooon closed this May 17, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants