mirror of
https://github.com/introlab/rtabmap_ros.git
synced 2026-10-04 08:47:45 +08:00
0.18.3: added apriltags2 support (input topic: tag_detections)
This commit is contained in:
+15
-1
@@ -25,12 +25,13 @@ find_package(catkin REQUIRED COMPONENTS
|
|||||||
# Optional components
|
# Optional components
|
||||||
find_package(costmap_2d)
|
find_package(costmap_2d)
|
||||||
find_package(octomap_msgs)
|
find_package(octomap_msgs)
|
||||||
|
find_package(apriltags2_ros)
|
||||||
find_package(rviz)
|
find_package(rviz)
|
||||||
find_package(find_object_2d)
|
find_package(find_object_2d)
|
||||||
|
|
||||||
## System dependencies are found with CMake's conventions
|
## System dependencies are found with CMake's conventions
|
||||||
# find_package(Boost REQUIRED COMPONENTS system)
|
# find_package(Boost REQUIRED COMPONENTS system)
|
||||||
find_package(RTABMap 0.18.2 REQUIRED)
|
find_package(RTABMap 0.18.3 REQUIRED)
|
||||||
|
|
||||||
find_package(OpenCV REQUIRED)
|
find_package(OpenCV REQUIRED)
|
||||||
|
|
||||||
@@ -240,6 +241,19 @@ SET(Libraries
|
|||||||
ADD_DEFINITIONS("-DWITH_OCTOMAP_MSGS")
|
ADD_DEFINITIONS("-DWITH_OCTOMAP_MSGS")
|
||||||
ENDIF(octomap_msgs_FOUND)
|
ENDIF(octomap_msgs_FOUND)
|
||||||
|
|
||||||
|
# If apriltags2_ros is found, add definition
|
||||||
|
IF(apriltags2_ros_FOUND)
|
||||||
|
MESSAGE(STATUS "WITH apriltags2_ros")
|
||||||
|
include_directories(
|
||||||
|
${apriltags2_ros_INCLUDE_DIRS}
|
||||||
|
)
|
||||||
|
SET(Libraries
|
||||||
|
${apriltags2_ros_LIBRARIES}
|
||||||
|
${Libraries}
|
||||||
|
)
|
||||||
|
ADD_DEFINITIONS("-DWITH_APRILTAGS2_ROS")
|
||||||
|
ENDIF(apriltags2_ros_FOUND)
|
||||||
|
|
||||||
# If rviz is found, add plugins
|
# If rviz is found, add plugins
|
||||||
IF(rviz_FOUND)
|
IF(rviz_FOUND)
|
||||||
MESSAGE(STATUS "WITH rviz")
|
MESSAGE(STATUS "WITH rviz")
|
||||||
|
|||||||
@@ -62,6 +62,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <octomap_msgs/GetOctomap.h>
|
#include <octomap_msgs/GetOctomap.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef WITH_APRILTAGS2_ROS
|
||||||
|
#include <apriltags2_ros/AprilTagDetectionArray.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <actionlib/client/simple_action_client.h>
|
#include <actionlib/client/simple_action_client.h>
|
||||||
#include <move_base_msgs/MoveBaseAction.h>
|
#include <move_base_msgs/MoveBaseAction.h>
|
||||||
#include <move_base_msgs/MoveBaseActionGoal.h>
|
#include <move_base_msgs/MoveBaseActionGoal.h>
|
||||||
@@ -129,6 +133,9 @@ private:
|
|||||||
void userDataAsyncCallback(const rtabmap_ros::UserDataConstPtr & dataMsg);
|
void userDataAsyncCallback(const rtabmap_ros::UserDataConstPtr & dataMsg);
|
||||||
void globalPoseAsyncCallback(const geometry_msgs::PoseWithCovarianceStampedConstPtr & globalPoseMsg);
|
void globalPoseAsyncCallback(const geometry_msgs::PoseWithCovarianceStampedConstPtr & globalPoseMsg);
|
||||||
void gpsFixAsyncCallback(const sensor_msgs::NavSatFixConstPtr & gpsFixMsg);
|
void gpsFixAsyncCallback(const sensor_msgs::NavSatFixConstPtr & gpsFixMsg);
|
||||||
|
#ifdef WITH_APRILTAGS2_ROS
|
||||||
|
void tagDetectionsAsyncCallback(const apriltags2_ros::AprilTagDetectionArray & tagDetections);
|
||||||
|
#endif
|
||||||
|
|
||||||
void initialPoseCallback(const geometry_msgs::PoseWithCovarianceStampedConstPtr & msg);
|
void initialPoseCallback(const geometry_msgs::PoseWithCovarianceStampedConstPtr & msg);
|
||||||
|
|
||||||
@@ -208,6 +215,8 @@ private:
|
|||||||
std::string databasePath_;
|
std::string databasePath_;
|
||||||
double odomDefaultAngVariance_;
|
double odomDefaultAngVariance_;
|
||||||
double odomDefaultLinVariance_;
|
double odomDefaultLinVariance_;
|
||||||
|
double landmarkDefaultAngVariance_;
|
||||||
|
double landmarkDefaultLinVariance_;
|
||||||
bool waitForTransform_;
|
bool waitForTransform_;
|
||||||
double waitForTransformDuration_;
|
double waitForTransformDuration_;
|
||||||
bool useActionForGoal_;
|
bool useActionForGoal_;
|
||||||
@@ -292,6 +301,8 @@ private:
|
|||||||
geometry_msgs::PoseWithCovarianceStamped globalPose_;
|
geometry_msgs::PoseWithCovarianceStamped globalPose_;
|
||||||
ros::Subscriber gpsFixAsyncSub_;
|
ros::Subscriber gpsFixAsyncSub_;
|
||||||
rtabmap::GPS gps_;
|
rtabmap::GPS gps_;
|
||||||
|
ros::Subscriber tagDetectionsSub_;
|
||||||
|
std::map<int, geometry_msgs::PoseWithCovarianceStamped> tags_;
|
||||||
|
|
||||||
bool stereoToDepth_;
|
bool stereoToDepth_;
|
||||||
bool odomSensorSync_;
|
bool odomSensorSync_;
|
||||||
|
|||||||
@@ -90,8 +90,8 @@ private:
|
|||||||
double mapFilterRadius_;
|
double mapFilterRadius_;
|
||||||
double mapFilterAngle_;
|
double mapFilterAngle_;
|
||||||
bool mapCacheCleanup_;
|
bool mapCacheCleanup_;
|
||||||
bool negativePosesIgnored_;
|
bool alwaysUpdateMap_;
|
||||||
bool negativeScanEmptyRayTracing_;
|
bool scanEmptyRayTracing_;
|
||||||
|
|
||||||
ros::Publisher cloudMapPub_;
|
ros::Publisher cloudMapPub_;
|
||||||
ros::Publisher cloudGroundPub_;
|
ros::Publisher cloudGroundPub_;
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <tf/transform_listener.h>
|
#include <tf/transform_listener.h>
|
||||||
#include <geometry_msgs/Transform.h>
|
#include <geometry_msgs/Transform.h>
|
||||||
#include <geometry_msgs/Pose.h>
|
#include <geometry_msgs/Pose.h>
|
||||||
|
#include <geometry_msgs/PoseWithCovarianceStamped.h>
|
||||||
#include <sensor_msgs/CameraInfo.h>
|
#include <sensor_msgs/CameraInfo.h>
|
||||||
#include <sensor_msgs/LaserScan.h>
|
#include <sensor_msgs/LaserScan.h>
|
||||||
#include <sensor_msgs/Image.h>
|
#include <sensor_msgs/Image.h>
|
||||||
@@ -150,6 +151,16 @@ void odomInfoToROS(const rtabmap::OdometryInfo & info, rtabmap_ros::OdomInfo & m
|
|||||||
cv::Mat userDataFromROS(const rtabmap_ros::UserData & dataMsg);
|
cv::Mat userDataFromROS(const rtabmap_ros::UserData & dataMsg);
|
||||||
void userDataToROS(const cv::Mat & data, rtabmap_ros::UserData & dataMsg, bool compress);
|
void userDataToROS(const cv::Mat & data, rtabmap_ros::UserData & dataMsg, bool compress);
|
||||||
|
|
||||||
|
rtabmap::Landmarks landmarksFromROS(
|
||||||
|
const std::map<int, geometry_msgs::PoseWithCovarianceStamped> & tags,
|
||||||
|
const std::string & frameId,
|
||||||
|
const std::string & odomFrameId,
|
||||||
|
const ros::Time & odomStamp,
|
||||||
|
tf::TransformListener & listener,
|
||||||
|
double waitForTransform,
|
||||||
|
double defaultLinVariance,
|
||||||
|
double defaultAngVariance);
|
||||||
|
|
||||||
inline double timestampFromROS(const ros::Time & stamp) {return double(stamp.sec) + double(stamp.nsec)/1000000000.0;}
|
inline double timestampFromROS(const ros::Time & stamp) {return double(stamp.sec) + double(stamp.nsec)/1000000000.0;}
|
||||||
|
|
||||||
// common stuff
|
// common stuff
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ private:
|
|||||||
bool visParams_;
|
bool visParams_;
|
||||||
bool icpParams_;
|
bool icpParams_;
|
||||||
rtabmap::Transform guess_;
|
rtabmap::Transform guess_;
|
||||||
double guessStamp_;
|
rtabmap::Transform guessPreviousPose_;
|
||||||
double previousStamp_;
|
double previousStamp_;
|
||||||
double expectedUpdateRate_;
|
double expectedUpdateRate_;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -100,6 +100,8 @@
|
|||||||
|
|
||||||
<arg name="gps_topic" default="/gps/fix" /> <!-- gps async subscription -->
|
<arg name="gps_topic" default="/gps/fix" /> <!-- gps async subscription -->
|
||||||
|
|
||||||
|
<arg name="tag_topic" default="/tag_detections" /> <!-- apriltags async subscription -->
|
||||||
|
|
||||||
<!-- These arguments should not be modified directly, see referred topics without "_relay" suffix above -->
|
<!-- These arguments should not be modified directly, see referred topics without "_relay" suffix above -->
|
||||||
<arg if="$(arg compressed)" name="rgb_topic_relay" default="$(arg rgb_topic)_relay"/>
|
<arg if="$(arg compressed)" name="rgb_topic_relay" default="$(arg rgb_topic)_relay"/>
|
||||||
<arg unless="$(arg compressed)" name="rgb_topic_relay" default="$(arg rgb_topic)"/>
|
<arg unless="$(arg compressed)" name="rgb_topic_relay" default="$(arg rgb_topic)"/>
|
||||||
@@ -256,6 +258,7 @@
|
|||||||
<param name="queue_size" type="int" value="$(arg queue_size)"/>
|
<param name="queue_size" type="int" value="$(arg queue_size)"/>
|
||||||
<param name="scan_normal_k" type="int" value="$(arg scan_normal_k)"/>
|
<param name="scan_normal_k" type="int" value="$(arg scan_normal_k)"/>
|
||||||
|
|
||||||
|
|
||||||
<remap from="rgb/image" to="$(arg rgb_topic_relay)"/>
|
<remap from="rgb/image" to="$(arg rgb_topic_relay)"/>
|
||||||
<remap from="depth/image" to="$(arg depth_topic_relay)"/>
|
<remap from="depth/image" to="$(arg depth_topic_relay)"/>
|
||||||
<remap from="rgb/camera_info" to="$(arg camera_info_topic)"/>
|
<remap from="rgb/camera_info" to="$(arg camera_info_topic)"/>
|
||||||
@@ -273,6 +276,7 @@
|
|||||||
<remap from="user_data" to="$(arg user_data_topic)"/>
|
<remap from="user_data" to="$(arg user_data_topic)"/>
|
||||||
<remap from="user_data_async" to="$(arg user_data_async_topic)"/>
|
<remap from="user_data_async" to="$(arg user_data_async_topic)"/>
|
||||||
<remap from="gps/fix" to="$(arg gps_topic)"/>
|
<remap from="gps/fix" to="$(arg gps_topic)"/>
|
||||||
|
<remap from="tag_detections" to="$(arg tag_topic)"/>
|
||||||
<remap from="odom" to="$(arg odom_topic)"/>
|
<remap from="odom" to="$(arg odom_topic)"/>
|
||||||
|
|
||||||
<!-- localization mode -->
|
<!-- localization mode -->
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<package>
|
<package>
|
||||||
<name>rtabmap_ros</name>
|
<name>rtabmap_ros</name>
|
||||||
<version>0.18.2</version>
|
<version>0.18.3</version>
|
||||||
<description>RTAB-Map's ros-pkg. RTAB-Map is a RGB-D SLAM approach with real-time constraints.</description>
|
<description>RTAB-Map's ros-pkg. RTAB-Map is a RGB-D SLAM approach with real-time constraints.</description>
|
||||||
<maintainer email="[email protected]">Mathieu Labbe</maintainer>
|
<maintainer email="[email protected]">Mathieu Labbe</maintainer>
|
||||||
<author>Mathieu Labbe</author>
|
<author>Mathieu Labbe</author>
|
||||||
|
|||||||
+29
-10
@@ -7,54 +7,73 @@ from rtabmap_ros.msg import Goal
|
|||||||
pub = rospy.Publisher('/rtabmap/goal_node', Goal, queue_size=1)
|
pub = rospy.Publisher('/rtabmap/goal_node', Goal, queue_size=1)
|
||||||
waypoints = []
|
waypoints = []
|
||||||
currentIndex = 0
|
currentIndex = 0
|
||||||
|
waitingTime = 1.0
|
||||||
|
|
||||||
def callback(data):
|
def callback(data):
|
||||||
global currentIndex
|
global currentIndex
|
||||||
|
global waitingTime
|
||||||
if data.data:
|
if data.data:
|
||||||
rospy.loginfo(rospy.get_caller_id() + "Goal '%s' reached! Publishing next goal in 1 sec...", waypoints[currentIndex])
|
rospy.loginfo(rospy.get_caller_id() + ": Goal '%s' reached! Publishing next goal in %.1f sec...", waypoints[currentIndex], waitingTime)
|
||||||
else:
|
else:
|
||||||
rospy.loginfo(rospy.get_caller_id() + "Goal '%s' failed! Publishing next goal in 1 sec...", waypoints[currentIndex])
|
rospy.loginfo(rospy.get_caller_id() + ": Goal '%s' failed! Publishing next goal in %.1f sec...", waypoints[currentIndex], waitingTime)
|
||||||
|
|
||||||
currentIndex = (currentIndex+1) % len(waypoints)
|
currentIndex = (currentIndex+1) % len(waypoints)
|
||||||
|
|
||||||
rospy.sleep(1.)
|
# Waiting time before sending next goal
|
||||||
|
rospy.sleep(waitingTime)
|
||||||
|
|
||||||
msg = Goal()
|
msg = Goal()
|
||||||
if waypoints[currentIndex].isdigit():
|
try:
|
||||||
|
int(waypoints[currentIndex])
|
||||||
|
is_dig = True
|
||||||
|
except ValueError:
|
||||||
|
is_dig = False
|
||||||
|
if is_dig:
|
||||||
msg.node_id = int(waypoints[currentIndex])
|
msg.node_id = int(waypoints[currentIndex])
|
||||||
msg.node_label = ""
|
msg.node_label = ""
|
||||||
else:
|
else:
|
||||||
msg.node_id = 0
|
msg.node_id = 0
|
||||||
msg.node_label = waypoints[currentIndex]
|
msg.node_label = waypoints[currentIndex]
|
||||||
|
|
||||||
|
rospy.loginfo(rospy.get_caller_id() + ": Publishing goal '%s'! (%d/%d)", waypoints[currentIndex], currentIndex+1, len(waypoints))
|
||||||
msg.header.stamp = rospy.get_rostime()
|
msg.header.stamp = rospy.get_rostime()
|
||||||
rospy.loginfo("Publishing goal '%s'! (%d/%d)", waypoints[currentIndex], currentIndex+1, len(waypoints))
|
|
||||||
pub.publish(msg)
|
pub.publish(msg)
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
rospy.init_node('patrol', anonymous=False)
|
rospy.init_node('patrol', anonymous=False)
|
||||||
rospy.Subscriber("/rtabmap/goal_reached", Bool, callback)
|
rospy.Subscriber("/rtabmap/goal_reached", Bool, callback)
|
||||||
|
global waitingTime
|
||||||
|
waitingTime = rospy.get_param('~time', waitingTime)
|
||||||
rospy.sleep(1.) # make sure that subscribers have seen this node before sending a goal
|
rospy.sleep(1.) # make sure that subscribers have seen this node before sending a goal
|
||||||
|
|
||||||
|
rospy.loginfo(rospy.get_caller_id() + ": Waypoints: [%s]", str(waypoints).strip('[]'))
|
||||||
|
rospy.loginfo(rospy.get_caller_id() + ": time: %f", waitingTime)
|
||||||
|
|
||||||
# send the first goal
|
# send the first goal
|
||||||
msg = Goal()
|
msg = Goal()
|
||||||
if waypoints[currentIndex].isdigit():
|
try:
|
||||||
|
int(waypoints[currentIndex])
|
||||||
|
is_dig = True
|
||||||
|
except ValueError:
|
||||||
|
is_dig = False
|
||||||
|
if is_dig:
|
||||||
msg.node_id = int(waypoints[currentIndex])
|
msg.node_id = int(waypoints[currentIndex])
|
||||||
msg.node_label = ""
|
msg.node_label = ""
|
||||||
else:
|
else:
|
||||||
msg.node_id = 0
|
msg.node_id = 0
|
||||||
msg.node_label = waypoints[currentIndex]
|
msg.node_label = waypoints[currentIndex]
|
||||||
while rospy.Time.now().secs == 0:
|
while rospy.Time.now().secs == 0:
|
||||||
rospy.loginfo("Waiting clock...")
|
rospy.loginfo(rospy.get_caller_id() + ": Waiting clock...")
|
||||||
rospy.sleep(.1)
|
rospy.sleep(.1)
|
||||||
msg.header.stamp = rospy.Time.now()
|
msg.header.stamp = rospy.Time.now()
|
||||||
rospy.loginfo("Publishing goal '%s'! (%d/%d)", waypoints[currentIndex], currentIndex+1, len(waypoints))
|
rospy.loginfo(rospy.get_caller_id() + ": Publishing goal '%s'! (%d/%d)", waypoints[currentIndex], currentIndex+1, len(waypoints))
|
||||||
pub.publish(msg)
|
pub.publish(msg)
|
||||||
rospy.spin()
|
rospy.spin()
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
if len(sys.argv) < 3:
|
if len(sys.argv) < 3:
|
||||||
print("usage: patrol.py waypointA waypointB waypointC ... (at least 2 waypoints, can be node id or label)")
|
print("usage: patrol.py waypointA waypointB waypointC ... [_time:=1] [topic remaps] (at least 2 waypoints, can be node id, landmark or label)")
|
||||||
else:
|
else:
|
||||||
waypoints = sys.argv[1:]
|
waypoints = sys.argv[1:]
|
||||||
rospy.loginfo("Waypoints: [%s]", str(waypoints).strip('[]'))
|
waypoints = [x for x in waypoints if not x.startswith('/') and not x.startswith('_')]
|
||||||
main()
|
main()
|
||||||
|
|||||||
+95
-13
@@ -93,8 +93,10 @@ CoreWrapper::CoreWrapper() :
|
|||||||
groundTruthFrameId_(""), // e.g., "world"
|
groundTruthFrameId_(""), // e.g., "world"
|
||||||
groundTruthBaseFrameId_(""), // e.g., "base_link_gt"
|
groundTruthBaseFrameId_(""), // e.g., "base_link_gt"
|
||||||
configPath_(""),
|
configPath_(""),
|
||||||
odomDefaultAngVariance_(1.0),
|
odomDefaultAngVariance_(0.001),
|
||||||
odomDefaultLinVariance_(1.0),
|
odomDefaultLinVariance_(0.001),
|
||||||
|
landmarkDefaultAngVariance_(0.001),
|
||||||
|
landmarkDefaultLinVariance_(0.001),
|
||||||
waitForTransform_(true),
|
waitForTransform_(true),
|
||||||
waitForTransformDuration_(0.2), // 200 ms
|
waitForTransformDuration_(0.2), // 200 ms
|
||||||
useActionForGoal_(false),
|
useActionForGoal_(false),
|
||||||
@@ -157,6 +159,8 @@ void CoreWrapper::onInit()
|
|||||||
pnh.param("tf_tolerance", tfTolerance, tfTolerance);
|
pnh.param("tf_tolerance", tfTolerance, tfTolerance);
|
||||||
pnh.param("odom_tf_angular_variance", odomDefaultAngVariance_, odomDefaultAngVariance_);
|
pnh.param("odom_tf_angular_variance", odomDefaultAngVariance_, odomDefaultAngVariance_);
|
||||||
pnh.param("odom_tf_linear_variance", odomDefaultLinVariance_, odomDefaultLinVariance_);
|
pnh.param("odom_tf_linear_variance", odomDefaultLinVariance_, odomDefaultLinVariance_);
|
||||||
|
pnh.param("landmark_angular_variance", landmarkDefaultAngVariance_, landmarkDefaultAngVariance_);
|
||||||
|
pnh.param("landmark_linear_variance", landmarkDefaultLinVariance_, landmarkDefaultLinVariance_);
|
||||||
pnh.param("wait_for_transform", waitForTransform_, waitForTransform_);
|
pnh.param("wait_for_transform", waitForTransform_, waitForTransform_);
|
||||||
pnh.param("wait_for_transform_duration", waitForTransformDuration_, waitForTransformDuration_);
|
pnh.param("wait_for_transform_duration", waitForTransformDuration_, waitForTransformDuration_);
|
||||||
pnh.param("use_action_for_goal", useActionForGoal_, useActionForGoal_);
|
pnh.param("use_action_for_goal", useActionForGoal_, useActionForGoal_);
|
||||||
@@ -687,6 +691,9 @@ void CoreWrapper::onInit()
|
|||||||
userDataAsyncSub_ = nh.subscribe("user_data_async", 1, &CoreWrapper::userDataAsyncCallback, this);
|
userDataAsyncSub_ = nh.subscribe("user_data_async", 1, &CoreWrapper::userDataAsyncCallback, this);
|
||||||
globalPoseAsyncSub_ = nh.subscribe("global_pose", 1, &CoreWrapper::globalPoseAsyncCallback, this);
|
globalPoseAsyncSub_ = nh.subscribe("global_pose", 1, &CoreWrapper::globalPoseAsyncCallback, this);
|
||||||
gpsFixAsyncSub_ = nh.subscribe("gps/fix", 1, &CoreWrapper::gpsFixAsyncCallback, this);
|
gpsFixAsyncSub_ = nh.subscribe("gps/fix", 1, &CoreWrapper::gpsFixAsyncCallback, this);
|
||||||
|
#ifdef WITH_APRILTAGS2_ROS
|
||||||
|
tagDetectionsSub_ = nh.subscribe("tag_detections", 1, &CoreWrapper::tagDetectionsAsyncCallback, this);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
CoreWrapper::~CoreWrapper()
|
CoreWrapper::~CoreWrapper()
|
||||||
@@ -1292,6 +1299,22 @@ void CoreWrapper::commonDepthCallbackImpl(
|
|||||||
}
|
}
|
||||||
gps_ = rtabmap::GPS();
|
gps_ = rtabmap::GPS();
|
||||||
|
|
||||||
|
//tag detections
|
||||||
|
Landmarks landmarks = rtabmap_ros::landmarksFromROS(
|
||||||
|
tags_,
|
||||||
|
frameId_,
|
||||||
|
odomFrameId,
|
||||||
|
lastPoseStamp_,
|
||||||
|
tfListener_,
|
||||||
|
waitForTransform_?waitForTransformDuration_:0,
|
||||||
|
landmarkDefaultLinVariance_,
|
||||||
|
landmarkDefaultAngVariance_);
|
||||||
|
tags_.clear();
|
||||||
|
if(!landmarks.empty())
|
||||||
|
{
|
||||||
|
data.setLandmarks(landmarks);
|
||||||
|
}
|
||||||
|
|
||||||
OdometryInfo odomInfo;
|
OdometryInfo odomInfo;
|
||||||
if(odomInfoMsg.get())
|
if(odomInfoMsg.get())
|
||||||
{
|
{
|
||||||
@@ -1565,6 +1588,22 @@ void CoreWrapper::commonStereoCallback(
|
|||||||
}
|
}
|
||||||
gps_ = rtabmap::GPS();
|
gps_ = rtabmap::GPS();
|
||||||
|
|
||||||
|
//tag detections
|
||||||
|
Landmarks landmarks = rtabmap_ros::landmarksFromROS(
|
||||||
|
tags_,
|
||||||
|
frameId_,
|
||||||
|
odomFrameId,
|
||||||
|
lastPoseStamp_,
|
||||||
|
tfListener_,
|
||||||
|
waitForTransform_?waitForTransformDuration_:0,
|
||||||
|
landmarkDefaultLinVariance_,
|
||||||
|
landmarkDefaultAngVariance_);
|
||||||
|
tags_.clear();
|
||||||
|
if(!landmarks.empty())
|
||||||
|
{
|
||||||
|
data.setLandmarks(landmarks);
|
||||||
|
}
|
||||||
|
|
||||||
OdometryInfo odomInfo;
|
OdometryInfo odomInfo;
|
||||||
if(odomInfoMsg.get())
|
if(odomInfoMsg.get())
|
||||||
{
|
{
|
||||||
@@ -1785,6 +1824,22 @@ void CoreWrapper::commonLaserScanCallback(
|
|||||||
odomInfo = odomInfoFromROS(*odomInfoMsg);
|
odomInfo = odomInfoFromROS(*odomInfoMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//tag detections
|
||||||
|
Landmarks landmarks = rtabmap_ros::landmarksFromROS(
|
||||||
|
tags_,
|
||||||
|
frameId_,
|
||||||
|
odomFrameId,
|
||||||
|
lastPoseStamp_,
|
||||||
|
tfListener_,
|
||||||
|
waitForTransform_?waitForTransformDuration_:0,
|
||||||
|
landmarkDefaultLinVariance_,
|
||||||
|
landmarkDefaultAngVariance_);
|
||||||
|
tags_.clear();
|
||||||
|
if(!landmarks.empty())
|
||||||
|
{
|
||||||
|
data.setLandmarks(landmarks);
|
||||||
|
}
|
||||||
|
|
||||||
process(lastPoseStamp_,
|
process(lastPoseStamp_,
|
||||||
data,
|
data,
|
||||||
lastPose_,
|
lastPose_,
|
||||||
@@ -1897,7 +1952,7 @@ void CoreWrapper::process(
|
|||||||
memcpy(poseMsg.pose.covariance.data(), cov.data, cov.total()*sizeof(double));
|
memcpy(poseMsg.pose.covariance.data(), cov.data, cov.total()*sizeof(double));
|
||||||
localizationPosePub_.publish(poseMsg);
|
localizationPosePub_.publish(poseMsg);
|
||||||
}
|
}
|
||||||
std::map<int, rtabmap::Transform> filteredPoses = rtabmap_.getLocalOptimizedPoses();
|
std::map<int, rtabmap::Transform> filteredPoses(rtabmap_.getLocalOptimizedPoses().lower_bound(1), rtabmap_.getLocalOptimizedPoses().end());
|
||||||
|
|
||||||
// create a tmp signature with latest sensory data if latest signature was ignored
|
// create a tmp signature with latest sensory data if latest signature was ignored
|
||||||
std::map<int, rtabmap::Signature> tmpSignature;
|
std::map<int, rtabmap::Signature> tmpSignature;
|
||||||
@@ -1909,9 +1964,9 @@ void CoreWrapper::process(
|
|||||||
(!mapsManager_.getOccupancyGrid()->isGridFromDepth() && data.laserScanRaw().is2d())) // 2d laser scan would fill empty space for latest data
|
(!mapsManager_.getOccupancyGrid()->isGridFromDepth() && data.laserScanRaw().is2d())) // 2d laser scan would fill empty space for latest data
|
||||||
{
|
{
|
||||||
SensorData tmpData = data;
|
SensorData tmpData = data;
|
||||||
tmpData.setId(-1);
|
tmpData.setId(0);
|
||||||
tmpSignature.insert(std::make_pair(-1, Signature(-1, -1, 0, data.stamp(), "", odom, Transform(), tmpData)));
|
tmpSignature.insert(std::make_pair(0, Signature(0, -1, 0, data.stamp(), "", odom, Transform(), tmpData)));
|
||||||
filteredPoses.insert(std::make_pair(-1, mapToOdom_*odom));
|
filteredPoses.insert(std::make_pair(0, mapToOdom_*odom));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(maxMappingNodes_ > 0 && filteredPoses.size()>1)
|
if(maxMappingNodes_ > 0 && filteredPoses.size()>1)
|
||||||
@@ -1926,7 +1981,7 @@ void CoreWrapper::process(
|
|||||||
nearestPoses.insert(*pter);
|
nearestPoses.insert(*pter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//add negative and make sure those on a planned path are not filtered
|
//add latest/zero and make sure those on a planned path are not filtered
|
||||||
std::set<int> onPath;
|
std::set<int> onPath;
|
||||||
if(rtabmap_.getPath().size())
|
if(rtabmap_.getPath().size())
|
||||||
{
|
{
|
||||||
@@ -1935,7 +1990,7 @@ void CoreWrapper::process(
|
|||||||
}
|
}
|
||||||
for(std::map<int, Transform>::iterator iter=filteredPoses.begin(); iter!=filteredPoses.end(); ++iter)
|
for(std::map<int, Transform>::iterator iter=filteredPoses.begin(); iter!=filteredPoses.end(); ++iter)
|
||||||
{
|
{
|
||||||
if(iter->first < 0 || onPath.find(iter->first) != onPath.end())
|
if(iter->first == 0 || onPath.find(iter->first) != onPath.end())
|
||||||
{
|
{
|
||||||
nearestPoses.insert(*iter);
|
nearestPoses.insert(*iter);
|
||||||
}
|
}
|
||||||
@@ -2113,6 +2168,22 @@ void CoreWrapper::gpsFixAsyncCallback(const sensor_msgs::NavSatFixConstPtr & gps
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef WITH_APRILTAGS2_ROS
|
||||||
|
void CoreWrapper::tagDetectionsAsyncCallback(const apriltags2_ros::AprilTagDetectionArray & tagDetections)
|
||||||
|
{
|
||||||
|
if(!paused_)
|
||||||
|
{
|
||||||
|
for(unsigned int i=0; i<tagDetections.detections.size(); ++i)
|
||||||
|
{
|
||||||
|
if(tagDetections.detections[i].id.size() == 1)
|
||||||
|
{
|
||||||
|
uInsert(tags_, std::make_pair(tagDetections.detections[i].id[0], tagDetections.detections[i].pose));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
void CoreWrapper::initialPoseCallback(const geometry_msgs::PoseWithCovarianceStampedConstPtr & msg)
|
void CoreWrapper::initialPoseCallback(const geometry_msgs::PoseWithCovarianceStampedConstPtr & msg)
|
||||||
{
|
{
|
||||||
@@ -2142,7 +2213,11 @@ void CoreWrapper::goalCommonCallback(
|
|||||||
|
|
||||||
if(id > 0)
|
if(id > 0)
|
||||||
{
|
{
|
||||||
NODELET_INFO("Planning: set goal %d", id);
|
NODELET_INFO("Planning: set goal to node %d", id);
|
||||||
|
}
|
||||||
|
else if(id < 0)
|
||||||
|
{
|
||||||
|
NODELET_INFO("Planning: set goal to landmark %d", id);
|
||||||
}
|
}
|
||||||
else if(!pose.isNull())
|
else if(!pose.isNull())
|
||||||
{
|
{
|
||||||
@@ -2155,7 +2230,7 @@ void CoreWrapper::goalCommonCallback(
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool success = false;
|
bool success = false;
|
||||||
if((id > 0 && rtabmap_.computePath(id, true)) ||
|
if((id != 0 && rtabmap_.computePath(id, true)) ||
|
||||||
(!pose.isNull() && rtabmap_.computePath(pose)))
|
(!pose.isNull() && rtabmap_.computePath(pose)))
|
||||||
{
|
{
|
||||||
if(planningTime)
|
if(planningTime)
|
||||||
@@ -2231,6 +2306,10 @@ void CoreWrapper::goalCommonCallback(
|
|||||||
{
|
{
|
||||||
NODELET_ERROR("Planning: Could not plan to node %d! The node is not in map's graph (look for warnings before this message for more details).", id);
|
NODELET_ERROR("Planning: Could not plan to node %d! The node is not in map's graph (look for warnings before this message for more details).", id);
|
||||||
}
|
}
|
||||||
|
else if(id < 0)
|
||||||
|
{
|
||||||
|
NODELET_ERROR("Planning: Could not plan to landmark %d! The landmark is not in map's graph (look for warnings before this message for more details).", id);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
NODELET_ERROR("Planning: Node id should be > 0 !");
|
NODELET_ERROR("Planning: Node id should be > 0 !");
|
||||||
@@ -2280,7 +2359,7 @@ void CoreWrapper::goalCallback(const geometry_msgs::PoseStampedConstPtr & msg)
|
|||||||
|
|
||||||
void CoreWrapper::goalNodeCallback(const rtabmap_ros::GoalConstPtr & msg)
|
void CoreWrapper::goalNodeCallback(const rtabmap_ros::GoalConstPtr & msg)
|
||||||
{
|
{
|
||||||
if(msg->node_id <= 0 && msg->node_label.empty())
|
if(msg->node_id == 0 && msg->node_label.empty())
|
||||||
{
|
{
|
||||||
NODELET_ERROR("Node id or label should be set!");
|
NODELET_ERROR("Node id or label should be set!");
|
||||||
return;
|
return;
|
||||||
@@ -2343,6 +2422,7 @@ bool CoreWrapper::resetRtabmapCallback(std_srvs::Empty::Request&, std_srvs::Empt
|
|||||||
previousStamp_ = ros::Time(0);
|
previousStamp_ = ros::Time(0);
|
||||||
globalPose_.header.stamp = ros::Time(0);
|
globalPose_.header.stamp = ros::Time(0);
|
||||||
gps_ = rtabmap::GPS();
|
gps_ = rtabmap::GPS();
|
||||||
|
tags_.clear();
|
||||||
userDataMutex_.lock();
|
userDataMutex_.lock();
|
||||||
userData_ = cv::Mat();
|
userData_ = cv::Mat();
|
||||||
userDataMutex_.unlock();
|
userDataMutex_.unlock();
|
||||||
@@ -2404,6 +2484,7 @@ bool CoreWrapper::backupDatabaseCallback(std_srvs::Empty::Request&, std_srvs::Em
|
|||||||
userDataMutex_.unlock();
|
userDataMutex_.unlock();
|
||||||
globalPose_.header.stamp = ros::Time(0);
|
globalPose_.header.stamp = ros::Time(0);
|
||||||
gps_ = rtabmap::GPS();
|
gps_ = rtabmap::GPS();
|
||||||
|
tags_.clear();
|
||||||
|
|
||||||
NODELET_INFO("Backup: Saving \"%s\" to \"%s\"...", databasePath_.c_str(), (databasePath_+".back").c_str());
|
NODELET_INFO("Backup: Saving \"%s\" to \"%s\"...", databasePath_.c_str(), (databasePath_+".back").c_str());
|
||||||
UFile::copy(databasePath_, databasePath_+".back");
|
UFile::copy(databasePath_, databasePath_+".back");
|
||||||
@@ -2658,8 +2739,8 @@ bool CoreWrapper::publishMapCallback(rtabmap_ros::PublishMap::Request& req, rtab
|
|||||||
|
|
||||||
if(!req.graphOnly && mapsManager_.hasSubscribers())
|
if(!req.graphOnly && mapsManager_.hasSubscribers())
|
||||||
{
|
{
|
||||||
std::map<int, Transform> filteredPoses = poses;
|
std::map<int, Transform> filteredPoses(poses.lower_bound(1), poses.end());
|
||||||
if(maxMappingNodes_ > 0 && poses.size()>1)
|
if(maxMappingNodes_ > 0 && filteredPoses.size()>1)
|
||||||
{
|
{
|
||||||
std::map<int, Transform> nearestPoses;
|
std::map<int, Transform> nearestPoses;
|
||||||
std::vector<int> nodes = graph::findNearestNodes(filteredPoses, filteredPoses.rbegin()->second, maxMappingNodes_);
|
std::vector<int> nodes = graph::findNearestNodes(filteredPoses, filteredPoses.rbegin()->second, maxMappingNodes_);
|
||||||
@@ -3046,6 +3127,7 @@ void CoreWrapper::publishStats(const ros::Time & stamp)
|
|||||||
|
|
||||||
markers.markers.push_back(marker);
|
markers.markers.push_back(marker);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add node ids
|
// Add node ids
|
||||||
visualization_msgs::Marker marker;
|
visualization_msgs::Marker marker;
|
||||||
marker.header.frame_id = mapFrameId_;
|
marker.header.frame_id = mapFrameId_;
|
||||||
|
|||||||
@@ -197,9 +197,9 @@ public:
|
|||||||
{
|
{
|
||||||
Signature tmpS = nodes_.at(poses.rbegin()->first);
|
Signature tmpS = nodes_.at(poses.rbegin()->first);
|
||||||
SensorData tmpData = tmpS.sensorData();
|
SensorData tmpData = tmpS.sensorData();
|
||||||
tmpData.setId(-1);
|
tmpData.setId(0);
|
||||||
uInsert(nodes_, std::make_pair(-1, Signature(-1, -1, 0, tmpS.getStamp(), "", tmpS.getPose(), Transform(), tmpData)));
|
uInsert(nodes_, std::make_pair(0, Signature(0, -1, 0, tmpS.getStamp(), "", tmpS.getPose(), Transform(), tmpData)));
|
||||||
poses.insert(std::make_pair(-1, poses.rbegin()->second));
|
poses.insert(std::make_pair(0, poses.rbegin()->second));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update maps
|
// Update maps
|
||||||
|
|||||||
+134
-126
@@ -63,8 +63,8 @@ MapsManager::MapsManager() :
|
|||||||
mapFilterRadius_(0.0),
|
mapFilterRadius_(0.0),
|
||||||
mapFilterAngle_(30.0), // degrees
|
mapFilterAngle_(30.0), // degrees
|
||||||
mapCacheCleanup_(true),
|
mapCacheCleanup_(true),
|
||||||
negativePosesIgnored_(true),
|
alwaysUpdateMap_(false),
|
||||||
negativeScanEmptyRayTracing_(true),
|
scanEmptyRayTracing_(true),
|
||||||
assembledObstacles_(new pcl::PointCloud<pcl::PointXYZRGB>),
|
assembledObstacles_(new pcl::PointCloud<pcl::PointXYZRGB>),
|
||||||
assembledGround_(new pcl::PointCloud<pcl::PointXYZRGB>),
|
assembledGround_(new pcl::PointCloud<pcl::PointXYZRGB>),
|
||||||
occupancyGrid_(new OccupancyGrid),
|
occupancyGrid_(new OccupancyGrid),
|
||||||
@@ -79,8 +79,30 @@ void MapsManager::init(ros::NodeHandle & nh, ros::NodeHandle & pnh, const std::s
|
|||||||
pnh.param("map_filter_radius", mapFilterRadius_, mapFilterRadius_);
|
pnh.param("map_filter_radius", mapFilterRadius_, mapFilterRadius_);
|
||||||
pnh.param("map_filter_angle", mapFilterAngle_, mapFilterAngle_);
|
pnh.param("map_filter_angle", mapFilterAngle_, mapFilterAngle_);
|
||||||
pnh.param("map_cleanup", mapCacheCleanup_, mapCacheCleanup_);
|
pnh.param("map_cleanup", mapCacheCleanup_, mapCacheCleanup_);
|
||||||
pnh.param("map_negative_poses_ignored", negativePosesIgnored_, negativePosesIgnored_);
|
|
||||||
pnh.param("map_negative_scan_empty_ray_tracing", negativeScanEmptyRayTracing_, negativeScanEmptyRayTracing_);
|
if(pnh.hasParam("map_negative_poses_ignored"))
|
||||||
|
{
|
||||||
|
ROS_WARN("Parameter \"map_negative_poses_ignored\" has been "
|
||||||
|
"removed. Use \"map_always_update\" instead.");
|
||||||
|
if(!pnh.hasParam("map_always_update"))
|
||||||
|
{
|
||||||
|
bool negPosesIgnored;
|
||||||
|
pnh.getParam("map_negative_poses_ignored", negPosesIgnored);
|
||||||
|
alwaysUpdateMap_ = !negPosesIgnored;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pnh.param("map_always_update", alwaysUpdateMap_, alwaysUpdateMap_);
|
||||||
|
|
||||||
|
if(pnh.hasParam("map_negative_scan_empty_ray_tracing"))
|
||||||
|
{
|
||||||
|
ROS_WARN("Parameter \"map_negative_scan_empty_ray_tracing\" has been "
|
||||||
|
"removed. Use \"map_empty_ray_tracing\" instead.");
|
||||||
|
if(!pnh.hasParam("map_empty_ray_tracing"))
|
||||||
|
{
|
||||||
|
pnh.getParam("map_negative_scan_empty_ray_tracing", scanEmptyRayTracing_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pnh.param("map_empty_ray_tracing", scanEmptyRayTracing_, scanEmptyRayTracing_);
|
||||||
|
|
||||||
if(pnh.hasParam("scan_output_voxelized"))
|
if(pnh.hasParam("scan_output_voxelized"))
|
||||||
{
|
{
|
||||||
@@ -98,8 +120,8 @@ void MapsManager::init(ros::NodeHandle & nh, ros::NodeHandle & pnh, const std::s
|
|||||||
ROS_INFO("%s(maps): map_filter_radius = %f", name.c_str(), mapFilterRadius_);
|
ROS_INFO("%s(maps): map_filter_radius = %f", name.c_str(), mapFilterRadius_);
|
||||||
ROS_INFO("%s(maps): map_filter_angle = %f", name.c_str(), mapFilterAngle_);
|
ROS_INFO("%s(maps): map_filter_angle = %f", name.c_str(), mapFilterAngle_);
|
||||||
ROS_INFO("%s(maps): map_cleanup = %s", name.c_str(), mapCacheCleanup_?"true":"false");
|
ROS_INFO("%s(maps): map_cleanup = %s", name.c_str(), mapCacheCleanup_?"true":"false");
|
||||||
ROS_INFO("%s(maps): map_negative_poses_ignored = %s", name.c_str(), negativePosesIgnored_?"true":"false");
|
ROS_INFO("%s(maps): map_always_update = %s", name.c_str(), alwaysUpdateMap_?"true":"false");
|
||||||
ROS_INFO("%s(maps): map_negative_scan_ray_tracing = %s", name.c_str(), negativeScanEmptyRayTracing_?"true":"false");
|
ROS_INFO("%s(maps): map_empty_ray_tracing = %s", name.c_str(), scanEmptyRayTracing_?"true":"false");
|
||||||
ROS_INFO("%s(maps): cloud_output_voxelized = %s", name.c_str(), cloudOutputVoxelized_?"true":"false");
|
ROS_INFO("%s(maps): cloud_output_voxelized = %s", name.c_str(), cloudOutputVoxelized_?"true":"false");
|
||||||
ROS_INFO("%s(maps): cloud_subtract_filtering = %s", name.c_str(), cloudSubtractFiltering_?"true":"false");
|
ROS_INFO("%s(maps): cloud_subtract_filtering = %s", name.c_str(), cloudSubtractFiltering_?"true":"false");
|
||||||
ROS_INFO("%s(maps): cloud_subtract_filtering_min_neighbors = %d", name.c_str(), cloudSubtractFilteringMinNeighbors_);
|
ROS_INFO("%s(maps): cloud_subtract_filtering_min_neighbors = %d", name.c_str(), cloudSubtractFilteringMinNeighbors_);
|
||||||
@@ -302,7 +324,7 @@ void MapsManager::set2DMap(
|
|||||||
//update cache in case the map should be updated
|
//update cache in case the map should be updated
|
||||||
if(memory)
|
if(memory)
|
||||||
{
|
{
|
||||||
for(std::map<int, rtabmap::Transform>::const_iterator iter=poses.begin(); iter!=poses.end(); ++iter)
|
for(std::map<int, rtabmap::Transform>::const_iterator iter=poses.lower_bound(1); iter!=poses.end(); ++iter)
|
||||||
{
|
{
|
||||||
std::map<int, std::pair< std::pair<cv::Mat, cv::Mat>, cv::Mat> >::iterator jter = gridMaps_.find(iter->first);
|
std::map<int, std::pair< std::pair<cv::Mat, cv::Mat>, cv::Mat> >::iterator jter = gridMaps_.find(iter->first);
|
||||||
if(!uContains(gridMaps_, iter->first))
|
if(!uContains(gridMaps_, iter->first))
|
||||||
@@ -388,7 +410,7 @@ std::map<int, Transform> MapsManager::getFilteredPoses(const std::map<int, Trans
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::map<int, rtabmap::Transform> MapsManager::updateMapCaches(
|
std::map<int, rtabmap::Transform> MapsManager::updateMapCaches(
|
||||||
const std::map<int, rtabmap::Transform> & poses,
|
const std::map<int, rtabmap::Transform> & posesIn,
|
||||||
const rtabmap::Memory * memory,
|
const rtabmap::Memory * memory,
|
||||||
bool updateGrid,
|
bool updateGrid,
|
||||||
bool updateOctomap,
|
bool updateOctomap,
|
||||||
@@ -434,6 +456,16 @@ std::map<int, rtabmap::Transform> MapsManager::updateMapCaches(
|
|||||||
return std::map<int, rtabmap::Transform>();
|
return std::map<int, rtabmap::Transform>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// process only nodes (exclude landmarks)
|
||||||
|
std::map<int, rtabmap::Transform> poses;
|
||||||
|
if(posesIn.begin()->first < 0)
|
||||||
|
{
|
||||||
|
poses.insert(posesIn.lower_bound(0), posesIn.end());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
poses = posesIn;
|
||||||
|
}
|
||||||
std::map<int, rtabmap::Transform> filteredPoses;
|
std::map<int, rtabmap::Transform> filteredPoses;
|
||||||
|
|
||||||
// update cache
|
// update cache
|
||||||
@@ -445,17 +477,10 @@ std::map<int, rtabmap::Transform> MapsManager::updateMapCaches(
|
|||||||
UDEBUG("Filter nodes...");
|
UDEBUG("Filter nodes...");
|
||||||
double angle = mapFilterAngle_ == 0.0?CV_PI+0.1:mapFilterAngle_*CV_PI/180.0;
|
double angle = mapFilterAngle_ == 0.0?CV_PI+0.1:mapFilterAngle_*CV_PI/180.0;
|
||||||
filteredPoses = rtabmap::graph::radiusPosesFiltering(poses, mapFilterRadius_, angle);
|
filteredPoses = rtabmap::graph::radiusPosesFiltering(poses, mapFilterRadius_, angle);
|
||||||
for(std::map<int, rtabmap::Transform>::const_iterator iter=poses.begin(); iter!=poses.end(); ++iter)
|
if(poses.find(0) != poses.end())
|
||||||
{
|
{
|
||||||
if(iter->first <=0)
|
// make sure to keep latest data
|
||||||
{
|
filteredPoses.insert(*poses.find(0));
|
||||||
// make sure to keep latest data
|
|
||||||
filteredPoses.insert(*iter);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -463,19 +488,9 @@ std::map<int, rtabmap::Transform> MapsManager::updateMapCaches(
|
|||||||
filteredPoses = poses;
|
filteredPoses = poses;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(negativePosesIgnored_)
|
if(alwaysUpdateMap_)
|
||||||
{
|
{
|
||||||
for(std::map<int, rtabmap::Transform>::iterator iter=filteredPoses.begin(); iter!=filteredPoses.end();)
|
filteredPoses.erase(0);
|
||||||
{
|
|
||||||
if(iter->first <= 0)
|
|
||||||
{
|
|
||||||
filteredPoses.erase(iter++);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
++iter;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool longUpdate = false;
|
bool longUpdate = false;
|
||||||
@@ -505,7 +520,7 @@ std::map<int, rtabmap::Transform> MapsManager::updateMapCaches(
|
|||||||
if(!iter->second.isNull())
|
if(!iter->second.isNull())
|
||||||
{
|
{
|
||||||
rtabmap::SensorData data;
|
rtabmap::SensorData data;
|
||||||
if(updateGridCache && (iter->first < 0 || !uContains(gridMaps_, iter->first)))
|
if(updateGridCache && (iter->first == 0 || !uContains(gridMaps_, iter->first)))
|
||||||
{
|
{
|
||||||
UDEBUG("Data required for %d", iter->first);
|
UDEBUG("Data required for %d", iter->first);
|
||||||
std::map<int, rtabmap::Signature>::const_iterator findIter = signatures.find(iter->first);
|
std::map<int, rtabmap::Signature>::const_iterator findIter = signatures.find(iter->first);
|
||||||
@@ -518,78 +533,35 @@ std::map<int, rtabmap::Transform> MapsManager::updateMapCaches(
|
|||||||
data = memory->getSignatureDataConst(iter->first, occupancyGrid_->isGridFromDepth() && !occupancySavedInDB, !occupancyGrid_->isGridFromDepth() && !occupancySavedInDB, false, true);
|
data = memory->getSignatureDataConst(iter->first, occupancyGrid_->isGridFromDepth() && !occupancySavedInDB, !occupancyGrid_->isGridFromDepth() && !occupancySavedInDB, false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(data.id() != 0)
|
UDEBUG("Adding grid map %d to cache...", iter->first);
|
||||||
|
cv::Point3f viewPoint;
|
||||||
|
cv::Mat ground, obstacles, emptyCells;
|
||||||
|
if(iter->first > 0)
|
||||||
{
|
{
|
||||||
UDEBUG("Adding grid map %d to cache...", iter->first);
|
cv::Mat rgb, depth;
|
||||||
cv::Point3f viewPoint;
|
LaserScan scan;
|
||||||
cv::Mat ground, obstacles, emptyCells;
|
bool generateGrid = data.gridCellSize() == 0.0f;
|
||||||
if(iter->first > 0)
|
static bool warningShown = false;
|
||||||
|
if(occupancySavedInDB && generateGrid && !warningShown)
|
||||||
{
|
{
|
||||||
cv::Mat rgb, depth;
|
warningShown = true;
|
||||||
LaserScan scan;
|
UWARN("Occupancy grid for location %d should be added to global map (e..g, a ROS node is subscribed to "
|
||||||
bool generateGrid = data.gridCellSize() == 0.0f;
|
"any occupancy grid output) but it cannot be found "
|
||||||
static bool warningShown = false;
|
"in memory. For convenience, the occupancy "
|
||||||
if(occupancySavedInDB && generateGrid && !warningShown)
|
"grid is regenerated. Make sure parameter \"%s\" is true to "
|
||||||
{
|
"avoid this warning for the next locations added to map. For older "
|
||||||
warningShown = true;
|
"locations already in database without an occupancy grid map, you can use the "
|
||||||
UWARN("Occupancy grid for location %d should be added to global map (e..g, a ROS node is subscribed to "
|
"\"rtabmap-databaseViewer\" to regenerate the missing occupancy grid maps and "
|
||||||
"any occupancy grid output) but it cannot be found "
|
"save them back in the database for next sessions. This warning is only shown once.",
|
||||||
"in memory. For convenience, the occupancy "
|
data.id(), Parameters::kRGBDCreateOccupancyGrid().c_str());
|
||||||
"grid is regenerated. Make sure parameter \"%s\" is true to "
|
|
||||||
"avoid this warning for the next locations added to map. For older "
|
|
||||||
"locations already in database without an occupancy grid map, you can use the "
|
|
||||||
"\"rtabmap-databaseViewer\" to regenerate the missing occupancy grid maps and "
|
|
||||||
"save them back in the database for next sessions. This warning is only shown once.",
|
|
||||||
data.id(), Parameters::kRGBDCreateOccupancyGrid().c_str());
|
|
||||||
}
|
|
||||||
if(memory && occupancySavedInDB && generateGrid)
|
|
||||||
{
|
|
||||||
// if we are here, it is because we loaded a database with old nodes not having occupancy grid set
|
|
||||||
// try reload again
|
|
||||||
data = memory->getSignatureDataConst(iter->first, occupancyGrid_->isGridFromDepth(), !occupancyGrid_->isGridFromDepth(), false, false);
|
|
||||||
}
|
|
||||||
data.uncompressData(
|
|
||||||
occupancyGrid_->isGridFromDepth() && generateGrid?&rgb:0,
|
|
||||||
occupancyGrid_->isGridFromDepth() && generateGrid?&depth:0,
|
|
||||||
!occupancyGrid_->isGridFromDepth() && generateGrid?&scan:0,
|
|
||||||
0,
|
|
||||||
generateGrid?0:&ground,
|
|
||||||
generateGrid?0:&obstacles,
|
|
||||||
generateGrid?0:&emptyCells);
|
|
||||||
|
|
||||||
if(generateGrid)
|
|
||||||
{
|
|
||||||
Signature tmp(data);
|
|
||||||
tmp.setPose(iter->second);
|
|
||||||
occupancyGrid_->createLocalMap(tmp, ground, obstacles, emptyCells, viewPoint);
|
|
||||||
uInsert(gridMaps_, std::make_pair(iter->first, std::make_pair(std::make_pair(ground, obstacles), emptyCells)));
|
|
||||||
uInsert(gridMapsViewpoints_, std::make_pair(iter->first, viewPoint));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
viewPoint = data.gridViewPoint();
|
|
||||||
uInsert(gridMaps_, std::make_pair(iter->first, std::make_pair(std::make_pair(ground, obstacles), emptyCells)));
|
|
||||||
uInsert(gridMapsViewpoints_, std::make_pair(iter->first, viewPoint));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
if(memory && occupancySavedInDB && generateGrid)
|
||||||
{
|
{
|
||||||
// generate tmp occupancy grid for negative ids (assuming data is already uncompressed)
|
// if we are here, it is because we loaded a database with old nodes not having occupancy grid set
|
||||||
// For negative laser scans, fill empty space?
|
// try reload again
|
||||||
bool unknownSpaceFilled = Parameters::defaultGridScan2dUnknownSpaceFilled();
|
data = memory->getSignatureDataConst(iter->first, occupancyGrid_->isGridFromDepth(), !occupancyGrid_->isGridFromDepth(), false, false);
|
||||||
Parameters::parse(parameters_, Parameters::kGridScan2dUnknownSpaceFilled(), unknownSpaceFilled);
|
}
|
||||||
|
data.uncompressData(
|
||||||
if(unknownSpaceFilled != negativeScanEmptyRayTracing_ && negativeScanEmptyRayTracing_)
|
|
||||||
{
|
|
||||||
ParametersMap parameters;
|
|
||||||
parameters.insert(ParametersPair(Parameters::kGridScan2dUnknownSpaceFilled(), uBool2Str(negativeScanEmptyRayTracing_)));
|
|
||||||
occupancyGrid_->parseParameters(parameters);
|
|
||||||
}
|
|
||||||
|
|
||||||
cv::Mat rgb, depth;
|
|
||||||
LaserScan scan;
|
|
||||||
bool generateGrid = data.gridCellSize() == 0.0f || (unknownSpaceFilled != negativeScanEmptyRayTracing_ && negativeScanEmptyRayTracing_);
|
|
||||||
data.uncompressData(
|
|
||||||
occupancyGrid_->isGridFromDepth() && generateGrid?&rgb:0,
|
occupancyGrid_->isGridFromDepth() && generateGrid?&rgb:0,
|
||||||
occupancyGrid_->isGridFromDepth() && generateGrid?&depth:0,
|
occupancyGrid_->isGridFromDepth() && generateGrid?&depth:0,
|
||||||
!occupancyGrid_->isGridFromDepth() && generateGrid?&scan:0,
|
!occupancyGrid_->isGridFromDepth() && generateGrid?&scan:0,
|
||||||
@@ -598,38 +570,74 @@ std::map<int, rtabmap::Transform> MapsManager::updateMapCaches(
|
|||||||
generateGrid?0:&obstacles,
|
generateGrid?0:&obstacles,
|
||||||
generateGrid?0:&emptyCells);
|
generateGrid?0:&emptyCells);
|
||||||
|
|
||||||
if(generateGrid)
|
if(generateGrid)
|
||||||
{
|
{
|
||||||
Signature tmp(data);
|
Signature tmp(data);
|
||||||
tmp.setPose(iter->second);
|
tmp.setPose(iter->second);
|
||||||
occupancyGrid_->createLocalMap(tmp, ground, obstacles, emptyCells, viewPoint);
|
occupancyGrid_->createLocalMap(tmp, ground, obstacles, emptyCells, viewPoint);
|
||||||
uInsert(gridMaps_, std::make_pair(iter->first, std::make_pair(std::make_pair(ground, obstacles), emptyCells)));
|
uInsert(gridMaps_, std::make_pair(iter->first, std::make_pair(std::make_pair(ground, obstacles), emptyCells)));
|
||||||
uInsert(gridMapsViewpoints_, std::make_pair(iter->first, viewPoint));
|
uInsert(gridMapsViewpoints_, std::make_pair(iter->first, viewPoint));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
viewPoint = data.gridViewPoint();
|
viewPoint = data.gridViewPoint();
|
||||||
uInsert(gridMaps_, std::make_pair(iter->first, std::make_pair(std::make_pair(ground, obstacles), emptyCells)));
|
uInsert(gridMaps_, std::make_pair(iter->first, std::make_pair(std::make_pair(ground, obstacles), emptyCells)));
|
||||||
uInsert(gridMapsViewpoints_, std::make_pair(iter->first, viewPoint));
|
uInsert(gridMapsViewpoints_, std::make_pair(iter->first, viewPoint));
|
||||||
}
|
|
||||||
|
|
||||||
// put back
|
|
||||||
if(unknownSpaceFilled != negativeScanEmptyRayTracing_ && negativeScanEmptyRayTracing_)
|
|
||||||
{
|
|
||||||
ParametersMap parameters;
|
|
||||||
parameters.insert(ParametersPair(Parameters::kGridScan2dUnknownSpaceFilled(), uBool2Str(unknownSpaceFilled)));
|
|
||||||
occupancyGrid_->parseParameters(parameters);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(memory)
|
else
|
||||||
{
|
{
|
||||||
ROS_ERROR("Data missing for node %d to update the maps", iter->first);
|
// generate tmp occupancy grid for latest id (assuming data is already uncompressed)
|
||||||
|
// For negative laser scans, fill empty space?
|
||||||
|
bool unknownSpaceFilled = Parameters::defaultGridScan2dUnknownSpaceFilled();
|
||||||
|
Parameters::parse(parameters_, Parameters::kGridScan2dUnknownSpaceFilled(), unknownSpaceFilled);
|
||||||
|
|
||||||
|
if(unknownSpaceFilled != scanEmptyRayTracing_ && scanEmptyRayTracing_)
|
||||||
|
{
|
||||||
|
ParametersMap parameters;
|
||||||
|
parameters.insert(ParametersPair(Parameters::kGridScan2dUnknownSpaceFilled(), uBool2Str(scanEmptyRayTracing_)));
|
||||||
|
occupancyGrid_->parseParameters(parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
cv::Mat rgb, depth;
|
||||||
|
LaserScan scan;
|
||||||
|
bool generateGrid = data.gridCellSize() == 0.0f || (unknownSpaceFilled != scanEmptyRayTracing_ && scanEmptyRayTracing_);
|
||||||
|
data.uncompressData(
|
||||||
|
occupancyGrid_->isGridFromDepth() && generateGrid?&rgb:0,
|
||||||
|
occupancyGrid_->isGridFromDepth() && generateGrid?&depth:0,
|
||||||
|
!occupancyGrid_->isGridFromDepth() && generateGrid?&scan:0,
|
||||||
|
0,
|
||||||
|
generateGrid?0:&ground,
|
||||||
|
generateGrid?0:&obstacles,
|
||||||
|
generateGrid?0:&emptyCells);
|
||||||
|
|
||||||
|
if(generateGrid)
|
||||||
|
{
|
||||||
|
Signature tmp(data);
|
||||||
|
tmp.setPose(iter->second);
|
||||||
|
occupancyGrid_->createLocalMap(tmp, ground, obstacles, emptyCells, viewPoint);
|
||||||
|
uInsert(gridMaps_, std::make_pair(iter->first, std::make_pair(std::make_pair(ground, obstacles), emptyCells)));
|
||||||
|
uInsert(gridMapsViewpoints_, std::make_pair(iter->first, viewPoint));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
viewPoint = data.gridViewPoint();
|
||||||
|
uInsert(gridMaps_, std::make_pair(iter->first, std::make_pair(std::make_pair(ground, obstacles), emptyCells)));
|
||||||
|
uInsert(gridMapsViewpoints_, std::make_pair(iter->first, viewPoint));
|
||||||
|
}
|
||||||
|
|
||||||
|
// put back
|
||||||
|
if(unknownSpaceFilled != scanEmptyRayTracing_ && scanEmptyRayTracing_)
|
||||||
|
{
|
||||||
|
ParametersMap parameters;
|
||||||
|
parameters.insert(ParametersPair(Parameters::kGridScan2dUnknownSpaceFilled(), uBool2Str(unknownSpaceFilled)));
|
||||||
|
occupancyGrid_->parseParameters(parameters);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(updateGrid &&
|
if(updateGrid &&
|
||||||
(iter->first < 0 ||
|
(iter->first == 0 ||
|
||||||
occupancyGrid_->addedNodes().find(iter->first) == occupancyGrid_->addedNodes().end()))
|
occupancyGrid_->addedNodes().find(iter->first) == occupancyGrid_->addedNodes().end()))
|
||||||
{
|
{
|
||||||
std::map<int, std::pair<std::pair<cv::Mat, cv::Mat>, cv::Mat> >::iterator mter = gridMaps_.find(iter->first);
|
std::map<int, std::pair<std::pair<cv::Mat, cv::Mat>, cv::Mat> >::iterator mter = gridMaps_.find(iter->first);
|
||||||
@@ -645,7 +653,7 @@ std::map<int, rtabmap::Transform> MapsManager::updateMapCaches(
|
|||||||
#ifdef WITH_OCTOMAP_MSGS
|
#ifdef WITH_OCTOMAP_MSGS
|
||||||
#ifdef RTABMAP_OCTOMAP
|
#ifdef RTABMAP_OCTOMAP
|
||||||
if(updateOctomap &&
|
if(updateOctomap &&
|
||||||
(iter->first < 0 ||
|
(iter->first == 0 ||
|
||||||
octomap_->addedNodes().find(iter->first) == octomap_->addedNodes().end()))
|
octomap_->addedNodes().find(iter->first) == octomap_->addedNodes().end()))
|
||||||
{
|
{
|
||||||
std::map<int, std::pair<std::pair<cv::Mat, cv::Mat>, cv::Mat> >::iterator mter = gridMaps_.find(iter->first);
|
std::map<int, std::pair<std::pair<cv::Mat, cv::Mat>, cv::Mat> >::iterator mter = gridMaps_.find(iter->first);
|
||||||
@@ -811,7 +819,7 @@ void MapsManager::publishMaps(
|
|||||||
cloudObstaclesPub_.getNumSubscribers();
|
cloudObstaclesPub_.getNumSubscribers();
|
||||||
bool graphGroundChanged = updateGround;
|
bool graphGroundChanged = updateGround;
|
||||||
bool graphObstacleChanged = updateObstacles;
|
bool graphObstacleChanged = updateObstacles;
|
||||||
for(std::map<int, Transform>::const_iterator iter=poses.begin(); iter!=poses.end(); ++iter)
|
for(std::map<int, Transform>::const_iterator iter=poses.lower_bound(0); iter!=poses.end(); ++iter)
|
||||||
{
|
{
|
||||||
std::map<int, Transform>::const_iterator jter;
|
std::map<int, Transform>::const_iterator jter;
|
||||||
if(updateGround)
|
if(updateGround)
|
||||||
|
|||||||
@@ -1233,6 +1233,69 @@ void userDataToROS(const cv::Mat & data, rtabmap_ros::UserData & dataMsg, bool c
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rtabmap::Landmarks landmarksFromROS(
|
||||||
|
const std::map<int, geometry_msgs::PoseWithCovarianceStamped> & tags,
|
||||||
|
const std::string & frameId,
|
||||||
|
const std::string & odomFrameId,
|
||||||
|
const ros::Time & odomStamp,
|
||||||
|
tf::TransformListener & listener,
|
||||||
|
double waitForTransform,
|
||||||
|
double defaultLinVariance,
|
||||||
|
double defaultAngVariance)
|
||||||
|
{
|
||||||
|
//tag detections
|
||||||
|
rtabmap::Landmarks landmarks;
|
||||||
|
for(std::map<int, geometry_msgs::PoseWithCovarianceStamped>::const_iterator iter=tags.begin(); iter!=tags.end(); ++iter)
|
||||||
|
{
|
||||||
|
rtabmap::Transform baseToCamera = rtabmap_ros::getTransform(
|
||||||
|
frameId,
|
||||||
|
iter->second.header.frame_id,
|
||||||
|
iter->second.header.stamp,
|
||||||
|
listener,
|
||||||
|
waitForTransform);
|
||||||
|
|
||||||
|
if(baseToCamera.isNull())
|
||||||
|
{
|
||||||
|
ROS_ERROR("Cannot transform tag pose from \"%s\" frame to \"%s\" frame!",
|
||||||
|
iter->second.header.frame_id.c_str(), frameId.c_str());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
rtabmap::Transform baseToTag = baseToCamera * transformFromPoseMsg(iter->second.pose.pose);
|
||||||
|
|
||||||
|
if(!baseToTag.isNull())
|
||||||
|
{
|
||||||
|
// Correction of the global pose accounting the odometry movement since we received it
|
||||||
|
rtabmap::Transform correction = rtabmap_ros::getTransform(
|
||||||
|
frameId,
|
||||||
|
odomFrameId,
|
||||||
|
iter->second.header.stamp,
|
||||||
|
odomStamp,
|
||||||
|
listener,
|
||||||
|
waitForTransform);
|
||||||
|
if(!correction.isNull())
|
||||||
|
{
|
||||||
|
baseToTag = correction * baseToTag;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ROS_WARN("Could not adjust tag pose accordingly to latest odometry pose. "
|
||||||
|
"If odometry is small since it received the tag pose and "
|
||||||
|
"covariance is large, this should not be a problem.");
|
||||||
|
}
|
||||||
|
cv::Mat covariance = cv::Mat(6,6, CV_64FC1, (void*)iter->second.pose.covariance.data()).clone();
|
||||||
|
if(covariance.empty() || !uIsFinite(covariance.at<double>(0,0)) || covariance.at<double>(0,0)<=0.0f)
|
||||||
|
{
|
||||||
|
covariance = cv::Mat::eye(6,6,CV_64FC1);
|
||||||
|
covariance(cv::Range(0,3), cv::Range(0,3)) *= defaultLinVariance;
|
||||||
|
covariance(cv::Range(3,6), cv::Range(3,6)) *= defaultAngVariance;
|
||||||
|
}
|
||||||
|
landmarks.insert(std::make_pair(iter->first, rtabmap::Landmark(iter->first, baseToTag, covariance)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return landmarks;
|
||||||
|
}
|
||||||
|
|
||||||
rtabmap::Transform getTransform(
|
rtabmap::Transform getTransform(
|
||||||
const std::string & fromFrameId,
|
const std::string & fromFrameId,
|
||||||
const std::string & toFrameId,
|
const std::string & toFrameId,
|
||||||
|
|||||||
+8
-10
@@ -36,7 +36,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include <cv_bridge/cv_bridge.h>
|
#include <cv_bridge/cv_bridge.h>
|
||||||
|
|
||||||
#include <rtabmap/core/Rtabmap.h>
|
|
||||||
#include <rtabmap/core/odometry/OdometryF2M.h>
|
#include <rtabmap/core/odometry/OdometryF2M.h>
|
||||||
#include <rtabmap/core/odometry/OdometryF2F.h>
|
#include <rtabmap/core/odometry/OdometryF2F.h>
|
||||||
#include <rtabmap/core/util3d.h>
|
#include <rtabmap/core/util3d.h>
|
||||||
@@ -78,7 +77,6 @@ OdometryROS::OdometryROS(bool stereoParams, bool visParams, bool icpParams) :
|
|||||||
stereoParams_(stereoParams),
|
stereoParams_(stereoParams),
|
||||||
visParams_(visParams),
|
visParams_(visParams),
|
||||||
icpParams_(icpParams),
|
icpParams_(icpParams),
|
||||||
guessStamp_(0.0),
|
|
||||||
previousStamp_(0.0),
|
previousStamp_(0.0),
|
||||||
expectedUpdateRate_(0.0)
|
expectedUpdateRate_(0.0)
|
||||||
{
|
{
|
||||||
@@ -448,8 +446,8 @@ void OdometryROS::processData(const SensorData & data, const ros::Time & stamp)
|
|||||||
Transform guessCurrentPose;
|
Transform guessCurrentPose;
|
||||||
if(!guessFrameId_.empty())
|
if(!guessFrameId_.empty())
|
||||||
{
|
{
|
||||||
Transform previousPose = this->getTransform(guessFrameId_, frameId_, guessStamp_>0.0?ros::Time(guessStamp_):stamp);
|
|
||||||
guessCurrentPose = this->getTransform(guessFrameId_, frameId_, stamp);
|
guessCurrentPose = this->getTransform(guessFrameId_, frameId_, stamp);
|
||||||
|
Transform previousPose = guessPreviousPose_.isNull()?guessCurrentPose:guessPreviousPose_;
|
||||||
if(!previousPose.isNull() && !guessCurrentPose.isNull())
|
if(!previousPose.isNull() && !guessCurrentPose.isNull())
|
||||||
{
|
{
|
||||||
if(guess_.isNull())
|
if(guess_.isNull())
|
||||||
@@ -460,7 +458,7 @@ void OdometryROS::processData(const SensorData & data, const ros::Time & stamp)
|
|||||||
{
|
{
|
||||||
guess_ = guess_ * previousPose.inverse() * guessCurrentPose;
|
guess_ = guess_ * previousPose.inverse() * guessCurrentPose;
|
||||||
}
|
}
|
||||||
if(guessStamp_>0.0 && (guessMinTranslation_ > 0.0 || guessMinRotation_ > 0.0))
|
if(!guessPreviousPose_.isNull() && (guessMinTranslation_ > 0.0 || guessMinRotation_ > 0.0))
|
||||||
{
|
{
|
||||||
float x,y,z,roll,pitch,yaw;
|
float x,y,z,roll,pitch,yaw;
|
||||||
guess_.getTranslationAndEulerAngles(x,y,z,roll,pitch,yaw);
|
guess_.getTranslationAndEulerAngles(x,y,z,roll,pitch,yaw);
|
||||||
@@ -478,11 +476,11 @@ void OdometryROS::processData(const SensorData & data, const ros::Time & stamp)
|
|||||||
rtabmap_ros::transformToGeometryMsg(correction, correctionMsg.transform);
|
rtabmap_ros::transformToGeometryMsg(correction, correctionMsg.transform);
|
||||||
tfBroadcaster_.sendTransform(correctionMsg);
|
tfBroadcaster_.sendTransform(correctionMsg);
|
||||||
}
|
}
|
||||||
guessStamp_ = stamp.toSec();
|
guessPreviousPose_ = guessCurrentPose;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
guessStamp_ = stamp.toSec();
|
guessPreviousPose_ = guessCurrentPose;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -557,11 +555,11 @@ void OdometryROS::processData(const SensorData & data, const ros::Time & stamp)
|
|||||||
odom.pose.covariance.at(35) = info.reg.covariance.at<double>(5,5)*2; // yawyaw
|
odom.pose.covariance.at(35) = info.reg.covariance.at<double>(5,5)*2; // yawyaw
|
||||||
|
|
||||||
//set velocity
|
//set velocity
|
||||||
bool setTwist = !odometry_->previousVelocityTransform().isNull();
|
bool setTwist = !odometry_->getVelocityGuess().isNull();
|
||||||
if(setTwist)
|
if(setTwist)
|
||||||
{
|
{
|
||||||
float x,y,z,roll,pitch,yaw;
|
float x,y,z,roll,pitch,yaw;
|
||||||
odometry_->previousVelocityTransform().getTranslationAndEulerAngles(x,y,z,roll,pitch,yaw);
|
odometry_->getVelocityGuess().getTranslationAndEulerAngles(x,y,z,roll,pitch,yaw);
|
||||||
odom.twist.twist.linear.x = x;
|
odom.twist.twist.linear.x = x;
|
||||||
odom.twist.twist.linear.y = y;
|
odom.twist.twist.linear.y = y;
|
||||||
odom.twist.twist.linear.z = z;
|
odom.twist.twist.linear.z = z;
|
||||||
@@ -757,7 +755,7 @@ bool OdometryROS::reset(std_srvs::Empty::Request&, std_srvs::Empty::Response&)
|
|||||||
NODELET_INFO( "visual_odometry: reset odom!");
|
NODELET_INFO( "visual_odometry: reset odom!");
|
||||||
odometry_->reset();
|
odometry_->reset();
|
||||||
guess_.setNull();
|
guess_.setNull();
|
||||||
guessStamp_ = 0.0;
|
guessPreviousPose_.setNull();
|
||||||
previousStamp_ = 0.0;
|
previousStamp_ = 0.0;
|
||||||
resetCurrentCount_ = resetCountdown_;
|
resetCurrentCount_ = resetCountdown_;
|
||||||
this->flushCallbacks();
|
this->flushCallbacks();
|
||||||
@@ -770,7 +768,7 @@ bool OdometryROS::resetToPose(rtabmap_ros::ResetPose::Request& req, rtabmap_ros:
|
|||||||
NODELET_INFO( "visual_odometry: reset odom to pose %s!", pose.prettyPrint().c_str());
|
NODELET_INFO( "visual_odometry: reset odom to pose %s!", pose.prettyPrint().c_str());
|
||||||
odometry_->reset(pose);
|
odometry_->reset(pose);
|
||||||
guess_.setNull();
|
guess_.setNull();
|
||||||
guessStamp_ = 0.0;
|
guessPreviousPose_.setNull();
|
||||||
previousStamp_ = 0.0;
|
previousStamp_ = 0.0;
|
||||||
resetCurrentCount_ = resetCountdown_;
|
resetCurrentCount_ = resetCountdown_;
|
||||||
this->flushCallbacks();
|
this->flushCallbacks();
|
||||||
|
|||||||
@@ -140,7 +140,7 @@ public:
|
|||||||
|
|
||||||
if(nodeToObjects_.size())
|
if(nodeToObjects_.size())
|
||||||
{
|
{
|
||||||
for(std::map<int, rtabmap::Transform>::iterator iter=poses.begin(); iter!=poses.end(); ++iter)
|
for(std::map<int, rtabmap::Transform>::iterator iter=poses.lower_bound(1); iter!=poses.end(); ++iter)
|
||||||
{
|
{
|
||||||
if(nodeToObjects_.find(iter->first) != nodeToObjects_.end())
|
if(nodeToObjects_.find(iter->first) != nodeToObjects_.end())
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user