Skip to content

Commit fba41b2

Browse files
authored
Merge pull request #7 from KumarRobotics/feature/robustness
Feature/robustness
2 parents 91337d2 + 7f5d2ac commit fba41b2

File tree

14 files changed

+347
-36
lines changed

14 files changed

+347
-36
lines changed

glider/config/example-params.yaml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
accelerometer_covariance: 0.0001
2+
gyroscope_covariance: 0.0001
3+
integration_covariance: 0.001
4+
bias_covariance: 0.001
5+
use_second_order: 0.0
6+
gravity: 9.81
7+
bias_num_measurements: 100 # number for imu measurements to use for imu bias calc
8+
gps_noise: 2.0
9+
odom_noise: 0.1 ## dep??
10+
heading_noise: 0.1 # dep??
11+
odom_orientation_noise: 0.1
12+
odom_translation_noise: 1.0
13+
odom_scale_noise: 1.0
14+
lag_time: 10.0 # amount of time for fixed lag smoother to look at
15+
imu_frame: "enu" # frame the imu outputs
16+
scale_odom: false # if you adding odom, does it need to be scaled?
17+
correct_imu: true # use mag to correct imu orienation
18+
gps_to_imu: # gps to imu extrinsics
19+
X: 0.0
20+
y: 0.0
21+
z: 0.0
Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
glider_node:
22
ros__parameters:
33
rate: 100.0
4-
use_odom: true
4+
use_odom: false
5+
viz: true
56
publish_nav_sat_fix: false
67
utm_zone: "18S"
78
declination: 11.82
9+
origin_easting: 482933.2819920078
10+
origin_northing: 4421345.135559781
Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
1-
accelerometer_covariance: 0.1
2-
gyroscope_covariance: 0.1
1+
accelerometer_covariance: 0.00001
2+
gyroscope_covariance: 0.00001
33
integration_covariance: 0.001
44
bias_covariance: 0.001
55
use_second_order: 0.0
6-
origin_x: 482990.7375634047
7-
origin_y: 4421250.443879729
86
gravity: 9.81
97
bias_num_measurements: 100
10-
gps_noise: 2.0
8+
gps_noise: 1.5
119
odom_noise: 0.5
1210
heading_noise: 0.1
1311
odom_orientation_noise: 0.1
@@ -16,4 +14,8 @@ odom_scale_noise: 50.0
1614
lag_time: 10.0
1715
imu_frame: "enu"
1816
scale_odom: true
19-
correct_imu: false
17+
correct_imu: true
18+
gps_to_imu:
19+
X: 0.0
20+
y: 0.0
21+
z: 0.0

glider/include/glider/core/glider.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ class Glider
4242
bool set_initial_heading_;
4343
bool correct_imu_;
4444
std::string frame_;
45+
Eigen::Vector3d t_imu_gps_;
4546

4647
Eigen::Matrix3d ned_to_enu_rot_;
4748
Eigen::Quaterniond ned_to_enu_quat_;

glider/include/glider/utils/parameters.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
* glider-mono parameters loaded from a yaml file.
66
*/
77

8+
#include <Eigen/Dense>
89
#include <yaml-cpp/yaml.h>
910
#include <string>
1011

@@ -22,8 +23,6 @@ struct Parameters
2223
double integration_cov;
2324
double bias_cov;
2425
double use_second_order;
25-
double origin_x;
26-
double origin_y;
2726
double gravity;
2827
double gps_noise;
2928
double heading_noise;
@@ -39,5 +38,6 @@ struct Parameters
3938

4039
bool scale_odom;
4140
bool correct_imu;
41+
Eigen::Vector3d t_imu_gps;
4242
};
4343
}

glider/include/ros/glider_node.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ class GliderNode : public rclcpp::Node
5858

5959
// publishers
6060
rclcpp::Publisher<nav_msgs::msg::Odometry>::SharedPtr odom_pub_;
61+
rclcpp::Publisher<nav_msgs::msg::Odometry>::SharedPtr odom_viz_pub_;
6162
rclcpp::Publisher<sensor_msgs::msg::NavSatFix>::SharedPtr gps_pub_;
6263

6364
// timers
@@ -67,8 +68,11 @@ class GliderNode : public rclcpp::Node
6768
bool initialized_;
6869
bool use_sim_time_;
6970
bool publish_nsf_;
71+
bool viz_;
7072
std::string utm_zone_;
7173
double declination_;
74+
double origin_easting_;
75+
double origin_northing_;
7276

7377
// tracker
7478
Glider::State current_state_;

glider/launch/glider-node.launch.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,13 @@ def generate_launch_description():
3131
ros_params_file = PathJoinSubstitution([
3232
glider_share,
3333
'config',
34-
'ros_params.yaml'
34+
'ros-params.yaml'
3535
])
3636

3737
graph_params_file = PathJoinSubstitution([
3838
glider_share,
3939
'config',
40-
'graph_params.yaml'
40+
'vectornav-vn100t.yaml'
4141
])
4242

4343
# Create the glider node
@@ -54,8 +54,8 @@ def generate_launch_description():
5454
],
5555
remappings=[
5656
('/gps', '/ublox_gps_node/fix'),
57-
('/imu', '/zed/zed_node/imu/data'),
58-
('/mag', '/zed/zed_node/imu/mag'),
57+
('/imu', '/vectornav/imu'),
58+
('/mag', '/vectornav/magnetic'),
5959
('/odom', '/Odometry'),
6060
]
6161
)

glider/ros/conversions.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ Output Conversions::odomToRos(Glider::Odometry& odom, const char* zone)
224224
msg.twist.twist.linear.x = v(0);
225225
msg.twist.twist.linear.y = v(1);
226226
msg.twist.twist.linear.z = v(2);
227-
msg.header = getHeader(odom.getTimestamp(), "enu-utm");
227+
msg.header = getHeader(odom.getTimestamp(), "enu");
228228

229229
return msg;
230230
}
@@ -303,7 +303,7 @@ Output Conversions::stateToRos(Glider::State& state, const char* zone)
303303
msg.twist.covariance[i * cov.rows() + j] = cov(i, j);
304304
}
305305
}
306-
msg.header = getHeader(state.getTimestamp(), "enu-utm");
306+
msg.header = getHeader(state.getTimestamp(), "enu");
307307

308308
}
309309
else

glider/ros/glider_node.cpp

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ GliderNode::GliderNode(const rclcpp::NodeOptions& options) : rclcpp::Node("glide
1616
declare_parameter("publish_nav_sat_fix", false);
1717
declare_parameter("utm_zone", "18S");
1818
declare_parameter("declination", 12.0);
19+
declare_parameter("origin_easting", 0.0);
20+
declare_parameter("origin_northing", 0.0);
21+
declare_parameter("viz", false);
1922

2023
// Get parameters
2124
double freq = this->get_parameter("rate").as_double();
@@ -29,10 +32,18 @@ GliderNode::GliderNode(const rclcpp::NodeOptions& options) : rclcpp::Node("glide
2932

3033
bool use_odom = this->get_parameter("use_odom").as_bool();
3134
RCLCPP_INFO_STREAM(this->get_logger(), "Fusing Odometry: " << std::boolalpha << use_odom);
35+
3236
publish_nsf_ = this->get_parameter("publish_nav_sat_fix").as_bool();
3337
utm_zone_ = this->get_parameter("utm_zone").as_string();
34-
declination_ = this->get_parameter("declination").as_double() * M_PI / 180.0d;
38+
RCLCPP_INFO_STREAM(this->get_logger(), "Using UTM Zone: " << utm_zone_);
39+
40+
declination_ = this->get_parameter("declination").as_double() * M_PI / 180.0;
3541
RCLCPP_INFO_STREAM(this->get_logger(), "Using Magnetic Declination: " << declination_);
42+
43+
viz_ = this->get_parameter("viz").as_bool();
44+
45+
origin_easting_ = this->get_parameter("origin_easting").as_double();
46+
origin_northing_ = this->get_parameter("origin_northing").as_double();
3647

3748
glider_ = std::make_unique<Glider::Glider>(path);
3849

@@ -80,6 +91,12 @@ GliderNode::GliderNode(const rclcpp::NodeOptions& options) : rclcpp::Node("glide
8091
odom_pub_ = this->create_publisher<nav_msgs::msg::Odometry>("/glider/odom", 10);
8192
}
8293

94+
if(viz_)
95+
{
96+
RCLCPP_INFO(this->get_logger(), "Publishing Odometry Viz message on /glider/odom/viz");
97+
odom_viz_pub_ = this->create_publisher<nav_msgs::msg::Odometry>("/glider/odom/viz", 10);
98+
}
99+
83100
std::chrono::milliseconds d = GliderROS::Conversions::hzToDuration(freq);
84101
timer_ = this->create_wall_timer(d, std::bind(&GliderNode::interpolationCallback, this));
85102
RCLCPP_INFO(this->get_logger(), "GliderNode Initialized");
@@ -110,6 +127,17 @@ void GliderNode::interpolationCallback()
110127
nav_msgs::msg::Odometry msg = GliderROS::Conversions::odomToRos<nav_msgs::msg::Odometry>(odom);
111128
GliderROS::Conversions::addCovariance<nav_msgs::msg::Odometry>(current_state_, msg);
112129
odom_pub_->publish(msg);
130+
131+
if (viz_)
132+
{
133+
nav_msgs::msg::Odometry viz_msg = msg;
134+
double x = viz_msg.pose.pose.position.x - origin_easting_;
135+
double y = viz_msg.pose.pose.position.y - origin_northing_;
136+
viz_msg.pose.pose.position.x = x;
137+
viz_msg.pose.pose.position.y = y;
138+
139+
odom_viz_pub_->publish(viz_msg);
140+
}
113141
}
114142
}
115143

glider/scripts/heading.py

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
#!/usr/bin/env python3
2+
3+
import rclpy
4+
from rclpy.node import Node
5+
from sensor_msgs.msg import Imu
6+
import math
7+
8+
9+
class RpyPrinter(Node):
10+
def __init__(self):
11+
super().__init__('rpy_printer')
12+
13+
# Create subscriber to IMU topic
14+
self.imu_subscriber = self.create_subscription(
15+
Imu,
16+
'/VN100T/imu', # Subscribe directly to IMU topic
17+
self.imu_callback,
18+
10
19+
)
20+
21+
# Create timer for 2Hz printing (0.5 seconds interval)
22+
self.timer = self.create_timer(0.5, self.print_rpy)
23+
24+
# Store latest orientation data
25+
self.latest_orientation = None
26+
self.latest_timestamp = None
27+
28+
self.get_logger().info('Roll Pitch Yaw Printer node started')
29+
self.get_logger().info('Subscribing to: /imu/data')
30+
self.get_logger().info('Printing RPY at 2Hz')
31+
32+
def imu_callback(self, msg):
33+
"""
34+
Callback function for IMU messages.
35+
Stores the latest orientation data.
36+
"""
37+
self.latest_orientation = msg.orientation
38+
self.latest_timestamp = msg.header.stamp
39+
40+
def quaternion_to_euler(self, quat):
41+
"""
42+
Convert quaternion to roll, pitch, yaw (in radians).
43+
44+
Args:
45+
quat: geometry_msgs.msg.Quaternion
46+
47+
Returns:
48+
tuple: (roll, pitch, yaw) in radians
49+
"""
50+
x, y, z, w = quat.x, quat.y, quat.z, quat.w
51+
52+
# Roll (x-axis rotation)
53+
sinr_cosp = 2 * (w * x + y * z)
54+
cosr_cosp = 1 - 2 * (x * x + y * y)
55+
roll = math.atan2(sinr_cosp, cosr_cosp)
56+
57+
# Pitch (y-axis rotation)
58+
sinp = 2 * (w * y - z * x)
59+
if abs(sinp) >= 1:
60+
pitch = math.copysign(math.pi / 2, sinp) # Use 90 degrees if out of range
61+
else:
62+
pitch = math.asin(sinp)
63+
64+
# Yaw (z-axis rotation)
65+
siny_cosp = 2 * (w * z + x * y)
66+
cosy_cosp = 1 - 2 * (y * y + z * z)
67+
yaw = math.atan2(siny_cosp, cosy_cosp)
68+
69+
return roll, pitch, yaw
70+
71+
def print_rpy(self):
72+
"""
73+
Timer callback function that prints roll, pitch, yaw at 2Hz.
74+
"""
75+
if self.latest_orientation is None:
76+
self.get_logger().warn('No IMU data received yet')
77+
return
78+
79+
# Convert quaternion to Euler angles
80+
roll, pitch, yaw = self.quaternion_to_euler(self.latest_orientation)
81+
82+
# Convert to degrees for easier reading
83+
roll_deg = math.degrees(roll)
84+
pitch_deg = math.degrees(pitch)
85+
yaw_deg = math.degrees(yaw)
86+
87+
# Print with formatting
88+
self.get_logger().info(
89+
f'Roll: {roll_deg:8.2f}° Pitch: {pitch_deg:8.2f}° Yaw: {yaw_deg:8.2f}°'
90+
)
91+
92+
93+
def main(args=None):
94+
rclpy.init(args=args)
95+
96+
node = RpyPrinter()
97+
98+
try:
99+
rclpy.spin(node)
100+
except KeyboardInterrupt:
101+
node.get_logger().info('Shutting down Roll Pitch Yaw Printer node')
102+
finally:
103+
node.destroy_node()
104+
rclpy.shutdown()
105+
106+
107+
if __name__ == '__main__':
108+
main()

0 commit comments

Comments
 (0)