Skip to content
This repository was archived by the owner on Jun 17, 2025. It is now read-only.
15 changes: 13 additions & 2 deletions F1TenthAlgorithms/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,13 @@
# Do imports to add necessary function to library
# TODO
from .desired_acceleration import find_desired_acceleration
from .desired_heading import find_desired_heading
from .proportional_steering_angle import find_proportional_control_steering_angle
from .desired_velocity import find_desired_velocity
from .desired_steering_angle import find_desired_steering_angle

__all__ = [
"find_desired_acceleration",
"find_desired_heading",
"find_proportional_control_steering_angle",
"find_desired_velocity",
"find_desired_steering_angle"
]
28 changes: 0 additions & 28 deletions F1TenthAlgorithms/v_des.py

This file was deleted.

119 changes: 119 additions & 0 deletions navigation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
# Built in Imports
import numpy as np

# Custom library imports
from F1TenthAlgorithms import find_desired_acceleration, find_desired_heading, \
find_desired_velocity, find_proportional_control_steering_angle

# ROS imports
import rclpy
from rclpy.node import Node
from nav_msgs.msg import Odometry
from tf_transformations import euler_from_quaternion

# Global Variables
# None


class Navigation(Node):
"""
#TODO: Navigation functionality should probably be part of \
# one entire SDM node [F1T-16]

Navigation node for Simple Drive Mode

Topics subscribed to:
/ego_racecar/odom:
Odometry

Topics published to: TODO: Integrate with other code [F1T-16]
<topicName>:
<messageType>
"""

def __init__(self):
super().__init__('navigation')

# Create subscriber
self.odometrySubscriber = self.create_subscription(
Odometry, "/ego_racecar/odom",
self.ego_odometry_callback, 10
)
# TODO: Integrate with other tickets (Take in target position) [F1T-16]
self.targetPosition_fix_m = [10, 10] # Placeholder
self.currentPosition_fix_m = None

def ego_odometry_callback(self, msg: Odometry):
"""
Processes Odometry data:
Calculates the desired heading, steering angle, and velocity based\
on the race car's current position to reach the target position.

Parameters:
msg:
Odometry message coming from /ego_racecar/odom topic

Returns:
None:
"""
Copy link
Contributor

Choose a reason for hiding this comment

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

Please follow the same commenting convention for class methods. Should describe what the input is and what it returns etc.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done: 649c1e6

# Update current position using the values in msg.
self.currentPosition_fix_m = np.array([
msg.pose.pose.position.x, msg.pose.pose.position.y
])

# Update current velocities using the values in msg.
self.currentLinearVelocity_fix_mps = msg.twist.twist.linear.x
self.currentAngularVelocity_fix_radps = msg.twist.twist.angular.z

# Update current orientation using the values in msg.
# Convert from quaternion to euler angles [roll, pitch, yaw]
self.currentOrientation_fix_rad = np.array(
euler_from_quaternion(msg.pose.pose.orientation)
)
Copy link
Contributor

Choose a reason for hiding this comment

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

Please just put a comment saying decomposing msg for all of this so that it is clear what is going on here. Think of someone stressed and tired reading over this late at night. This is quite a lot to read. What tends to happen is people go from comment to comment so if you put a line saying msg is being decomposed into elements they will understand and move to the next comment with little headache.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Okay. I'll do that for other parts of the code too.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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


# Calculate the desired heading
self.desiredHeading_fix = find_desired_heading(
self.currentPosition_fix_m[0],
self.currentPosition_fix_m[1],
self.targetPosition_fix_m[0],
self.targetPosition_fix_m[1]
)
Copy link
Contributor

Choose a reason for hiding this comment

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

Should add a comment. As a rule, every line of code should be accompanied with a comment. For example:

# Finding the desired heading angle in the fixed frame
self.desiredHeading_fix = find_desired_heading(
            self.currentPosition_fix_m[0],
            self.currentPosition_fix_m[1],
            self.targetPosition_fix_m[0],
            self.targetPosition_fix_m[1]
        )

Copy link
Collaborator Author

Choose a reason for hiding this comment

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


# Calculate the desired steering angle
self.desiredSteeringAngle_ego_rad = find_proportional_control_steering_angle(
0.5,
self.desiredHeading_fix,
self.currentOrientation_fix_rad[2] # [2] refers to yaw
)

Copy link
Contributor

Choose a reason for hiding this comment

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

You should run tests to confirm this. Won't merge this PR until it is confirmed.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This will be ready to test when Shailin's package config ticket is merged.

# Calculate the desired velocity
self.desiredVelocity_ego_mps = find_desired_velocity(
self.targetPosition_fix_m[0],
self.currentPosition_fix_m[0],
self.targetPosition_fix_m[1],
self.currentPosition_fix_m[1],
1,
2
)

# Calculate the desired acceleration
self.desiredAcceleration = find_desired_acceleration(
self.currentLinearVelocity_fix_mps,
self.desiredVelocity_ego_mps
)

# TODO: Integrate with other tickets (publish to /AckermannDriveStamped) [F1T-16]


def main(args=None):
rclpy.init(args=args)
node = Navigation()
rclpy.spin(node)

# Destroy the node explicitly
node.destroy_node()
rclpy.shutdown()


if __name__ == '__main__':
main()