14 Tutorial - Simulation of Maneuvering Motions in Python
In this tutorial we will learn to simulate the motions of a ship in python using the linearized maneuvering equations of motion.
After completing this tutorial, the student will be able to:
- Calculate rotation matrices and Euler rate matrices
- Implement fixed and switching rudder control
- Calculate the mass matrix of a vessel
- Dimensionalize hydrodynamic derivatives
- Implement the vessel’s equations of motion - both kinematic and dynamic
- Simulate the vessel’s motion
14.1 Getting Started
We will be using the same repository as the previous tutorial. Once the previous tutorial deadline is over, your instructor will update the upstream repository with the necessary files for this tutorial and raise a pull request on your team repository. You will need to pull in the changes from the upstream repository to your team repository to start this tutorial. The instructions to pull in the changes are given in Appendix B.
After you complete the steps shown in Appendix B to synchronize your repository with the upstream repository, navigate to the root directory of your repository. Pull the latest changes made to your team repository onto your local machine.
cd <your-repository-name>
git pull origin main
The relevant folder structure of the repository for this tutorial is shown below.
<your-repository-name>
├── ros2_ws/
│ ├── src/
│ │ ├── student/
│ │ │ ├── tut_03/
│ │ │ │ ├── hyd.yml
│ │ │ │ ├── input.yml
│ │ │ │ ├── simulate.py
│ │ │ │ ├── read_input.py
│ │ │ │ ├── class_vessel.py
│ │ │ │ ├── module_control.py
│ │ │ │ ├── module_kinematics.py
│ │ │ │ └── plot_results.py
│ │ │ └── ...
├── README.md
├── ros2_run_devdocker.sh
├── ros2_run_devdocker.bat
└── LICENSE
Start your own branch from the main
branch.
git checkout -b <your-name>
All your group members can work independently on their own branches. However, you will have to merge your branches back to the main
branch before the end of the tutorial. We learnt how to do this in Chapter 13 using pull requests.
14.2 Description of Files
The tutorial contains several Python files that work together to simulate vessel motion:
14.2.1 Configuration Files
input.yml
: Contains vessel parameters including:- Physical properties (mass, dimensions, density)
- Initial conditions for position and velocity
- Simulation parameters (time step, duration)
- Control settings
- Path to hydrodynamic coefficients file
hyd.yml
: Contains hydrodynamic derivatives including:- Surge coefficients (\(X_u\), \(X_{\dot{u}}\))
- Sway coefficients (\(Y_v\), \(Y_{\dot{v}}\), \(Y_r\), \(Y_{\dot{r}}\))
- Yaw coefficients (\(N_v\), \(N_{\dot{v}}\), \(N_r\), \(N_{\dot{r}}\))
- Rudder coefficients (\(Y_{\delta}\), \(N_{\delta}\))
14.2.2 Python Files
simulate.py
: Main simulation script that:- Reads input parameters
- Creates vessel instance
- Runs simulation
- Generates plots
read_input.py
: Handles reading and parsing of configuration files:- Reads YAML files
- Converts parameters to appropriate data types
- Returns structured dictionaries of vessel and hydrodynamic parameters
class_vessel.py
: Contains the Vessel class implementation:- Manages vessel state
- Implements vessel dynamics (vessel_ode)
- Handles simulation stepping and history tracking
- Calculates hydrodynamic and control forces
module_control.py
: Implements control strategies:- Fixed rudder control
- Switching rudder control
module_kinematics.py
: Handles vessel kinematics:- Rotation matrices
- Euler rate matrix calculation
- Expressing cross product in matrix form
- Rotation matrices
plot_results.py
: Generates visualization of simulation results:- Trajectory plot
- Velocity time history
- Turn rate history
- Rudder angle history
- Heading angle history
The simulation uses numerical integration (RK45 method) to solve the vessel’s equations of motion, taking into account hydrodynamic forces, control inputs, and vessel kinematics. The results are stored in the vessel’s history attribute and plotted using matplotlib.
14.3 Steps to Execute the Code
14.3.1 Start the Course Docker Container
First start docker desktop and then follow the instructions below to run the course docker container. Make sure to navigate in the terminal to the root folder of your repository.
For Windows:
./ros2_run_devdocker.bat
For Ubuntu (or MacOS):
./ros2_run_devdocker.sh
You would have noticed that when entering the docker container your path is /workspaces/mavlab
. The root directory of the repository is mounted to the folder /workspaces/mavlab
inside the docker container. The files you edit on your system inside the repository folder are immediately accessible inside the docker container.
14.3.2 Run the Python Script to Simulate the Motion
You can now execute the following command to run the Python code that is present in your repository.
python3 ros2_ws/src/student/tut_03/simulate.py
Now we really see the power of running things inside a docker container. If we were working in our own operating systems, the path of the files will be different for different students. For running the python file, each person would have to edit the above command to make sure python is pointed towards the correct path of the file simulate.py
. However, as we are running things inside a docker container, the path of the file simulate.py
will not change.
Similarly, observe that you did not have to install any python packages like numpy
, scipy
or matplotlib
. These were pre-installed for you in the docker container. Now everyone in the class is using the exact same version of Python and the same version of packages (numpy
, scipy
and matplotlib
).
Running the above command will result in a plot named simulation_results.png
being generated in the root directory of your repository. This plot contains the following subplots:
- The trajectory of the ship in the x-y plane
- The time history of the velocity of the ship
- The time history of the turn rate of the ship
- The time history of the rudder angle
- The time history of the yaw angle
14.4 Implementation Tasks
There are a total of 9 tasks in this tutorial and are described below.
Task 1: Cross Product in Matrix Form
Location: module_kinematics.py
, Smat()
function
Description: Implement the Smat()
function to calculate the cross product of a vector in matrix form.
Input:
- vec: A 3x1 numpy array representing the vector to be cross-multiplied.
Output:
- A 3x3 numpy matrix representing the cross product matrix such that when this matrix is multiplied with another vector, it gives the cross product of the input vector with the other vector.
Task 2: Rotation Matrix
Location: module_kinematics.py
, eul_to_rotm()
function
Description: Implement the eul_to_rotm()
function to calculate the rotation matrix from Euler angles.
Input:
- eul: A 3x1 numpy array representing the Euler angles (roll, pitch, yaw).
Output:
- A 3x3 numpy matrix representing the rotation matrix such that when this matrix is multiplied with a vector in the body coordinate system, it gives the corresponding vector in the global coordinate system.
Task 3: Euler Rate Matrix
Location: module_kinematics.py
, eul_rate_matrix()
function
Description: Implement the eul_rate_matrix()
function to calculate the Euler rate matrix \([J_2]\).
Input:
- eul: A 3x1 numpy array representing the Euler angles (roll, pitch, yaw).
Output:
- A 3x3 numpy matrix representing the Euler rate matrix such that when this matrix is multiplied with the angular velocity vector in the body coordinate system, it gives the rate of change of the Euler angles.
Task 4: Fixed Rudder Control
Location: module_control.py
, fixed_rudder()
function
Description: Implement the fixed_rudder()
function to calculate the rudder angle for fixed rudder control.
Input:
t
: A float representing the time.state
: A 13x1 numpy array representing the state of the vessel. The state vector is defined as:
\[\begin{align} \{x\} = \begin{bmatrix} u & v & w & p & q & r & x & y & z & \phi & \theta & \psi & \delta \end{bmatrix}^T \end{align}\]
Output:
- A float representing the commanded rudder angle \(\delta_c\) in radians.
Task 5: Switching Rudder Control
Location: module_control.py
, switching_rudder()
function
Description: Implement the switching_rudder()
function to calculate the rudder angle for switching rudder control.
Input:
t
: A float representing the time.state
: A 13x1 numpy array representing the state of the vessel.
Output:
- A float representing the commanded rudder angle \(\delta_c\) in radians.
Task 6: Mass Matrix
Location: class_vessel.py
, _generate_mass_matrix()
function
Description: Implement the _generate_mass_matrix()
function to calculate the mass matrix.
Input:
self
: The vessel object.
Output:
- None
Task 7: Dimentionalize Hydrodynamic Derivatives
Location: class_vessel.py
, _dimensionalize_coefficients()
function
Description: Implement the _dimensionalize_coefficients()
function to dimensionalize the hydrodynamic derivatives.
Input:
self
: The vessel object.rho
: A float representing the density of the fluid.L
: A float representing the length of the vessel.U
: A float representing the velocity of the vessel.
Output:
- None
Task 8: Vessel ODE
Location: class_vessel.py
, vessel_ode()
function
Description: Implement the vessel_ode()
function to calculate the vessel’s equations of motion.
Input:
self
: The vessel object.t
: A float representing the time.state
: A 13x1 numpy array representing the state of the vessel.
Output:
- A 13x1 numpy array representing the rate of change of the state.
Task 9: Simulation
Location: simulate.py
, simulate()
function
Description: Implement the simulate()
function to simulate the vessel’s motion.
Input:
self
: The vessel object.
Output:
- None
14.5 Testing the Code
To test the code, commit your changes and push them to the remote repository. This will trigger the GitHub Actions workflow to run the tests. You can view the results of the tests by navigating to the “Actions” tab in the GitHub repository. If the tests pass, the workflow will be marked as successful. If the tests fail, you can view the detailed logs to see which tests failed and why. The GitHub workflow will also show the difference between the expected output and the output generated by your code.
14.6 Evaluation
The evaluation of the tutorial will be performed in the classroom. Notice that this is a group activity. You will be working in a group of 4 students. The evaluation will be performed on the group level. In order to pass the tutorial, the group must pass all the tests in the GitHub Actions workflow and also be able to answer all the questions during the evaluation in the classroom. Those who are not present in the classroom on the day of evaluation will not be able to participate in the evaluation and will automatically fail the tutorial.
While one of the objectives of these tutorials is to give you hands on experience with coding and practical implementation, the more important goal is to help you relate what you are doing in your tutorials to the underlying concepts discussed in the class. Therefore, while you are working on the implementation tasks, make sure you are also thinking about the underlying concepts and how they are being applied in the code.
Some questions to think about while you are working on the implementation tasks:
- Is your code able to pass all the tests in the GitHub Actions workflow?
- Are you able to show running of the simulation live during the evaluation?
- What is the difference between fixed and switching rudder control?
- How have you implemented the switching rudder control?
- Are we integrating the dynamic equations and kinematics equations separately or together? Where in the code is this happening?
- How do you think the simulation results would change if we used a different integration method?
- What is the difference between actual rudder angle and commanded rudder angle?
- Did you run the simulation and check the results?
- Do you think the simulation results are in agreement with the expected results? Why or why not?
- Where is the commanded rudder angle being used in your simulation?
- Is the vessel straight line stable? Why or why not?
- Can we simulate and check the vessel’s straight line stability? How?
14.7 Instructor Feedback through Pull Requests
Commit your changes to the remote repository often. This will help you to track your progress and also help you to revert to a working version if you make a mistake. In addition, the instructor and TA will be able to provide you with feedback on your code through the Feeback
pull request available in your repository. Please do not close this pull request.