77 ros::TransportHints().tcpNoDelay());
85 this, ros::TransportHints().tcpNoDelay());
109 <<
" Initialized Legged Velocity Unary Factor Odometry subscriber with topic: " <<
subLeggedVelocityUnary_.getTopic()
133 holistic_fusion_ros_msgs::OfflineOptimizationTrigger::Response& res) {
140 const double referenceLatitude =
gnssHandlerPtr_->getGnssReferenceLatitude();
141 const double referenceLongitude =
gnssHandlerPtr_->getGnssReferenceLongitude();
142 const double referenceAltitude =
gnssHandlerPtr_->getGnssReferenceAltitude();
143 const double referenceHeading =
gnssHandlerPtr_->getGnssReferenceHeading();
144 REGULAR_COUT <<
" GNSS reference (latitude, longitude, altitude, heading): " << referenceLatitude <<
", " << referenceLongitude <<
", "
145 << referenceAltitude <<
", " << referenceHeading << std::endl;
148 std::map<std::string, std::ofstream> fileStreams;
153 if (timeString.empty()) {
160 std::string transformIdentifier =
"gnss_reference_lat_lon_alt";
164 transformIdentifier, ros::Time::now().toSec());
165 REGULAR_COUT <<
" Wrote GNSS reference (latitude, longitude, altitude) coordinates to file." << std::endl;
169 transformIdentifier =
"gnss_enu_trajectory";
175 Eigen::Isometry3d optionalGnssEnuCoordinatesIsometry = Eigen::Isometry3d::Identity();
176 optionalGnssEnuCoordinatesIsometry.translation() = optionalGnssEnuCoordinates;
195 Eigen::Vector3d gnssCoord = Eigen::Vector3d(gnssMsgPtr->latitude, gnssMsgPtr->longitude, gnssMsgPtr->altitude);
196 Eigen::Vector3d estStdDevXYZ(sqrt(gnssMsgPtr->position_covariance[0]), sqrt(gnssMsgPtr->position_covariance[4]),
197 sqrt(gnssMsgPtr->position_covariance[8]));
204 REGULAR_COUT <<
" NOT ENOUGH GNSS MESSAGES ARRIVED!" << std::endl;
209 REGULAR_COUT <<
" GNSS Handler initialized." << std::endl;
214 Eigen::Vector3d W_t_W_Gnss;
236 double initYaw_W_Base{0.0};
239 initYaw_W_Base =
gnssHandlerPtr_->getGlobalYawDegFromFile() / 180.0 * M_PI;
246 Eigen::Isometry3d T_W_Base = Eigen::Isometry3d::Identity();
254 << 180.0 * initYaw_W_Base / M_PI << std::endl;
299 Eigen::Isometry3d lio_T_M_Lk = Eigen::Isometry3d::Identity();
301 double lidarUnaryTimeK = odomLidarPtr->header.stamp.toSec();
344 Eigen::Isometry3d lio_T_M_Lk = Eigen::Isometry3d::Identity();
347 double lidarBetweenTimeK = odomLidarPtr->header.stamp.toSec();
378 const Eigen::Isometry3d T_Lkm1_Lk =
lio_T_M_Lkm1_.inverse() * lio_T_M_Lk;
409 Eigen::Isometry3d T_O_Bl_k = Eigen::Isometry3d::Identity();
411 double legOdometryTimeK = leggedOdometryPoseKPtr->header.stamp.toSec();
421 const std::string& leggedOdometryFrameName =
442 const Eigen::Isometry3d T_Bkm1_Bk =
T_O_Bl_km1_.inverse() * T_O_Bl_k;
487 Eigen::Vector3d legVelocity = Eigen::Vector3d(leggedOdometryKPtr->twist.twist.linear.x, leggedOdometryKPtr->twist.twist.linear.y,
488 leggedOdometryKPtr->twist.twist.linear.z);
491 const std::string& leggedOdometryFrameName =
521 Eigen::Matrix<double, 6, 1>::Identity());
536 const std::string& leggedOdometryFrameName =
540 Eigen::Isometry3d T_O_B = Eigen::Isometry3d::Identity();
544 visualization_msgs::MarkerArray footContactMarkers = visualization_msgs::MarkerArray();
546 for (
int legIndex = 0; legIndex <
legNames_.size(); ++legIndex) {
548 bool footInContact = anymalStatePtr->contacts[legIndex].state;
550 const std::string legName = anymalStatePtr->contacts[legIndex].name;
572 Eigen::Vector3d O_t_O_foot =
573 Eigen::Vector3d(anymalStatePtr->contacts[legIndex].position.x, anymalStatePtr->contacts[legIndex].position.y,
574 anymalStatePtr->contacts[legIndex].position.z);
575 Eigen::Vector3d B_t_B_foot = T_O_B.inverse() * O_t_O_foot;
578 std::string legIdentifier = legName;
588 visualization_msgs::Marker footContactMarker;
589 createContactMarker(leggedOdometryFrameName, anymalStatePtr->header.stamp, B_t_B_foot,
"foot_contact", legIndex,
590 Eigen::Vector3d(0.0, 1.0, 0.0), footContactMarker);
591 footContactMarkers.markers.push_back(footContactMarker);
600 REGULAR_COUT <<
" Leg " << legName <<
" lost contact. " << std::endl;
603 visualization_msgs::Marker deleteMarker;
604 deleteMarker.header.frame_id = leggedOdometryFrameName;
605 deleteMarker.header.stamp = anymalStatePtr->header.stamp;
606 deleteMarker.ns =
"foot_contact";
607 deleteMarker.id = legIndex;
608 deleteMarker.action = visualization_msgs::Marker::DELETE;
609 footContactMarkers.markers.push_back(deleteMarker);
#define NUM_GNSS_CALLBACKS_UNTIL_START
int leggedOdometryOdomCallbackCounter_
ros::Subscriber subGnssUnary_
Eigen::Isometry3d lio_T_M_Lkm1_
double gnssPositionOutlierThreshold_
Eigen::Matrix< double, 6, 1 > initialSe3AlignmentNoise_
Eigen::Matrix< double, 6, 1 > legPoseBetweenNoise_
nav_msgs::PathPtr measGnss_worldGnssPathPtr_
nav_msgs::PathPtr measLio_mapLidarPathPtr_
void leggedBetweenCallback_(const geometry_msgs::PoseWithCovarianceStamped::ConstPtr &leggedOdometryPoseKPtr)
void initializePublishers(ros::NodeHandle &privateNode) override
ros::Publisher pubMeasMapLioPath_
ros::Subscriber subLeggedBetween_
void initializeSubscribers(ros::NodeHandle &privateNode) override
Eigen::Matrix< double, 3, 1 > legVelocityUnaryNoise_
void gnssUnaryCallback_(const sensor_msgs::NavSatFix::ConstPtr &gnssPtr)
double lidarBetweenTimeKm1_
void leggedVelocityUnaryCallback_(const nav_msgs::Odometry::ConstPtr &leggedOdometryKPtr)
bool useLeggedKinematicsFlag_
int lidarUnaryCallbackCounter_
double leggedOdometryVelocityRate_
int leggedOdometryPoseCallbackCounter_
std::shared_ptr< holistic_fusion::GnssHandler > gnssHandlerPtr_
static constexpr long legInContactDebounceThreshold_
bool srvOfflineSmootherOptimizeCallback(holistic_fusion_ros_msgs::OfflineOptimizationTrigger::Request &req, holistic_fusion_ros_msgs::OfflineOptimizationTrigger::Response &res) override
bool useLeggedVelocityUnaryFlag_
int leggedOdometryVelocityDownsampleFactor_
int leggedOdometryPoseDownsampleFactor_
AnymalEstimator(const std::shared_ptr< ros::NodeHandle > &privateNodePtr)
void leggedKinematicsCallback_(const holistic_fusion_anymal_msgs::AnymalState::ConstPtr &anymalStatePtr)
Eigen::Isometry3d T_O_Bl_km1_
void lidarBetweenCallback_(const nav_msgs::Odometry::ConstPtr &lidar_odom_ptr)
double leggedOdometryBetweenRate_
static constexpr std::array< const char *, 4 > legNames_
Eigen::Matrix< double, 3, 1 > legKinematicsFootPositionUnaryNoise_
void initializeMessages(ros::NodeHandle &privateNode) override
ros::Subscriber subLeggedKinematics_
int leggedKinematicsCallbackCounter_
std::shared_ptr< holistic_fusion::TrajectoryAlignmentHandler > trajectoryAlignmentHandler_
int leggedKinematicsDownsampleFactor_
std::vector< Eigen::Vector3d > optionalGnssEnuCoordinatesTrajectory_
std::vector< double > optionalGnssEnuCoordinatesTimeStamps_
std::array< long, legNames_.size()> legInContactForNSteps_
double legOdometryTimeKm1_
ros::Subscriber subLioBetween_
double leggedKinematicsRate_
Eigen::Matrix< double, 6, 1 > lioSe3AlignmentRandomWalk_
Eigen::Vector3d accumulatedGnssCoordinates_
void readParams(const ros::NodeHandle &privateNode) override
ros::Publisher pubMeasWorldGnssPath_
ros::Subscriber subLeggedVelocityUnary_
Eigen::Matrix< double, 6, 1 > lioPoseUnaryNoise_
void initializeServices_(ros::NodeHandle &privateNode)
ros::Subscriber subLioUnary_
void lidarUnaryCallback_(const nav_msgs::Odometry::ConstPtr &lidar_odom_ptr)
ros::Publisher pubFootContactMarkers_
std::array< long, legNames_.size()> legTotalContactsCounter_
int lidarBetweenCallbackCounter_
bool useLeggedBetweenFlag_
static constexpr bool logOptionalGnssEnuCoordinatesFlag_
void addBinaryPose3Measurement(const BinaryMeasurementXD< Eigen::Isometry3d, 6 > &F_T_F_S) override
Binary Measurements.
void addUnaryPosition3AbsoluteMeasurement(UnaryMeasurementXDAbsolute< Eigen::Vector3d, 3 > &R_t_R_S) override
void addUnaryPose3AbsoluteMeasurement(const UnaryMeasurementXDAbsolute< Eigen::Isometry3d, 6 > &R_T_R_S, const bool addToOnlineSmootherFlag=true) override
Unary Measurements / Absolute Measurements: In reference frame --> systematic drift.
void addUnaryVelocity3LocalMeasurement(UnaryMeasurementXD< Eigen::Vector3d, 3 > &S_v_F_S) override
void addUnaryPosition3LandmarkMeasurement(UnaryMeasurementXDLandmark< Eigen::Vector3d, 3 > &S_t_S_L, const int landmarkCreationCounter) override
Landmark Measurements: No systematic drift.
virtual bool srvOfflineSmootherOptimizeCallback(holistic_fusion_ros_msgs::OfflineOptimizationTrigger::Request &req, holistic_fusion_ros_msgs::OfflineOptimizationTrigger::Response &res)
std::string sensorFrameCorrectedNameId
static void addToPathMsg(const nav_msgs::PathPtr &pathPtr, const std::string &frameName, const ros::Time &stamp, const Eigen::Vector3d &t, int maxBufferLength)
static void createContactMarker(const std::string &referenceFrameName, const ros::Time &stamp, const Eigen::Vector3d &position, const std::string &nameSpace, const int id, const Eigen::Vector3d &colorRgb, visualization_msgs::Marker &marker)
std::string referenceFrameAlignedNameId
std::string optimizationResultLoggingPath
ros::NodeHandle privateNode
HolisticFusionRos(const std::shared_ptr< ros::NodeHandle > &privateNodePtr)
std::shared_ptr< GraphConfig > graphConfigPtr_
bool initYawAndPositionInWorld(const double yaw_W_frame1, const Eigen::Vector3d &W_t_W_frame2, const std::string &frame1, const std::string &frame2)
bool areYawAndPositionInited() const
bool areRollAndPitchInited() const
std::shared_ptr< StaticTransforms > staticTransformsPtr_
bool initYawAndPosition(const UnaryMeasurementXD< Eigen::Isometry3d, 6 > &unary6DMeasurement)
Class to represent x-dimensional absolute unary measurement in the graph.
Class to represent x-dimensional landmark unary measurement in the graph.
Class to represent x-dimensional unary measurement in the graph.
void createPose3CsvFileStream(std::map< std::string, std::ofstream > &fileStreams, const std::string &savePath, const std::string &transformIdentifier, const std::string &timeString, const bool saveCovarianceFlag)
void createLatLonAltCsvFileStream(std::map< std::string, std::ofstream > &fileStreams, const std::string &savePath, const std::string &transformIdentifier, const std::string &timeString)
void odomMsgToEigen(const nav_msgs::Odometry &odomLidar, Eigen::Matrix4d &T)
void writeLatLonAltToCsvFile(std::map< std::string, std::ofstream > &fileStreams, const Eigen::Vector3d &latLonAlt, const std::string &transformIdentifier, const double timeStamp)
void geometryPoseToEigen(const geometry_msgs::Pose &pose, Eigen::Matrix4d &T)
std::string getLatestSubdirectory(const std::string &directoryPath)
void writePose3ToCsvFile(std::map< std::string, std::ofstream > &fileStreams, const Eigen::Isometry3d pose, const std::string &transformIdentifier, const double timeStamp, const bool saveCovarianceFlag, const std::optional< Eigen::Matrix< double, 6, 6 > > &optionalPoseCovarianceInWorldRos=std::nullopt)