Skip to content

Commit 70216b9

Browse files
committed
initialize world_origin with RTK when available
1 parent 42970dd commit 70216b9

File tree

4 files changed

+175
-25
lines changed

4 files changed

+175
-25
lines changed

config/public/transform_manager/transform_manager.yaml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,15 @@ mrs_uav_managers:
3737
parent: "fcu_untilted" # fcu should be the parent if using the default inverted mrs tf tree convention with fcu as the root of the tf tree
3838
child: "amsl_origin"
3939

40+
# frame_id with the frame defined by the position of the RTK antenna
41+
rtk_antenna:
42+
frame_id: "rtk_antenna"
43+
4044
# the list of additional source topics from which the tfs will be constructed
4145
tf_sources: []
4246

4347
# first available tf source from this list will produce the utm and world origin tfs
44-
utm_source_priority: ["ground_truth", "rtk", "gps_garmin", "gps_baro"]
48+
utm_source_priority: ["rtk_garmin", "rtk", "gps_garmin", "gps_baro"]
4549

4650
# configuration of individual tf sources
4751
hw_api_raw:

include/transform_manager/tf_source.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -352,9 +352,14 @@ class TfSource {
352352
/*//}*/
353353

354354
/*//{ tf utm origin */
355+
355356
geometry_msgs::TransformStamped tf_utm_msg;
356357
if (is_utm_source_) {
357-
358+
359+
if (!is_utm_origin_set_) {
360+
ROS_INFO_THROTTLE(5.0, "[%s]: %s utm_origin initialization", getPrintName().c_str(), Support::waiting_for_string.c_str());
361+
return;
362+
}
358363

359364
geometry_msgs::Pose pose_utm = odom->pose.pose;
360365
pose_utm.position.x += utm_origin_.x - first_msg_->pose.pose.position.x;

launch/transform_manager.launch

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
<remap from="~height_agl_in" to="estimation_manager/height_agl" />
6262
<remap from="~orientation_in" to="hw_api/orientation" />
6363
<remap from="~gnss_in" to="hw_api/gnss" />
64+
<remap from="~rtk_gps_in" to="hw_api/rtk" />
6465
<remap from="~altitude_amsl_in" to="hw_api/altitude" />
6566

6667
<!-- Publishers -->

src/transform_manager/transform_manager.cpp

Lines changed: 163 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <mrs_msgs/UavState.h>
1515
#include <mrs_msgs/Float64Stamped.h>
1616
#include <mrs_msgs/HwApiAltitude.h>
17+
#include <mrs_msgs/RtkGps.h>
1718

1819
#include <tf2_ros/transform_broadcaster.h>
1920
#include <tf2_ros/static_transform_broadcaster.h>
@@ -129,6 +130,11 @@ class TransformManager : public nodelet::Nodelet {
129130
void callbackGnss(const sensor_msgs::NavSatFix::ConstPtr msg);
130131
std::atomic<bool> got_utm_offset_ = false;
131132

133+
mrs_lib::SubscribeHandler<mrs_msgs::RtkGps> sh_rtk_gps_;
134+
void callbackRtkGps(const mrs_msgs::RtkGps::ConstPtr msg);
135+
136+
std::optional<geometry_msgs::Pose> transformRtkToFcu(const geometry_msgs::PoseStamped& pose_in) const;
137+
132138
void publishFcuUntiltedTf(const geometry_msgs::QuaternionStampedConstPtr& msg);
133139
};
134140
/*//}*/
@@ -279,6 +285,9 @@ void TransformManager::onInit() {
279285

280286
/*//}*/
281287

288+
param_loader.loadParam(yaml_prefix + "rtk_antenna/frame_id", ch_->frames.rtk_antenna);
289+
ch_->frames.ns_rtk_antenna = ch_->uav_name + "/" + ch_->frames.rtk_antenna;
290+
282291
param_loader.loadParam("mrs_uav_managers/estimation_manager/state_estimators", estimator_names_);
283292
param_loader.loadParam(yaml_prefix + "tf_sources", tf_source_names_);
284293

@@ -396,7 +405,11 @@ void TransformManager::onInit() {
396405
sh_hw_api_orientation_ =
397406
mrs_lib::SubscribeHandler<geometry_msgs::QuaternionStamped>(shopts, "orientation_in", &TransformManager::callbackHwApiOrientation, this);
398407

399-
sh_gnss_ = mrs_lib::SubscribeHandler<sensor_msgs::NavSatFix>(shopts, "gnss_in", &TransformManager::callbackGnss, this);
408+
if (utm_source_name_ == "rtk" || utm_source_name_ == "rtk_garmin") {
409+
sh_rtk_gps_ = mrs_lib::SubscribeHandler<mrs_msgs::RtkGps>(shopts, "rtk_gps_in", &TransformManager::callbackRtkGps, this);
410+
} else {
411+
sh_gnss_ = mrs_lib::SubscribeHandler<sensor_msgs::NavSatFix>(shopts, "gnss_in", &TransformManager::callbackGnss, this);
412+
}
400413
/*//}*/
401414

402415
if (!param_loader.loadedSuccessfully()) {
@@ -708,38 +721,122 @@ void TransformManager::callbackGnss(const sensor_msgs::NavSatFix::ConstPtr msg)
708721
return;
709722
}
710723

724+
if (got_utm_offset_) {
725+
return;
726+
}
727+
711728
mrs_lib::ScopeTimer scope_timer = mrs_lib::ScopeTimer("TransformManager::callbackGnss", ch_->scope_timer.logger, ch_->scope_timer.enabled);
712729

713-
if (!got_utm_offset_) {
730+
double out_x;
731+
double out_y;
732+
733+
mrs_lib::UTM(msg->latitude, msg->longitude, &out_x, &out_y);
714734

715-
double out_x;
716-
double out_y;
735+
if (!std::isfinite(out_x)) {
736+
ROS_ERROR_THROTTLE(1.0, "[%s]: NaN detected in UTM variable \"out_x\"!!!", getPrintName().c_str());
737+
return;
738+
}
717739

718-
mrs_lib::UTM(msg->latitude, msg->longitude, &out_x, &out_y);
740+
if (!std::isfinite(out_y)) {
741+
ROS_ERROR_THROTTLE(1.0, "[%s]: NaN detected in UTM variable \"out_y\"!!!", getPrintName().c_str());
742+
return;
743+
}
719744

720-
if (!std::isfinite(out_x)) {
721-
ROS_ERROR_THROTTLE(1.0, "[Odometry]: NaN detected in UTM variable \"out_x\"!!!");
722-
return;
723-
}
745+
geometry_msgs::Point utm_origin;
746+
utm_origin.x = out_x;
747+
utm_origin.y = out_y;
748+
utm_origin.z = msg->altitude;
724749

725-
if (!std::isfinite(out_y)) {
726-
ROS_ERROR_THROTTLE(1.0, "[Odometry]: NaN detected in UTM variable \"out_y\"!!!");
727-
return;
728-
}
750+
ROS_INFO("[%s]: utm_origin position calculated as: x: %.2f, y: %.2f, z: %.2f from GNSS", getPrintName().c_str(), utm_origin.x, utm_origin.y, utm_origin.z);
751+
752+
for (size_t i = 0; i < tf_sources_.size(); i++) {
753+
tf_sources_[i]->setUtmOrigin(utm_origin);
754+
tf_sources_[i]->setWorldOrigin(world_origin_);
755+
}
756+
got_utm_offset_ = true;
757+
}
758+
/*//}*/
729759

730-
geometry_msgs::Point utm_origin;
731-
utm_origin.x = out_x;
732-
utm_origin.y = out_y;
733-
utm_origin.z = msg->altitude;
760+
/*//{ callbackRtkGps() */
761+
void TransformManager::callbackRtkGps(const mrs_msgs::RtkGps::ConstPtr msg) {
734762

735-
ROS_INFO("[%s]: utm_origin position calculated as: x: %.2f, y: %.2f, z: %.2f", getPrintName().c_str(), utm_origin.x, utm_origin.y, utm_origin.z);
763+
if (!is_initialized_) {
764+
return;
765+
}
736766

737-
for (size_t i = 0; i < tf_sources_.size(); i++) {
738-
tf_sources_[i]->setUtmOrigin(utm_origin);
739-
tf_sources_[i]->setWorldOrigin(world_origin_);
740-
}
741-
got_utm_offset_ = true;
767+
if (got_utm_offset_) {
768+
return;
769+
}
770+
771+
mrs_lib::ScopeTimer scope_timer = mrs_lib::ScopeTimer("TransformManager::callbackRtkGps", ch_->scope_timer.logger, ch_->scope_timer.enabled);
772+
773+
double out_x;
774+
double out_y;
775+
776+
geometry_msgs::PoseStamped rtk_pos;
777+
778+
if (!std::isfinite(msg->gps.latitude)) {
779+
ROS_ERROR_THROTTLE(1.0, "[%s] NaN detected in RTK variable \"msg->latitude\"!!!", getPrintName().c_str());
780+
return;
781+
}
782+
783+
if (!std::isfinite(msg->gps.longitude)) {
784+
ROS_ERROR_THROTTLE(1.0, "[%s] NaN detected in RTK variable \"msg->longitude\"!!!", getPrintName().c_str());
785+
return;
742786
}
787+
788+
if (!std::isfinite(msg->gps.altitude)) {
789+
ROS_ERROR_THROTTLE(1.0, "[%s] NaN detected in RTK variable \"msg->altitude\"!!!", getPrintName().c_str());
790+
return;
791+
}
792+
793+
if (msg->fix_type.fix_type != mrs_msgs::RtkFixType::RTK_FIX) {
794+
ROS_INFO_THROTTLE(1.0, "[%s] %s RTK FIX", getPrintName().c_str(), Support::waiting_for_string.c_str());
795+
return;
796+
}
797+
798+
rtk_pos.header = msg->header;
799+
mrs_lib::UTM(msg->gps.latitude, msg->gps.longitude, &rtk_pos.pose.position.x, &rtk_pos.pose.position.y);
800+
rtk_pos.pose.position.z = msg->gps.altitude;
801+
rtk_pos.pose.orientation = mrs_lib::AttitudeConverter(0, 0, 0);
802+
803+
rtk_pos.pose.position.x -= ch_->world_origin.x;
804+
rtk_pos.pose.position.y -= ch_->world_origin.y;
805+
806+
807+
// transform the RTK position from antenna to FCU
808+
auto res = transformRtkToFcu(rtk_pos);
809+
if (res) {
810+
rtk_pos.pose = res.value();
811+
} else {
812+
ROS_ERROR_THROTTLE(1.0, "[%s]: transform to fcu failed", getPrintName().c_str());
813+
return;
814+
}
815+
816+
mrs_lib::UTM(msg->gps.latitude, msg->gps.longitude, &out_x, &out_y);
817+
818+
if (!std::isfinite(out_x)) {
819+
ROS_ERROR_THROTTLE(1.0, "[%s]: NaN detected in UTM variable \"out_x\"!!!", getPrintName().c_str());
820+
return;
821+
}
822+
823+
if (!std::isfinite(out_y)) {
824+
ROS_ERROR_THROTTLE(1.0, "[%s]: NaN detected in UTM variable \"out_y\"!!!", getPrintName().c_str());
825+
return;
826+
}
827+
828+
geometry_msgs::Point utm_origin;
829+
utm_origin.x = out_x;
830+
utm_origin.y = out_y;
831+
utm_origin.z = msg->gps.altitude;
832+
833+
ROS_INFO("[%s]: utm_origin position calculated as: x: %.2f, y: %.2f, z: %.2f from RTK msg", getPrintName().c_str(), utm_origin.x, utm_origin.y, utm_origin.z);
834+
835+
for (size_t i = 0; i < tf_sources_.size(); i++) {
836+
tf_sources_[i]->setUtmOrigin(utm_origin);
837+
tf_sources_[i]->setWorldOrigin(world_origin_);
838+
}
839+
got_utm_offset_ = true;
743840
}
744841
/*//}*/
745842

@@ -786,6 +883,49 @@ void TransformManager::publishFcuUntiltedTf(const geometry_msgs::QuaternionStamp
786883
}
787884
/*//}*/
788885

886+
/*//{ transformRtkToFcu() */
887+
std::optional<geometry_msgs::Pose> TransformManager::transformRtkToFcu(const geometry_msgs::PoseStamped& pose_in) const {
888+
889+
geometry_msgs::PoseStamped pose_tmp = pose_in;
890+
891+
// inject current orientation into rtk pose
892+
auto res1 = ch_->transformer->getTransform(ch_->frames.ns_fcu_untilted, ch_->frames.ns_fcu, ros::Time::now());
893+
if (res1) {
894+
pose_tmp.pose.orientation = res1.value().transform.rotation;
895+
} else {
896+
ROS_ERROR_THROTTLE(1.0, "[%s]: Could not obtain transform from %s to %s.", getPrintName().c_str(),
897+
ch_->frames.ns_fcu_untilted.c_str(), ch_->frames.ns_fcu.c_str());
898+
return {};
899+
}
900+
901+
// invert tf
902+
tf2::Transform tf_utm_to_antenna = Support::tf2FromPose(pose_tmp.pose);
903+
geometry_msgs::PoseStamped utm_in_antenna;
904+
utm_in_antenna.pose = Support::poseFromTf2(tf_utm_to_antenna.inverse());
905+
utm_in_antenna.header.stamp = pose_in.header.stamp;
906+
utm_in_antenna.header.frame_id = ch_->frames.ns_rtk_antenna;
907+
908+
// transform to fcu
909+
geometry_msgs::PoseStamped utm_in_fcu;
910+
utm_in_fcu.header.frame_id = ch_->frames.ns_fcu;
911+
utm_in_fcu.header.stamp = pose_in.header.stamp;
912+
auto res2 = ch_->transformer->transformSingle(utm_in_antenna, ch_->frames.ns_fcu);
913+
914+
if (res2) {
915+
utm_in_fcu = res2.value();
916+
} else {
917+
ROS_ERROR_THROTTLE(1.0, "[%s]: Could not transform RTK pose from %s to %s.", getPrintName().c_str(), utm_in_antenna.header.frame_id.c_str(), ch_->frames.ns_fcu.c_str());
918+
return {};
919+
}
920+
921+
// invert tf
922+
tf2::Transform tf_fcu_to_utm = Support::tf2FromPose(utm_in_fcu.pose);
923+
geometry_msgs::Pose fcu_in_utm = Support::poseFromTf2(tf_fcu_to_utm.inverse());
924+
925+
return fcu_in_utm;
926+
}
927+
/*//}*/
928+
789929
/*//{ getName() */
790930
std::string TransformManager::getName() const {
791931
return name_;

0 commit comments

Comments
 (0)