diff --git a/docs/docs/ControlAndTelemetry.md b/docs/docs/ControlAndTelemetry.md
new file mode 100644
index 00000000..ae0a4f1c
--- /dev/null
+++ b/docs/docs/ControlAndTelemetry.md
@@ -0,0 +1 @@
+## Telemetry
diff --git a/docs/docs/Tutorials/Install/Install_apt.md b/docs/docs/Tutorials/Install/Install_apt.md
deleted file mode 100644
index be6914ef..00000000
--- a/docs/docs/Tutorials/Install/Install_apt.md
+++ /dev/null
@@ -1,54 +0,0 @@
-##### Requirements
-At the moment, only source installation is supported. Use Ubuntu Focal.
-
-1. Install [ROS 2 Galactic](https://docs.ros.org/en/galactic/index.html)
-
-1. Install [Gazebo Fortress](https://ignitionrobotics.org/docs/fortress)
-
-1. Install necessary tools
-
- ```
- sudo apt install python3-vcstool python3-colcon-common-extensions python3-pip git wget
- ```
-
-##### Usage
-
-1. Create a workspace, for example:
-
- ```
- mkdir -p ~/buoy_ws/src
- cd ~/buoy_ws/src
- ```
-
-1. Clone all source repos with the help of `vcstool`:
-
- ```
- wget https://raw.githubusercontent.com/osrf/buoy_entrypoint/main/buoy_all.yaml
- vcs import < buoy_all.yaml
- cd ~/buoy_ws
- ```
-
-1. Set the Gazebo version to Fortress. This is needed because we're not using an
- official ROS + Gazebo combination:
-
- ```
- export IGNITION_VERSION=fortress
- export GZ_VERSION=fortress
- ```
-
-1. Install ROS dependencies
-
- ```
- sudo pip3 install -U rosdep
- sudo rosdep init
- rosdep update
- rosdep install --from-paths src --ignore-src -r -y -i
- ```
-
-1. Build and install
-
- ```
- source /opt/ros/galactic/setup.bash
- cd ~/buoy_ws
- colcon build
- ```
diff --git a/docs/docs/Tutorials/Install/Install_docker.md b/docs/docs/Tutorials/Install/Install_docker.md
index 105768f6..cd123306 100644
--- a/docs/docs/Tutorials/Install/Install_docker.md
+++ b/docs/docs/Tutorials/Install/Install_docker.md
@@ -1,3 +1,5 @@
+Docker images that include the neccessary software and dependencies have been created for convenience.
+
##### Requirements
1. Install Docker using [installation instructions.](https://docs.docker.com/engine/install/ubuntu/).
@@ -12,22 +14,23 @@
1. Clone the buoy_entrypoint repository to download the latest Dockerfile.
- ```
- git clone https://github.com/osrf/buoy_entrypoint.git
- cd ~/buoy_entrypoint/docker/
- ```
+```
+$ git clone https://github.com/osrf/buoy_entrypoint.git
+$ cd ~/buoy_entrypoint/docker/
+```
1. Build the docker image
-
- ```
- ./build.bash buoy
- ```
+
+```
+$ ./build.bash buoy
+```
1. Run the container
- ```
- ./run.bash [-d|s] buoy:latest
- ```
+```
+$ ./run.bash [-d|s] buoy:latest
+```
+
where `./run.bash` option:
* -d Use for development with host system volume mount
* -s Simulation purposes only
@@ -37,8 +40,18 @@
1. To have another window running the same docker container, run this command in a new terminal:
- ```
- ./join.bash buoy_latest_runtime
- ```
+```
+$ ./join.bash buoy_latest_runtime
+```
> The build and run bash scripts are a wrapper around rocker, checkout its [documentation](https://github.com/osrf/rocker) for additional options.
+
+##### Run an example to test
+
+Inside the docker container, run:
+
+```
+$ gz sim mbari_wec.sdf -r
+```
+
+The simulation software should now be available. To run and test, proceed to the [Run the Simulator](../../../tutorials/#running-the-simulator) tutorial series.
\ No newline at end of file
diff --git a/docs/docs/Tutorials/Install/Install_source.md b/docs/docs/Tutorials/Install/Install_source.md
new file mode 100644
index 00000000..4cc56199
--- /dev/null
+++ b/docs/docs/Tutorials/Install/Install_source.md
@@ -0,0 +1,77 @@
+##### Install Requirements
+Use Ubuntu 22.04.
+
+1. Install [ROS 2 Humble](https://docs.ros.org/en/humble/index.html)
+
+Buoy Sim is tested against the cyclonedds rmw implementation, so set that up as follows:
+```
+sudo apt install -y ros-humble-rmw-cyclonedds-cpp
+export RMW_IMPLEMENTATION=rmw_cyclonedds_cpp
+```
+
+2. Install [Gazebo Garden](https://gazebosim.org/docs/garden)
+
+
+3. Install necessary tools
+
+```
+$ sudo apt install python3-vcstool python3-colcon-common-extensions python3-pip git wget
+```
+
+##### Buoy Simulation Software Build
+
+1. Create a workspace, for example:
+
+```
+$ mkdir -p ~/buoy_ws/src
+$ cd ~/buoy_ws/src
+```
+
+1. Clone all source repos with the help of `vcstool`:
+
+```
+$ wget https://raw.githubusercontent.com/osrf/buoy_entrypoint/main/buoy_all.yaml
+$ vcs import < buoy_all.yaml
+$ cd ~/buoy_ws
+```
+
+1. Set the Gazebo version to Garden. This is needed because we're not using an
+ official ROS + Gazebo combination:
+
+```
+$ export GZ_VERSION=garden
+```
+
+1. Install ROS dependencies
+
+```
+$ sudo pip3 install -U rosdep
+$ sudo rosdep init
+$ rosdep update
+$ rosdep install --from-paths src --ignore-src -r -y -i
+```
+
+1. Build and install
+
+```
+$ source /opt/ros/humble/setup.bash
+$ cd ~/buoy_ws
+$ colcon build
+```
+
+The simulation software should build without errors. To run and test, proceed to the [Run the Simulator](../../../tutorials/#running-the-simulator) tutorial series. Or run a quick test as described below to confirm all has worked as expected.
+
+##### Run an example to test
+
+1. In a new terminal, source the workspace
+
+```
+$ . ~/buoy_ws/install/setup.sh`
+```
+
+1. Launch the simulation
+
+```
+$ ros2 launch buoy_gazebo mbari_wec.launch.py`
+```
+
diff --git a/docs/docs/Tutorials/ROS2/ROS2.md b/docs/docs/Tutorials/ROS2/ClosedLoopControl.md
similarity index 100%
rename from docs/docs/Tutorials/ROS2/ROS2.md
rename to docs/docs/Tutorials/ROS2/ClosedLoopControl.md
diff --git a/docs/docs/Tutorials/ROS2/MPC.md b/docs/docs/Tutorials/ROS2/MPC.md
new file mode 100644
index 00000000..e69de29b
diff --git a/docs/docs/Tutorials/ROS2/MessagesAndServices.md b/docs/docs/Tutorials/ROS2/MessagesAndServices.md
new file mode 100644
index 00000000..e69de29b
diff --git a/docs/docs/Tutorials/ROS2/OpenLoopControl.md b/docs/docs/Tutorials/ROS2/OpenLoopControl.md
new file mode 100644
index 00000000..e69de29b
diff --git a/docs/docs/Tutorials/ROS2/Template.md b/docs/docs/Tutorials/ROS2/Template.md
new file mode 100644
index 00000000..e69de29b
diff --git a/docs/docs/Tutorials/Simulation/RunSimulator.md b/docs/docs/Tutorials/Simulation/RunSimulator.md
new file mode 100644
index 00000000..c18255b0
--- /dev/null
+++ b/docs/docs/Tutorials/Simulation/RunSimulator.md
@@ -0,0 +1,32 @@
+##### Introduction
+
+This tutorial will illustrate how to start the buoy simulation in Gazebo, when the simulation is running, a rendering of the buoy system motions will be visible, and ROS2 messages will be published that represent the buoy systems state. The simulation also provides the same ROS2 services the real buoy does, so will respond to ROS2 messages appropriately.
+
+Subsequent tutorials will illustrate how to view and plot data being published by the simulation, view data logs being generated, and control the simulated buoy with the command-line tool that is available on the buoy.
+
+
+##### Run
+To run the simulator, it is necessary to source the workspace in a separate terminal than was used to build the application. Therefore, open a new terminal window and do the following:
+
+1. Source the workspace
+
+```
+$ . ~/buoy_ws/install/setup.sh
+```
+
+1. Launch the simulation
+
+```
+$ ros2 launch buoy_gazebo mbari_wec.launch.py
+```
+
+The Gazebo rendering of the buoy system should become visible and appear as follows:
+
+
+
+To start the simulation, press the "play" arrow in the lower left, the buoy should start to move in response to incoming waves.
+
+It is also possible to adjust various parameters such as the sea-state, visibility of the rendering, and speed the simulation will run relative to real-time. These topics are covered in a later tutorial.
+
+To view the ROS2 messages and associated data while the simulation runs, proceed to the next tutorial: [View ROS2 Messages](SimulatorOutputROS.md)
+
diff --git a/docs/docs/Tutorials/Simulation/Simulation.md b/docs/docs/Tutorials/Simulation/SimulatorInteraction.md
similarity index 100%
rename from docs/docs/Tutorials/Simulation/Simulation.md
rename to docs/docs/Tutorials/Simulation/SimulatorInteraction.md
diff --git a/docs/docs/Tutorials/Simulation/SimulatorOutputLogs.md b/docs/docs/Tutorials/Simulation/SimulatorOutputLogs.md
new file mode 100644
index 00000000..1f8dcc32
--- /dev/null
+++ b/docs/docs/Tutorials/Simulation/SimulatorOutputLogs.md
@@ -0,0 +1,12 @@
+##### Run
+
+1. Source the workspace
+
+ `. ~/buoy_ws/install/setup.sh`
+
+1. Launch the simulation
+
+ `ros2 launch buoy_gazebo mbari_wec.launch.py rviz:=True`
+
+
+
diff --git a/docs/docs/Tutorials/Simulation/SimulatorOutputPbcmd.md b/docs/docs/Tutorials/Simulation/SimulatorOutputPbcmd.md
new file mode 100644
index 00000000..1f8dcc32
--- /dev/null
+++ b/docs/docs/Tutorials/Simulation/SimulatorOutputPbcmd.md
@@ -0,0 +1,12 @@
+##### Run
+
+1. Source the workspace
+
+ `. ~/buoy_ws/install/setup.sh`
+
+1. Launch the simulation
+
+ `ros2 launch buoy_gazebo mbari_wec.launch.py rviz:=True`
+
+
+
diff --git a/docs/docs/Tutorials/Simulation/SimulatorOutputPlotjuggler.md b/docs/docs/Tutorials/Simulation/SimulatorOutputPlotjuggler.md
new file mode 100644
index 00000000..b65ceed4
--- /dev/null
+++ b/docs/docs/Tutorials/Simulation/SimulatorOutputPlotjuggler.md
@@ -0,0 +1,23 @@
+"[PlotJuggler](https://www.plotjuggler.io/)" is a plotting program that includes support for ROS2 messages, and allows real-time plotting of data from ROS2 messages while the simulator runs, as well as plotting of logged data.
+
+- To install, see instructions [here](https://index.ros.org/p/plotjuggler/). If using the supplied docker images, this step is not necessary as the software is already installed.
+
+- To start, issue the following command in a window where the environment has already been sourced using ```$ . ~/buoy_ws/install/setup.sh```:
+
+```
+$ ros2 run plotjuggler plotjuggler
+```
+
+- After an entertaining splash-screen, a blank PlotJuggler screen will appear. Under "Streaming" (upper left, second item below "File"), select the "ROS2 Topic Subscriber" option and click "Start". A new window will appear showing the ROS2 topics available on the system. Note that the Gazebo Simulator of the buoy must be running for the ROS2 topics that contain the buoy data to be present.
+
+Select the /arhs_data, /power_data, /spring_data, battery_data, heavecone_data and /xb_data topics and click "OK"
+
+- The selected topics will appear in the "Timeseries List" window, and selecting the carot to the left of each topic will expand them and show the data that can be plotted. Note that these topics and data are the same as are visible using the ```$ ros2 topic list``` and ```$ ros2 topic echo ...``` commands from the command-line.
+
+
+- Dragging any data item into the plot field on the right will plot that data on a scrolling graph. The time-extent of the graph can be changed using the "Buffer" text-box under the "Streaming" box in the upper left. Graphs can be split horizontally and vertically to make room for more data items, see this guide for information on manipulating the PlotJuggler windows.
+
+- After a bit of data selection, the window can look like the example below and show many data items in real-time. Under the "File" box in the upper left, there are options to save and retrieve this layout to avoid setting up the windows at each invocation of PlotJuggler. PlotJuggler will continue to run through re-starts of the simulator, so it is often not necessary to re-start PlotJuggler often.
+
+
+
diff --git a/docs/docs/Tutorials/Simulation/SimulatorOutputROS.md b/docs/docs/Tutorials/Simulation/SimulatorOutputROS.md
new file mode 100644
index 00000000..8bb37f1a
--- /dev/null
+++ b/docs/docs/Tutorials/Simulation/SimulatorOutputROS.md
@@ -0,0 +1,53 @@
+##### ROS2 Message
+
+While running, the simulator generates exactly the same ROS2 messages that the buoy hardware does during operation. These are grouped into ROS2 topics that corresponds to data being produced by each micro-controller or instrument on the buoy. To see all ROS2 topics being published to on the system, issue the following command (after sourcing the workspace if needed in a new terminal ``` $ . ~/buoy_ws/install/setup.sh```
+
+```
+$ ros2 topic list
+/ahrs_data
+/clock
+/joint_states
+/parameter_events
+/power_data
+/rosout
+/spring_data
+/tf
+/tf_static
+/xb_imu
+```
+
+The topics /ahrs_data, /battery_data, /spring_data, /power_data, and /heavecone_data coorespond to the buoy-based instrumentation (AHRS), battery controller, spring controller, power-converter controller, and heave-cone controller. To see the data being published in these topics, issue the following command and the data will scroll by:
+
+```
+$ ros2 topic echo power_data
+---
+header:
+ stamp:
+ sec: 712
+ nanosec: 710000000
+ frame_id: ''
+seq_num: 6703
+rpm: 369.927978515625
+sd_rpm: 0.0
+voltage: 313.98431396484375
+draw_curr_limit: 0.0
+bcurrent: -0.14509780704975128
+wcurrent: -0.2554447054862976
+torque: 0.0
+diff_press: 2.9100000858306885
+bias_current: 0.0
+loaddc: 0.0
+scale: 1.0
+retract: 0.6000000238418579
+target_v: 0.0
+target_a: -0.2554447054862976
+charge_curr_limit: 0.0
+status: 0
+---
+```
+
+The data in each topic corresponds to the message descriptions which can be seen here along wit a description of each field.
+
+Several of these topics are only available in simulation, and only /ahrs_data, /battery_data, /spring_data, /power_data, and /heavecone_data will be present on the real buoy.
+
+The next tutorial "[View Messages with Plotjuggler](SimulatorOutputPlotjuggler.md)" shows how to conveniently plot these data items while the simulator is running.
diff --git a/docs/docs/Tutorials/Simulation/SimulatorParameters.md b/docs/docs/Tutorials/Simulation/SimulatorParameters.md
new file mode 100644
index 00000000..3b2bd11f
--- /dev/null
+++ b/docs/docs/Tutorials/Simulation/SimulatorParameters.md
@@ -0,0 +1,9 @@
+##### Start-up parameters
+There are a number of parameters that change the behavior of the simulator, and must be specified at start-up:
+
+- Sea-State: This is specified as a Wave Height and Period. If a positive value of wave-period is specified, a Pierson-Moskowitch spectrum with the specfied significant wave-height and peak-period is used. If a negative value of wave-period is specified, a mono-chromatic incoming wave at the specified period and height is used.
+- Real-time factor: This specifies how fast the simulator will run. A real-time factor of 1.0 cooresponds to the simulation time proceeding at the same speed as the wall-clock. A larger value runs the simulator faster than real-time, practical upper limits on normal hardware are a real-time factor of about 30, and if this is not possible the simulator will run as fast as possible.
+- Heave-cone door position: The simulation can be run with the heave-cone doors either open, or closed. This can not be changed while the simulation is running.
+- Simulation Rendering: The simulator can be run with our without a visual rendering of the system. The simulator may run faster without the rendering graphics.
+
+##### Run-time control
diff --git a/docs/docs/Tutorials/Simulation/images/BuoyGazebo.png b/docs/docs/Tutorials/Simulation/images/BuoyGazebo.png
new file mode 100644
index 00000000..24f896b0
Binary files /dev/null and b/docs/docs/Tutorials/Simulation/images/BuoyGazebo.png differ
diff --git a/docs/docs/images/Buoy_Gazebo_RViz.png b/docs/docs/Tutorials/Simulation/images/Buoy_Gazebo_RViz.png
similarity index 100%
rename from docs/docs/images/Buoy_Gazebo_RViz.png
rename to docs/docs/Tutorials/Simulation/images/Buoy_Gazebo_RViz.png
diff --git a/docs/docs/Tutorials/Simulation/images/PlotJuggler.png b/docs/docs/Tutorials/Simulation/images/PlotJuggler.png
new file mode 100644
index 00000000..07e3ecc8
Binary files /dev/null and b/docs/docs/Tutorials/Simulation/images/PlotJuggler.png differ
diff --git a/docs/docs/architecture.md b/docs/docs/architecture.md
index 3396bc4e..11c305c7 100644
--- a/docs/docs/architecture.md
+++ b/docs/docs/architecture.md
@@ -1,21 +1,57 @@
-The MBARI Wave-Energy-Converter is a small point absorber design that includes a surface expression, an electro-hydraulic PTO, and a submerged heave-cone device.
-The system is moored to the seafloor (typically in 80m of water) through a chain-catenary mooring connected to an anchor.
-As waves excite the system, a differential motion results between the buoy at the surface and the submerged heave cone.
-Resisting this motion results in energy being absorbed by the system, and this energy is converted to electrical form and stored in a battery bank on the buoy. The rest of this section provides details about the various components of the system
+The MBARI Wave-Energy-Converter is a small point absorber design that includes a surface expression, an electro-hydraulic PTO, and a submerged heave-cone device. The system is moored to the seafloor (typically in 80m of water) through a chain-catenary mooring connected to an anchor. As waves excite the system, a differential motion results between the buoy at the surface and the submerged heave cone. Resisting this motion results in energy being absorbed by the system, and this energy is converted to electrical form and stored in a battery bank on the buoy. The rest of this section provides details about the various components of the system

-# Buoy, Heave Cone, and Mooring
-The buoy
+## Buoy, Heave Cone, and Mooring
+The buoy in the MBARI-WEC has a diameter of 2.6m, a waterplane area of 5 m^2, and a mass of 1400kg. This buoy houses the system battery and compute infrastructure, described below.
-# Electrical System
+The heave-cone component sits at about 30m depth and provides inertia and drag for the surface-buoy to pull against. The heave-cone has operable doors that can be opened to reduce the drag and inertial of this component in high sea-states. When the doors are open, the heave-cone has added-mass of about 10,000kg, in addition to it's own 600kg mass. When opened, the added-mass reduces to about 3,000kg, which reduces the inertial forcing and increses the natural frequency of the buoy -- heave-cone pair.
-# Compute and Control Systems
+A chain-catenary mooring and anchor connects to heave-cone to the ocean floor, keeping the buoy on-station. The system loading due to the mooring increases in higher winds and currents, but remains relatively low compared with the inertia forces the heave-cone creates.
-# Sensors
-### Load Cell
-### Buoy IMU
-### Heave Cone IMU
+## PTO System
+The power take-off device is located below the buoy and converts the differential motion and forces between the buoy and heave-cone from mechanical to eletrical energy. This device is an electro-hydraulic device in which a piston pumps oil through a hydraulic motor, causing an electrical motor/generator to spin and generate electrical energy. In parallel to the hydraulic ram, a pneumatic piston charged with an inert gas provides a sprint returning force for the system.
-# Instrumentation Interface
+ The combination of the hydraulic and pneumatic pistons creates a spring-damper system for which the spring constant is set by the amount of gas in the systen, and the damping behavior is adjustable electronically by varying the torque on the hydraulic motor in response to conditions. The electrical-drive is a four-quadrant device in which the electric motor can operate as a generator in which energy flows into the battery, or as a motor in which energy is drawn from the battery. The winding-currents (and resulting torque) can be set arbitrarily, but by default the power take-off device acts as a generator, i.e. a damper resisting motion.
+
+## Electrical System
+The electrical system of this buoy consists of a 325V battery system for energy storage, and a 24V system for powering ancillary instrumenation. The 325V battery is connected directly to the power take-off device motor drive electronics. In normal use, the motor-drive device is generating electrial energy at 325V which charges the battery system. In the case the battery is full (or dis-connected), the motor-drive system directs excess energy to an electrical load-dump device. This submerged heater plays a critcal role in maintaining a load on the power take-off device at all times.
+
+The electrical system also includes 300V-24V power supplies that provides 24 volts to the compute and instrumentation infrastructure in the system. In the case of low battery voltage due to an extended period of calm seas, the
+
+## Compute and Control Systems
+The compute and control architecture of the system is such that critical functions are performed by micro-controllers throughout the system that implement default behaviors and stream sensor data continously. A Linux computer on the buoy performs data-logging and provides a command interface to the underlying micro-controllers. See figure. The system is designed such that the Linux computer is not necessary for safe behavior, if this computer re-boots or goes offline, the system will default to safe behaviors. Additionally, the microcontrollers will ignore damaging commands from the Linux computer. This architecture allows control algorithms running on the Linux computer to be started, stopped, and changed while the device is at sea through the cell-modem connection.
+
+
+
+The fundamental system behaviors are performed by a network of micro-controller based compute nodes, that communicate with the buoy Linux computer and with one-another through a Controller Area Network (CAN) bus. There are four of these controllers as follows:
+
+- Battery Controller (BC_): This micro-controller monitors battery voltage, currents, state-of-charge, cell-balance, and environmental conditions inside the battery enclosure. This controller is largely a data-telemetery gathering item, but also includes an important low-voltage disconnect features which shuts down the 24V battery bus during periods of low-battery state-of-charge. During these periods the system continues to convert wave-energy and charge the batteries, but all sources of significant battery drain are disconnected which allows the battery to re-charge to a servicable level, even in calm conditions.
+
+- Spring Controller (SC_): This micro-controller primarily monitors the piston position and a load-cell located between the buoy and power take-off component. Additionally, this controller responds to commands to change the gas pressure in each chamber of the pneumatic spring, a pumop to move gas from the lower pressure chamber to the higher pressure chamber, and a valve to do the opposite. Additionally, this controller can turn power on and off to the heave-cone.
+
+- Power Converter (PC_): This controller implements the field-oriented control of the winding current in the generator.
+
+- Heave-cone Controller (TC_): This
+
+
+The on-board linux computer is assessible from shore over a radio link (cell-modem, satellite, or line-of-site radio). This link enables enabling data-telemetry, real-time control, and software-updates to be applied to the Linux computer.
+
+
+## Sensors and Measurements
+** Load Cell: ** This is a load cell between the buoy and the power take-off device, and has a range of up to 20,000lbs.
+
+** Piston Position: ** Inside the pneumatic spring there is a laser range-finder that contiously monitors the position of the power take-off piston.
+
+** Pneumatic Pressures: ** The spring controller monitors the pressures of the two gas-chambers that make up the pneumatic spring.
+
+** Buoy Inertial Measurement Unit: ** On-board the buoy there is a GPS disciplined six DOF attitude-heading and reference system. This unit monitors and resports the buoys attitude and GPS location.
+
+** Heave Cone Inertial Measurement Unit: ** On-board the heave-cone there is an attitude-heading and reference system with a magnetometer and pressure sensor that reports the heave-cones orientation and depth.
+
+** Electrical System Sensors: **
+
+** RADAR: **
+
+## Instrumentation Interface
diff --git a/docs/docs/images/SoftwareArchitectureDiagramV2aDeployed.png b/docs/docs/images/SoftwareArchitectureDiagramV2aDeployed.png
new file mode 100644
index 00000000..95e044db
Binary files /dev/null and b/docs/docs/images/SoftwareArchitectureDiagramV2aDeployed.png differ
diff --git a/docs/docs/theory.md b/docs/docs/theory.md
index 7f132062..8e1cb553 100644
--- a/docs/docs/theory.md
+++ b/docs/docs/theory.md
@@ -1 +1,244 @@
-Under Construction
+## Modeling Technique Overview
+The numerical modeling used in this simulator relies upon the Gazebo simulators ability to solve for the
+motion of a collection of rigid bodies connected by various types of joints. Gazebo can use several
+different physics solvers to perform this solution, and the wave-energy buoy simulator in this project
+uses the DART physics engine. The physics engine
+solves the multi-body six degree-of-freedom problem for the motion of the connected buoy, power-take-off device, and heave cone,
+subject to initial conditions and forces that act on the various components as the simulation progresses. In the Gazebo simulator,
+these forces are provided by plugin code that applies forces to each body based on the state (position and velocity) of each
+component in the system at each timestep.
+
+The Gazebo simulator already includes several plugins that provide relevant forces such as buoyancy and hydrodynamic drag.
+Additionally, several additional plugins have been created for this simulator that provide the forcings on the system
+due to the electro-hydraulic power-take-off system, the pneumatic spring system, the tether connecting the PTO to the
+heave-cone, the mooring system that anchors the system, and the forcing on the buoy from the ocean surface waves.
+The sections below outline some details about how each of these forcings are modelled and computed. First however,
+the specific physical characteristics of the MBARI WEC are tabulated for reference.
+
+--------------------------------------------------------------------------------------------------------
+## Physical Characteristics
+
+Each rigid body in the simulation has a "Link Frame" coordinate system in which all other characteristics of the
+body are defined in for computational purposes. This link-frame coordinate system is often selected to be at the
+location of a joint that connects the various bodies (which are also called links in the vernacular of Gazebo).
+In the following sections, all quantities are defined in the body's link frame unless otherwise noted. Also, the
+description below includes alternative notation for added mass, e.g. \(\\ \mu_{xx}\), in the style of Newman.
+
+
+### Surface Buoy
+| | Description | | Units |
+|:----------------:|:----------------------------------------------------------|:----------------:|:---------:|
+| \(m\) | Buoy Mass | 1400 | kg |
+| \(V\) | Displacement (undisturbed buoy) | 1.0 | m\(^3\) |
+| \(\bf{x}_{COG}\) | Center of Gravity in Link Frame (x,y,z) | (0.0, 0.0, 2.03) | m |
+| \(\bf{x}_{COB}\) | Center of Buoyancy in Link Frame (x,y,z) | (0.0, 0.0, 2.05) | m |
+| \(\bf{x}_{COW}\) | Center of Waterplane in Link Frame, including PTO and cone| (0.0, 0.0, 2.27) | m |
+| \(I_{xx}\) | Roll Moment of Inertia (MOI), origin at pivot | 7000 | kg m\(^2\)|
+| \(I_{yy}\) | Pitch Moment of Inertia origin at pivot | 7040 | kg m\(^2\)|
+| \(I_{zz}\) | Yaw Moment of Inertia, origin at pivot | 670 | kg m\(^2\)|
+| \(A_{wp}\) | Waterplane Area (undisturbed buoy) | 5.0 | m\(^2\) |
+| \(X_{\dot{u}}\) | Surge Added Mass (\(\mu_{xx}\)) | 260 | kg |
+| \(X_{\dot{q}}\) | Surge-Pitch Added Mass, origin at pivot (\(\mu_{xq}\)) | 370 | kg |
+| \(Y_{\dot{v}}\) | Sway Added Mass ( \(\mu_{yy}\)) | 260 | kg |
+| \(Y_{\dot{p}}\) | Sway-Roll Added Mass, origin at pivot (\(\mu_{yp}\)) | -370 | kg |
+| \(Z_{\dot{w}}\) | Heave Added Mass (\(\mu_{zz}\)) | 3080 | kg |
+| \(K_{\dot{p}}\) | Roll Added Mass MOI, origin at pivot (\(\mu_{pp}\)) | 780 | kg m\(^2\)|
+| \(M_{\dot{q}}\) | Pitch Added Mass MOI, origin at pivot (\(\mu_{qq}\)) | 780 | kg m\(^2\)|
+| \(X_{u\mid u \mid}\) | Surge Quadratic Drag | -430 | kg/m |
+| \(Y_{v\mid v \mid}\) | Sway Quadratic Drag | -430 | kg/m |
+| \(Z_{w\mid w \mid}\) | Heave Quadratic Drag | -3280 | kg/m |
+| \(K_{p\mid p \mid}\) | Roll Quadratic Drag: | -880 | kg m\(^2\)|
+| \(M_{q\mid q \mid}\) | Pitch Quadratic Drag: | -880 | kg m\(^2\)|
+| \(N_{r\mid r \mid}\) | Yaw Quadratic Drag: | -50 | kg m\(^2\)|
+
+
+- Buoy Link Frame is located at base of the buoy bridle at the pivot.
+- Unspecified stability derivative values (\(M_{\dot{r}}\), \(X_{uv}\), \(Y_{vu}\), etc) are zero.
+- Inertias, Added mass inertias, and stability derivatives are all specified about the link frame origin, i.e. the pivot.
+- Added mass values are infinite frequency.
+- Free-Surface Hydrodynamic Coefficients and Impulse Response Functions can be found here:
+
+### Power Take-Off Device
+| | Description | | Units |
+|:-----------------:|:-------------------------------------------|:----------------:|:---------:|
+| \(m\) | PTO Mass | 605 | kg |
+| \(V\) | PTO Displacement | 1.0 | m\(^3\) |
+| \(\bf{x}_{COG}\) | Center of Gravity in Link Frame (x,y,z) | (0.0, 0.0, -4.0) | m |
+| \(\bf{x}_{COB}\) | Center of Buoyancy in Link Frame (x,y,z) | (0.0, 0.0, -3.0) | m |
+| \(I_{xx}\) | Roll Moment of Inertia | 32600 | kg m\(^2\)|
+| \(I_{yy}\) | Pitch Moment of Inertia | 32600 | kg m\(^2\)|
+| \(I_{zz}\) | Yaw Moment of Inertia | 7 | kg m\(^2\)|
+| \(I_{xy}\) | Roll-Pitch Product of Inertia | 0 | kg m\(^2\)|
+| \(I_{xz}\) | Roll-Yaw Product of Inertia | -2 | kg m\(^2\)|
+| \(I_{yz}\) | Pitch-Yaw Product of Inertia | -3 | kg m\(^2\)|
+| \(X_{\dot{u}}\) | Surge Added Mass (\(\mu_{xx}\)) | 310 | kg |
+| \(X_{\dot{q}}\) | Surge-Pitch Added Mass MOI (\(\mu_{xq}\)) | 1250 | kg m |
+| \(Y_{\dot{v}}\) | Sway Added Mass (\(\mu_{yy}\)) | 310 | kg |
+| \(Y_{\dot{p}}\) | Sway-Roll Added Mass MOI (\(\mu_{yp}\)) | -1250 | kg m |
+| \(Z_{\dot{w}}\) | Heave Added Mass (\(\mu_{zz}\)) | 10 | kg |
+| \(K_{\dot{p}}\) | Roll Added Mass MOI (\(\mu_{pp}\)) | 7040 | kg m\(^2\)|
+| \(M_{\dot{q}}\) | Pitch Added Mass MOI (\(\mu_{qq}\)) | 7040 | kg m\(^2\)|
+| \(X_{u\mid u \mid}\) | Surge Quadratic Drag | -1140 | kg/m |
+| \(Y_{v\mid v \mid}\) | Sway Quadratic Drag | -1140 | kg/m |
+| \(Z_{w\mid w \mid}\) | Heave Quadratic Drag | -50 | kg/m |
+| \(K_{p\mid p \mid}\) | Roll Quadratic Drag | -195400 | kg m\(^2\)|
+| \(M_{p\mid p \mid}\) | Pitch Quadratic Drag | -195400 | kg m\(^2\)|
+| \(N_{r\mid r \mid}\) | Yaw Quadratic Drag | -50 | kg m\(^2\)|
+
+- PTO Link Frame is located at top attachment of the PTO (where connects to the buoy).
+- Unspecified stability derivative values (\(M_{\dot{r}}\), \(X_{uv}\), \(Y_{vu}\), etc) are zero.
+- Inertias, Added mass inertias, and stability derivatives are all specified about the link frame origin.
+- Added mass values are infinite frequency.
+
+### Piston
+| | Description | | Units |
+|:-----------------:|:-------------------------------------------|:-----------------:|:---------:|
+| \(m\) | Piston Mass | 48.0 | kg |
+| \(\bf{x}_{COG}\) | Center of Gravity in Link Frame (x,y,z) | (0.0, 0.0, -2.58) | m |
+| \(I_{xx}\) | Roll Moment of Inertia | 100.0 | kg m\(^2\)|
+| \(I_{yy}\) | Pitch Moment of Inertia | 100.0 | kg m\(^2\)|
+| \(I_{zz}\) | Yaw Moment of Inertia | 5.0 | kg m\(^2\)|
+
+- The piston is contained with the PTO housing, so it has mass and moments of inertial, but contributes
+no buoyancy, added mass, or quadratic fluid drag.
+
+### Heave Cone
+| | Description | | Units |
+|:-----------------:|:-------------------------------------------|:----------------:|:---------:|
+| \(m\) | Heave Cone Mass | 820 | kg |
+| \(V\) | Heave Cone Displacement | 1.0 | m\(^3\) |
+| \(\bf{x}_{COG}\) | Center of Gravity in Link Frame (x,y,z) | (0.0, 0.0, -1.25)| m |
+| \(\bf{x}_{COB}\) | Center of Buoyancy in Link Frame (x,y,z) | (0.0, 0.0, -1.21)| m |
+| \(I_{xx}\) | Roll Moment of Inertia | 4200 | kg m\(^2\)|
+| \(I_{yy}\) | Pitch Moment of Inertia | 4200 | kg m\(^2\)|
+| \(I_{zz}\) | Yaw Moment of Inertia | 610 | kg m\(^2\)|
+| \(I_{xy}\) | Roll-Pitch Product of Inertia | 0 | kg m\(^2\)|
+| \(I_{xz}\) | Roll-Yaw Product of Inertia | -1 | kg m\(^2\)|
+| \(I_{yz}\) | Pitch-Yaw Product of Inertia | 0 | kg m\(^2\)|
+| \(X_{\dot{u}}\) | Surge Added Mass (\(\mu_{xx}\)) | 720 | kg |
+| \(X_{\dot{q}}\) | Surge-Pitch Added Mass MOI (\(\mu_{xq}\)) | 900 | kg m |
+| \(Y_{\dot{v}}\) | Sway Added Mass (\(\mu_{yy}\)) | 720 | kg |
+| \(Y_{\dot{p}}\) | Sway-Roll Added Mass MOI (\(\mu_{yp}\)) | -900 | kg m |
+| \(Z_{\dot{w}}\) | Heave Added Mass: Doors Closed (\(\mu_{zz}\))| 9330 | kg |
+| \(Z_{\dot{w}}\) | Heave Added Mass: Doors Open | 3000 | kg |
+| \(K_{\dot{p}}\) | Roll Added Mass MOI (\(\mu_{pp}\)) | 3990 | kg m\(^2\)|
+| \(M_{\dot{q}}\) | Pitch Added Mass MOI(\(\mu_{qq}\)) | 3990 | kg m\(^2\)|
+| \(N_{\dot{r}}\) | Yaw Added Mass MOI (\(\mu_{rr}\)) | 10 | kg m\(^2\)|
+| \(X_{u\mid u \mid}\) | Surge Quadratic Drag | -1580 | kg/m |
+| \(Y_{v\mid v \mid}\) | Sway Quadratic Drag | -1580 | kg/m |
+| \(Z_{w\mid w \mid}\) | Vertical Quadratic Drag: Doors Open | -3200 | kg/m |
+| \(Z_{w\mid w \mid}\) | Vertical Quadratic Drag: Doors Closed| -3900 | kg/m |
+| \(K_{p\mid p \mid}\) | Roll Quadratic Drag: | -4620 | kg m\(^2\)|
+| \(M_{q\mid q \mid}\) | Pitch Quadratic Drag: | -4620 | kg m\(^2\)|
+| \(N_{r\mid r \mid}\) | Yaw Quadratic Drag: | -50 | kg m\(^2\)|
+
+- Heave-Cone Link Frame is located at top attachment of the Heave Cone (where it connects to the tether).
+- Unspecified stability derivative values (\(M_{\dot{r}}\), \(X_{uv}\), \(Y_{vu}\), etc) are zero.
+- Inertias, Added mass inertias, and stability derivatives are all specified about the link frame origin.
+- Added mass values are infinite frequency.
+
+
+--------------------------------------------------------------------------------------------------------
+## Electro-Hydraulic PTO Forces
+
+
+
+--------------------------------------------------------------------------------------------------------
+## Pneumatic Spring Forces
+
+#### Definitions
+
+| | Description | Units |
+|------------------|---------------------------------------------------------------|-----------|
+| \(x\) | Piston position | m |
+| \(v\) | Piston velocity | m/s |
+| \(m\) | Mass of gas in chamber | kg |
+| \(T\) | Temperature of gas | K |
+| \(P\) | Gas pressure | Pa |
+| \(V\) | Chamber volume (dependent on piston position) | m\(^{3}\) |
+| \(R_{specific}\) | Specific Gas Constant N\(_2\) | J/kg/K |
+| \(V_{dead}\) | Chamber dead volume (fully compressed) | m\(^{3}\) |
+| \(c_p\) | Specific Heat Capacity N\(_2\) (constant pressure) | J/kg/K |
+| \(A_{piston}\) | Surface area of piston head | m\(^{2}\) |
+| \(n\) | Polytropic index (Adiabatic if \(n=\lambda=1.4\) for N\(_2\)) | N/A |
+| \(r\) | Coefficient of heat transfer (Newton's Law of Cooling) | 1/s |
+
+
+#### Model
+
+Under compression and expansion, the pressure, volume and temperature of the Nitrogen in each
+chamber evolves according to Ideal Gas Law:
+
+$$ P V = m R_{specific} T $$
+
+and a polytropic process:
+
+$$ P = P_0 \left({V_{0} \over V}\right)^{n} $$
+
+with hysteresis, there are two values for the polytropic index, \(n_1\) and \(n_2\), to capture behavior when
+the gas is compressing or expanding. Using this quasi-static solution and
+discrete time steps, and also incorporating hysteresis, the process becomes:
+
+$$ V_k = x_k A_{piston} + V_{dead} $$
+$$
+P_k = P_{k-1} \left({V_{k-1} \over V_k}\right)^n ,\,\,\, n = \begin{cases}
+ n_1 & \text{if } v \ge 0 \\
+ n_2 & \text{otherwise.}
+\end{cases}
+$$
+$$ T_k = {P_k V_k \over m R_{specific}} $$
+
+where \(k\) is the current time step.
+
+Whenever the piston velocity is slow enough, the process is dominated by heat loss and
+modeled with Newton's Law of Cooling (using forward difference) followed by an update of pressure using
+Ideal Gas Law:
+
+$$ T_k = r\, \Delta t\, (T_{env} - T_{k-1}) + T_{k-1} $$
+$$ V_k = x_k A_{piston} + V_{dead} $$
+$$ P_k = {m R_{specific} T_k \over V_k} $$
+
+The mass of the Nitrogen in each chamber is determined from inputs in the SDF:
+
+$$ m = {P_0 (x_0 A_{piston} + V_{dead}) \over R_{specific} T_0} $$
+
+and is used for mass flow between chambers in simulating the pump/valve.
+
+
+#### Determining Parameter Values
+
+Linear regression was used to determine the polytropic indices for each chamber using empirical
+data from the physical system. Using pressure vs volume curves, \(n_1\) is determined from
+increasing volume, and \(n_2\) is determined from decreasing volume. The data is then preconditioned
+by taking the logarithm to linearize and perform regression to find the parameters. For a
+polytropic process:
+
+$$ P V^{n} = C $$
+
+so,
+
+$$ \log{P} + n \log{V} = \log{C} $$
+$$
+\left[ { \begin{array}{cc}
+ \log{\bf V} & 1 \\
+\end{array} } \right] \left[ { \begin{array}{c}
+ -n \\
+ \log{C} \\
+\end{array} } \right] = \log{\bf P}
+$$
+
+in block matrix notation where \({\bf V}\) and \({\bf P}\) are the arrays of volume and pressure data, respectively.
+The other parameters in the system are taken from CAD or empirically determined by comparing logged
+data from prescribed motion between simulation and the physical test bench.
+
+
+--------------------------------------------------------------------------------------------------------
+## Tether Forces
+
+
+--------------------------------------------------------------------------------------------------------
+## Mooring Forces
+
+
+--------------------------------------------------------------------------------------------------------
+## Ocean Wave Forces
diff --git a/docs/docs/tutorials.md b/docs/docs/tutorials.md
index fbabef48..31e195f4 100644
--- a/docs/docs/tutorials.md
+++ b/docs/docs/tutorials.md
@@ -1,21 +1,18 @@
-## Tutorial 1: Installation
-These tutorials will get the required software set up on your computer. The software used by this system have dependencies on a number of software packages with specific versions.
-There are a few ways to install and use the software that provide equivalent capabilities, and are a matter of personal
-preference. Only one of the following tutorials is required.
-
-The simplest approach is to use [docker](www.docker.org). Docker images are provided that have pre-configured installations with all required dependencies, so this is the fast way to get started.
-
-* [Install (docker)](Tutorials/Install/Install_docker.md)
-
-It is also straightforward to simply install the required software and dependencies using apt on Linux. Some configuration is then required and details are provided here:
-
-* [Install (apt)](Tutorials/Install/Install_apt.md)
-
-## Tutorial 2: Run the Simulator
-This tutorial will get the Gazebo Simulation of the WEC running on your computer. With this done you can see the operation of the simulator and perform actions that control it's behavior (e.g. Change the sea-state).
-
-* [Simulate](Tutorials/Simulation/Simulations.md)
-
-## Tutorial 3: Write and Control Code
-
-* [Simulate](Tutorials/ROS2/ROS2.md)
+#### Installation
+- [Install (from source)](Tutorials/Install/Install_source.md)
+- [Install (docker)](Tutorials/Install/Install_docker.md)
+-----------------------------------------------------------
+#### Running the Simulator
+- [Run the Simulator](Tutorials/Simulation/RunSimulator.md)
+- [View Tutorials/ROS2 Messages](Tutorials/Simulation/SimulatorOutputROS.md)
+- [View Messages with Plotjuggler](Tutorials/Simulation/SimulatorOutputPlotjuggler.md)
+- [Simulator Output Data Logs](Tutorials/Simulation/SimulatorOutputLogs.md)
+- [Adjust Simulator parameters](Tutorials/Simulation/SimulatorParameters.md)
+- [Control Simulator with pbcmd](Tutorials/Simulation/SimulatorInteractionPbcmd.md)
+-----------------------------------------------------------
+#### Adding Control Code
+- [Tutorials/ROS2 Messages and Services](Tutorials/ROS2/MessagesAndServices.md)
+- [Project Template](Tutorials/ROS2/Template.md)
+- [Open-Loop Control Example](Tutorials/ROS2/OpenLoopControl.md)
+- [Closed-Loop Control Example](Tutorials/ROS2/ClosedLoopControl.md)
+- [Model-Predictive Control Example](Tutorials/ROS2/MPC.md)
diff --git a/docs/matlab/amText.m b/docs/matlab/amText.m
new file mode 100644
index 00000000..fedbe24a
--- /dev/null
+++ b/docs/matlab/amText.m
@@ -0,0 +1,71 @@
+function str = amText(MA)
+
+if(size(MA) ~= [6 6])
+ fprintf(' amText:Error - The added mass matrix must be 6x6.\n')
+ str = "Error";
+ return
+end
+
+strMat(1,1) = ...
+ "| \\(X_{\\dot{u}}\\) | Surge Added Mass (\\(\\mu_{xx}\\)) | %12.f | kg |";
+strMat(1,2) = ...
+ "| \\(X_{\\dot{v}}\\) | Surge-Sway Added Mass (\\(\\mu_{xy}\\)) | %12.f | kg |";
+strMat(1,3) = ...
+ "| \\(X_{\\dot{w}}\\) | Surge-Heave Added Mass (\\(\\mu_{xz}\\)) | %12.f | kg |";
+strMat(1,4) = ...
+ "| \\(X_{\\dot{p}}\\) | Surge-Roll Added Mass MOI (\\(\\mu_{xp}\\)) | %12.f | kg m |";
+strMat(1,5) = ...
+ "| \\(X_{\\dot{q}}\\) | Surge-Pitch Added Mass MOI (\\(\\mu_{xq}\\)) | %12.f | kg m |";
+strMat(1,6) = ...
+ "| \\(X_{\\dot{r}}\\) | Surge-Yaw Added Mass MOI (\\(\\mu_{xr}\\)) | %12.f | kg m |";
+
+strMat(2,2) = ...
+ "| \\(Y_{\\dot{v}}\\) | Sway Added Mass (\\(\\mu_{yy}\\)) | %12.f | kg |";
+strMat(2,3) = ...
+ "| \\(Y_{\\dot{w}}\\) | Sway-Heave Added Mass (\\(\\mu_{yz}\\)) | %12.f | kg |";
+strMat(2,4) = ...
+ "| \\(Y_{\\dot{p}}\\) | Sway-Roll Added Mass MOI (\\(\\mu_{yp}\\)) | %12.f | kg m |";
+strMat(2,5) = ...
+ "| \\(Y_{\\dot{q}}\\) | Sway-Pitch Added Mass MOI(\\(\\mu_{yq}\\)) | %12.f | kg m |";
+strMat(2,6) = ...
+ "| \\(Y_{\\dot{r}}\\) | Sway-Yaw Added Mass MOI (\\(\\mu_{yr}\\)) | %12.f | kg m |";
+
+
+strMat(3,3) = ...
+ "| \\(Z_{\\dot{w}}\\) | Heave Added Mass (\\(\\mu_{yy}\\)) | %12.f | kg |";
+strMat(3,4) = ...
+ "| \\(Z_{\\dot{p}}\\) | Heave-Roll Added Mass MOI (\\(\\mu_{yp}\\)) | %12.f | kg m |";
+strMat(3,5) = ...
+ "| \\(Z_{\\dot{q}}\\) | Heave-Pitch Added Mass MOI(\\(\\mu_{yq}\\)) | %12.f | kg m |";
+strMat(3,6) = ...
+ "| \\(Z_{\\dot{r}}\\) | Heave-Yaw Added Mass MOI (\\(\\mu_{yr}\\)) | %12.f | kg m |";
+
+
+strMat(4,4) = ...
+ "| \\(K_{\\dot{p}}\\) | Roll Added Mass MOI (\\(\\mu_{pp}\\)) | %12.f | kg m\\(^2\\)|";
+strMat(4,5) = ...
+ "| \\(K_{\\dot{q}}\\) | Roll-Pitch Added Mass MOI(\\(\\mu_{pq}\\)) | %12.f | kg m\\(^2\\)|";
+strMat(4,6) = ...
+ "| \\(K_{\\dot{r}}\\) | Roll-Yaw Added Mass MOI (\\(\\mu_{pr}\\)) | %12.f | kg m\\(^2\\)|";
+
+
+strMat(5,5) = ...
+ "| \\(M_{\\dot{q}}\\) | Pitch Added Mass MOI (\\(\\mu_{qq}\\)) | %12.f | kg m\\(^2\\)|";
+strMat(5,6) = ...
+ "| \\(M_{\\dot{r}}\\) | Pitch-Yaw Added Mass MOI (\\(\\mu_{qr}\\)) | %12.f | kg m\\(^2\\)|";
+
+strMat(6,6) = ...
+ "| \\(N_{\\dot{r}}\\) | Yaw Added Mass MOI (\\(\\mu_{rr}\\)) | %12.f | kg m\\(^2\\)|";
+
+k=0;
+for( i=1:6 )
+ for( j=i:6 )
+ if( MA(i,j) ~= 0 )
+ k=k+1;
+ str(k,1) = sprintf(strMat(i,j),10*round(MA(i,j)/10));
+ end
+ end
+end
+
+
+end
diff --git a/docs/matlab/pbStabDer.m b/docs/matlab/pbStabDer.m
new file mode 100644
index 00000000..dac1e031
--- /dev/null
+++ b/docs/matlab/pbStabDer.m
@@ -0,0 +1,523 @@
+%
+% PURPOSE: Estimate stability derivatives for the buoy, PTO and heave cone
+% components of the Power Buoy.
+%
+% DATE: 20 Dec 2022
+%
+% NOTES: The stability derivatives are defined with respect to land robot
+% coordinates, with z up and x towards the front. The origin is at the pivot.
+%
+% REFERENCES:
+% (1) Francois C, Solid Works schematic of "MBARI Wave Energy Converter: Heave
+% Cone", April, 2022.
+% (2) Francois C, Solid Works schematic of "MBARI Wave Energy Converter: Power
+% Take Off Device", Dec. 5, Jan 6, 2021.
+% (3) Francois C, Solid Works schematic of "MBARI Wave Energy Converter: Buoy",
+% 10/11/2022.
+% (4) Hoerner, "Fluid-Dynamic Drag", 1965.
+% (5) Blevins, "Formulas for Dynamics, Acoustics and Vibration", Wiley, 2016.
+% (6) WAMIT run by Dom, 1 Feb 2022. Filename: mbari_snl.out.
+%
+% Parameters:
+%
+ rho = 1025; %kg/m^3 Density of sea water
+%
+% *** Buoy ***
+%
+ dia_b = 2.64; %m
+ h_b = 1.12-.81; %m height of the beveled section [3]
+ h_cg = 2.03; %m height of the cg above the bridle pivot.
+ zG = .24; %m height of the cg above the water plane.
+ m_b = 1400; %kg Mass of the buoy (in air, no water).
+ m_w_pto = 395; %kg This is in-water "weight"
+ m_w_hc = 703; %kg This is in-water "weight"
+ Cdp = 1.17; %none. For a flat plate, 3 dim perp flow.
+ Ixx_b = 1492; %kg-m^2 Moment of inertia at water plane [3]
+ Ixy_b = -14.15; %kg-m^2 Product of inertia at water plane [3]
+ Ixz_b = 12.96;
+ Iyy_b = 1539;
+ Iyz_b = -14.59;
+ Izz_b = 650.5;
+ h_wl = 2.27; %m height of the waterline above the bridle pivot
+ %when loaded with the pto and heave cone in water.
+%
+% Approximate the below-water part of the buoy as a hemisphere. Find the radius
+% through the density of the displaced water.
+%
+% Vol of a hemisphere = Vh = 2/3*pi*r^3. (1)
+%
+% Vol of displaced sea water =
+%
+ Vw = (m_b + m_w_pto + m_w_hc)/rho;
+%
+% where rho*(m_w_pto and m_w_hc) is the in-water weight of the pto and
+% heave cone respectively. I'm using in-water weights for these two because
+% we want the displaced volume of the buoy, not the displaced volume of the
+% whole rig. Then, from Archimedes:
+%
+% Vh = Vw
+%
+% Substituting (1) for Vh above and solving for r gives
+%
+ r = ( 3/2/pi*Vw )^(1/3);
+%
+% Now the added mass of a 1/2 submerged sphere is (Blevins, #10, page 326)
+%
+ Xudot_b = (2/3) * (1/2) * rho * pi * r^3;
+%
+ Yvdot_b = Xudot_b;
+ Zwdot_b = 8/3*rho*(dia_b/2)^3; %kg. Blevins p.325, #1.
+%
+% These numbers are from Andy's part of theory.md, and apparently he
+% took them from an earlier WAMIT run. So, we have three sets of numbers;
+% 1. My Blevins estimates; 2. Andy's original estimates; and 3. Dom's most
+% recent WAMIT run from 1 Feb 2022. Below are from item 2 above:
+
+ MA_b = [ 330 0 0 0 180 0;
+ 0 330 0 -180 0 0;
+ 0 0 2800 0 0 0;
+ 0 -180 0 430 0 0;
+ 180 0 0 0 430 0;
+ 0 0 0 0 0 50];
+%
+% Transform it to the bridle point using Joan's generalized parallel axis theorem:
+%
+ MAT_b = parallelAxis( MA_b, [0 0 -h_wl]' );
+%
+% And, here are Dom's WAMIT results from his 1 Feb 2022 run, mbari_snl.out.
+% These are the infinite frequency (infinite wave number, zero wave period)
+% values. The values in the .out are nondimensionalized by rho. That is,
+% multiply by rho to get the dimensionalized values. Also, The origin is 10 cm
+% above the water plane:
+%
+ Xudot_bw = .25*rho;
+ Yvdot_bw = .25*rho;
+ Zwdot_bw = 3.0*rho;
+ Xqdot_bw = .23*rho;
+ Ypdot_bw = -.23*rho;
+ Kpdot_bw = .45*rho;
+ Mqdot_bw = .45*rho;
+ Nrdot_bw = 50; %Arbitrary
+%
+% Replace MA_b above with the most recent values:
+%
+ MA_bw= [ Xudot_bw 0 0 0 Xqdot_bw 0;
+ 0 Yvdot_bw 0 Ypdot_bw 0 0;
+ 0 0 Zwdot_bw 0 0 0;
+ 0 Ypdot_bw 0 Kpdot_bw 0 0;
+ Xqdot_bw 0 0 0 Mqdot_bw 0;
+ 0 0 0 0 0 Nrdot_bw];
+
+%
+% Transform it to the bridle point using Joan's generalized parallel axis theorem:
+%
+ h_wlw = h_wl + .1; %m, WAMIT origin 10 cm above waterline
+%
+ MAT_bw = parallelAxis( MA_bw, [0 0 -h_wlw]' );
+%
+% Now build the generalized mass matrix, about the COW:
+%
+ M_b = [ m_b 0 0 0 zG*m_b 0;
+ 0 m_b 0 -zG*m_b 0 0;
+ 0 0 m_b 0 0 0;
+ 0 -zG*m_b 0 Ixx_b Ixy_b Ixz_b;
+ zG*m_b 0 0 Ixy_b Iyy_b Iyz_b;
+ 0 0 0 Ixz_b Iyz_b Izz_b ];
+%
+% Transform it to the bridle point using Joan's generalized parallel axis theorem:
+%
+ MT_b = parallelAxis( M_b, [0 0 -h_wl]' );
+%
+% Drag:
+%
+% Find the drag by assuming a flat plate with area equal to the side view of
+% the in-water part. This is a trapezoid with base b1 = dia_b. Assume the
+% sides form 45 degree angles, then:
+%
+ b1 = dia_b;
+ b2 = dia_b - 2*h_b;
+ At = 1/2 * h_b * (b1 + b2);
+
+ Xuabsu_b = -1/2*rho*Cdp*At; %kg/m.
+ Yvabsv_b = Xuabsu_b;
+%
+% The location of the c.g. appears to be in the center of the side-view,
+% excluding the bridle framework. Thus I'll assume this is also the
+% center-of-area as well as the center-of-drag.
+ Kpabsp_b = Xuabsu_b*h_cg;
+ Mqabsq_b = Kpabsp_b;
+ Nrabsr_b = -50; %kg-m^2 arbitrary
+%
+% Flat plate again, with area of a circle:
+%
+ a = dia_b/2;
+ Zww_b = 1/2*rho*Cdp*pi*a^2; %kg/m, down only.
+%
+
+%
+%
+% *** PTO ***
+%
+ l_pto = 8.82; %m, total length not including tether, L.
+ d_pto = .21; %m, diameter, D, scaled from .34 m, [2].
+ r_pto = d_pto/2; %m, radius
+ cg_pto= 4; %m, distance of the link origin above the c.g.
+ m_pto = 605; %kg, mass (in air).
+ Cd_pto= 1.2; %none. Section drag of a cylinder for
+ % 1e4 < Re < 1.3e5
+ Ixx_pto = 3526; %kg-m^2 Moment of inertia about c.g. [2]
+ Ixy_pto = .4293; %kg-m^2 Product of inertia about c.g. [2]
+ Ixz_pto = -2.289;
+ Iyy_pto = 3526;
+ Iyz_pto = -3.089;
+ Izz_pto = 7.276;
+%
+% Now build the generalized mass matrix, about the CG:
+%
+ M_pto = [ m_pto 0 0 0 cg_pto*m_pto 0;
+ 0 m_pto 0 -cg_pto*m_pto 0 0;
+ 0 0 m_pto 0 0 0;
+ 0 -cg_pto*m_pto 0 Ixx_pto Ixy_pto Ixz_pto;
+ cg_pto*m_pto 0 0 Ixy_pto Iyy_pto Iyz_pto;
+ 0 0 0 Ixz_pto Iyz_pto Izz_pto ];
+%
+% Transform it to the bridle point using Joan's generalized parallel axis theorem:
+%
+ MT_pto = parallelAxis( M_pto, [0 0 cg_pto]' );
+%
+% Translation:
+%
+% Added mass of a cylindrical section; Blevins #1 p. 322.
+%
+ Xudot_pto = rho*pi*d_pto^2/4*l_pto; %kg
+ Yvdot_pto = rho*pi*d_pto^2/4*l_pto; %kg
+ Zwdot_pto = 10; %kg, arbitrary
+%
+% Now rotation about the geometric center:
+%
+% Blevins, #13 p.33 and #1 p322. Add mass MOI is the same as solid MOI.
+%
+ Kpdot_pto = rho*pi*r_pto^2*l_pto/12*(3*r_pto^2 + l_pto^2);
+ Mqdot_pto = Kpdot_pto;
+ Nrdot_pto = 10;
+%
+% Build the generalized added mass matrix about the center of mass:
+%
+ MA_pto = [ Xudot_pto 0 0 0 0 0;
+ 0 Yvdot_pto 0 0 0 0;
+ 0 0 Zwdot_pto 0 0 0;
+ 0 0 0 Kpdot_pto 0 0;
+ 0 0 0 0 Mqdot_pto 0;
+ 0 0 0 0 0 Nrdot_pto];
+%
+% Translate to bridle frame:
+ MAT_pto = parallelAxis( MA_pto, [0 0 cg_pto]');
+
+%
+% Drag of cylindrical section Re ~ 10^4
+%
+ Xuabsu_pto = -1/2*rho*l_pto*d_pto*Cd_pto; %kg/m, Cd ~= 1.0 at Re ~= 10,000.
+ Yvabsv_pto = Xuabsu_pto;
+ Zwabsw = 10;
+%
+% Rotation:
+%
+% Model the pto as a long, thin, vertical cylinder, pivoting at the top. It is
+% length L, and a distance down the cylinder is l meters from the top.
+%
+% drag of a thin cross section at a point l is then
+%
+% Drag = 1/2 * rho * (l*q)^2 * Cd * D * dl
+%
+% where q is the angular speed. dl is an infinitesimal distance along
+% the cylinder. The moment contribution from dl is then D*l. Adding all these
+% up gives a total moment of
+%
+% L
+% M = integral 1/2 * rho * (l*q )^2 * Cd * D * l * dl.
+% 0
+% Performing the integration gives:
+%
+% M = rho/8 * q^2 * D * L^4 * Cd
+%
+% Accounting for the sign:
+% M = -rho/8 * D * L^4 * Cd * q * |q|
+%
+% So then:
+ Kpabsp_pto = -rho/8 *d_pto*l_pto^4*Cd_pto; %kg m^2. Assuming origin at the top.
+ Mqabsq_pto = Kpabsp_pto; %kg m^2.
+ Nrabsr_pto = -10; %kg-m^2 Arbitrary.
+%
+% *** Heave Cone ***
+%
+ A_c = 6.56; %m^2 Projected area, doors closed, along z.
+ A_o = 5.14; %m^2 Projected area, doors open, along z.
+ w_hc = 2.8; %m, Width of the heave cone, [1]
+ hs_hc = 1.3; %m, height of the stem. See drawing.
+ cg_hc = 1.25; %m, height of the pivot above the c.g. See drawing.
+ h_hc = .4; %m, height of the heave cone.
+ A_x = w_hc-h_hc^2; %m^2 Frontal area (trapezoid), perpendicular to x.
+ Cd_hc = 1.2; %none. Drag of cylindrical section.
+ m_hc = 817; %kg Mass of heave cone
+ Ixx_hc = 339.8; %kg-m^2 Moment of inertia about cg [3]
+ Ixy_hc = .16; %kg-m^2 Product of inertia about cg [3]
+ Ixz_hc = -.9;
+ Iyy_hc = 343.73;
+ Iyz_hc = .33;
+ Izz_hc = 613.52;
+%
+% Translation:
+%
+% Doors closed, moving up (*_c_u). Drag specified in [1]. Checks with the 3D
+% drag of a cup, from Hoerner p. 3-17 Fig. 32 b.
+%
+ Zwdot_c = 10000; %kg, Francois [1].
+ Zww_c_u = -1/2*rho*1.45*A_c; %kg/m
+%
+% Doors closed, moving down (*_c_d).
+ Zww_c_d = 1/2*rho*.8*A_c; %kg/m Francois [1]
+% Doors open, moving up (*_o_u).
+ Zwdot_o = 3000; %kg Francois [1].
+ Zww_o_u = -1/2*rho*1.2*A_c; %kg/m Francois [1].
+% Doors open, moving down (*_o_d).
+ Zww_o_d = 1/2*rho*.85*A_c; %kg/m Francois [1].
+%
+% For accel in the x direction (parallel to bottom plate), we will approximate
+% the heave cone as a rectangular solid with the same dimensions as the heave
+% cone. See Blevins p.325 #6 for a rectangular solid:
+ a = w_hc;
+ c = a;
+ b = h_hc;
+ alpha = .64*sqrt(b*c)/a;
+ Xudot_hc = alpha*rho*a*b*c; %kg
+ Xuabsu_hc = -1/2*rho*A_x*Cdp; %kg/m Flat plate perp to flow
+%
+ Yvdot_hc = Xudot_hc; %kg
+ Yvabsv_hc = Xuabsu_hc; %kg/m
+%
+% Translate inertias to pivot point:
+%
+%
+% Now build the generalized mass matrix, about the CG:
+%
+ M_hc = [ m_hc 0 0 0 cg_hc*m_hc 0;
+ 0 m_hc 0 -cg_hc*m_hc 0 0;
+ 0 0 m_hc 0 0 0;
+ 0 -cg_hc*m_hc 0 Ixx_hc Ixy_hc Ixz_hc;
+ cg_hc*m_hc 0 0 Ixy_hc Iyy_hc Iyz_hc;
+ 0 0 0 Ixz_hc Iyz_hc Izz_hc ];
+%
+% Transform it to the pivot point using Joan's generalized parallel axis theorem:
+%
+ MT_hc = parallelAxis( M_hc, [0 0 cg_hc]' );
+%
+% Added Mass Inertia:
+%
+% Approximate the HC as a thin circular disk with radius R.
+% The area of the hc is:
+%
+ A_hc = 2*sqrt(3)*(w_hc/2)^2;
+%
+% Find the radius of a circle with equal area:
+%
+ R = sqrt(A_hc/pi);
+%
+% Then for a thin circular disk (Blevins #1, p.325)
+
+ Kpdot_hc = .37*rho*R^5;
+ Mqdot_hc = Kpdot_hc;
+ Nrdot_hc = 80;
+%
+% And, here are the WAMIT results, with the doors closed. These are about the
+% center of symmetry. I'll assume this is also the center of mass of the HC alone:
+%
+ Xudot_hcw = .70*rho;
+ Yvdot_hcw = .70*rho;
+ Zwdot_hcw = 9.1*rho;
+ Kpdot_hcw = 2.8*rho;
+ Mqdot_hcw = 2.8*rho;
+ Nrdot_hcw = .08*rho;
+%
+% Build the generalized added mass matrix about the center of mass:
+%
+ MA_hcw= [ Xudot_hcw 0 0 0 0 0;
+ 0 Yvdot_hcw 0 0 0 0;
+ 0 0 Zwdot_hcw 0 0 0;
+ 0 0 0 Kpdot_hcw 0 0;
+ 0 0 0 0 Mqdot_hcw 0;
+ 0 0 0 0 0 Nrdot_hcw];
+%
+% Translate to the pivot point:
+%
+ MAT_hcw = parallelAxis( MA_hcw, [0 0 cg_hc]');
+
+% Drag Rotation:
+%
+% Compute the torque necessary to rotate the heave cone about its pivot
+% perpendicular to the stem. This is like swinging an umbrella by its
+% handle. I will superimpose the drag of two pieces; the edge-on cone, as we
+% have done before, and then a hexagonal plate rotating about its center line.
+%
+% The drag of the edge-on cone (tangential direction to the rotation) is
+%
+% D = -1/2 * rho * (hs_hc * q)^2 * Cdp * A_xc.
+%
+% M = D * hs_hc.
+%
+% where hs_hc is also the moment arm. So:
+%
+ Mqabsq_tang = -1/2*rho*hs_hc^3*Cdp*A_x;
+%
+% Now find the moment of an octagonal plate twirling about its centerline.
+% First, the half-plate above the centerline is a trapezoid with a long base
+% twice the length of the short base. See [1]. The height is such that this
+% trapezoid is composed of three equilateral triangles. The total width D of
+% the plate as a function of height h above the centerline is then
+%
+% D(h) = 2/sqrt(3) * ( 2*R - h ). (2)
+%
+% The moment of an infinitesimally thin strip parallel to the centerline is
+% then:
+%
+% dM = 1/2 * rho * (h*q)^2 * Cd * D(h) * dh * h
+%
+% where the final h is the moment arm. We'll take Cd to be similar to a flat
+% plate section. Then substituting (2) into the above,
+%
+% R
+% M = 1/2 * rho * Cd * q^2 * 2/sqrt(3) * integral (2*R*h^3 - h^4) * dh
+% 0
+% Peforming the integration, with R = w_hc/2, gives:
+%
+ Mqabsq_rot = -1/2*rho*sqrt(3)/5*(w_hc/2)^5*Cd_hc; %kg m^2
+%
+ fprintf('Mq|q| rotat [kg m^2]: %12.f \n', Mqabsq_rot );
+ fprintf('Mq|q| tang [kg m^2]: %12.f \n', Mqabsq_tang);
+ Mqabsq_hc = Mqabsq_rot + Mqabsq_tang; %kg m^2
+ Kpabsp_hc = Mqabsq_hc; %kg m^2
+
+% Approx area of panel:
+ A_p = (2.8/sqrt(3) -.2/sqrt(2))*.4; %m^2
+ A_pt = 6*A_p; %m^2 total area
+%
+% Approximate this one as a flywheel?
+%
+ Nrabsr_hc = -50; %kg m^2, arbitrary
+
+
+fprintf('\n** Buoy **\n\n');
+fprintf('Added masses are from WAMIT 10 cm above water plane.\n\n');
+
+fprintf('Xudot [kg]: %12.f \n',Xudot_bw);
+fprintf('Yvdot [kg]: %12.f \n',Yvdot_bw);
+fprintf('Zwdot [kg]: %12.f \n',Zwdot_bw);
+fprintf('Stability Derivatives below are taken at the water plane.\n\n');
+fprintf('Xu|u| [kg/m]: %12.f \n',Xuabsu_b);
+fprintf('Yv|v| [kg/m]: %12.f \n',Yvabsv_b);
+fprintf('This value is for downward motion.\n');
+fprintf('Zww [kg/m]: %12.f \n',Zww_b);
+fprintf('Kp|p| [kg m^2]: %12.f \n',Kpabsp_b);
+fprintf('Mq|q| [kg m^2]: %12.f \n',Mqabsq_b);
+fprintf('Nr|r| [kg m^2]: %12.f \n',Nrabsr_b);
+
+fprintf('Generalized Mass Matrix about Bridle Point:\n\n');
+fprintf('%12.f %12.f %12.f %12.f %12.f %12.f\n',MT_b');
+
+if( 0 )
+fprintf('Generalized Added Mass Matrix about Bridle Point:\n\n');
+%fprintf('%12.f %12.f %12.f %12.f %12.f %12.f\n',MAT_b');
+buoyAM = amText(MAT_b);
+for(i = 1:length(buoyAM))
+ disp(buoyAM(i))
+end
+
+end
+
+fprintf('WAMIT Generalized Added Mass Matrix about Bridle Point:\n\n');
+%fprintf('%12.f %12.f %12.f %12.f %12.f %12.f\n',MAT_b');
+buoyAMw = amText(MAT_bw);
+for(i = 1:length(buoyAMw))
+ disp(buoyAMw(i))
+end
+
+fprintf('\n** Power Take Off **\n\n');
+fprintf('Added masses below are about the c.g.\n\n');
+fprintf('Xudot [kg]: %12.f \n',Xudot_pto);
+fprintf('Yvdot [kg]: %12.f \n',Yvdot_pto);
+fprintf('Stability Derivatives below are about the pivot.\n\n');
+fprintf('Xu|u| [kg/m]: %12.f \n',Xuabsu_pto);
+fprintf('Yv|v| [kg/m]: %12.f \n',Yvabsv_pto);
+fprintf('Kp|p| [kg m^2]: %12.f \n',Kpabsp_pto);
+fprintf('Mq|q| [kg m^2]: %12.f \n',Mqabsq_pto);
+fprintf('Nr|r| [kg m^2]: %12.f \n',Nrabsr_pto);
+fprintf('Generalized Mass Matrix about pivot:\n\n');
+fprintf('%12.f %12.f %12.f %12.f %12.f %12.f\n',MT_pto');
+fprintf('Generalized Added Mass Matrix about pivot:\n\n');
+%fprintf('%12.f %12.f %12.f %12.f %12.f %12.f\n',MAT_b');
+ptoAM = amText(MAT_pto);
+for(i = 1:length(ptoAM))
+ disp(ptoAM(i))
+end
+
+
+fprintf('\n** Heave Cone **\n\n');
+fprintf('Doors Open::\n');
+fprintf('Zww, Moving Up: [kg/m]: %12.f \n',Zww_o_u);
+fprintf('Zww, Moving Down: [kg/m]: %12.f \n',Zww_o_d);
+fprintf('Zwdot [kg]: %12.f \n',Zwdot_o_d);
+fprintf('\n');
+fprintf('Doors Closed:\n');
+fprintf('Zww, Moving Up: [kg/m]: %12.f \n',Zww_c_u);
+fprintf('Zww, Moving Down: [kg/m]: %12.f \n',Zww_c_d);
+fprintf('Zwdot [kg]: %12.f \n',Zwdot_c_d);
+fprintf('\n');
+fprintf('Added masses below are about the c.g.\n\n');
+fprintf('Xudot (R,W) [kg]: %12.f, %12.f \n',Xudot_hc, Xudot_hcw);
+fprintf('Yvdot (R,W) [kg]: %12.f, %12.f \n',Yvdot_hc, Yvdot_hcw);
+fprintf('Xu|u| [kg/m]: %12.f \n',Xuabsu_hc);
+fprintf('Yv|v| [kg/m]: %12.f \n',Yvabsv_hc);
+fprintf('These are about the pivot:\n');
+fprintf('Kp|p| [kg m^2]: %12.f \n',Kpabsp_hc);
+fprintf('Mq|q| [kg m^2]: %12.f \n',Mqabsq_hc);
+fprintf('Nr|r| [kg m^2]: %12.f \n',Nrabsr_hc);
+fprintf('Generalized Mass Matrix about pivot:\n\n');
+fprintf('%12.f %12.f %12.f %12.f %12.f %12.f\n',MT_hc');
+fprintf('Generalized Added Mass Matrix about pivot:\n\n');
+hc_AM = amText(MAT_hcw);
+for(i = 1:length(hc_AM))
+ disp(hc_AM(i))
+end
+%
+% Skew-symmetric operator defined below. See Fossen 2.6 on p 8.
+%
+function M = S(x)
+ if(size(x) ~= [3 1])
+ fprintf('S(x) - Error. x must be 3x1.\n');
+ M = 0*eye(3);
+ return;
+ end
+ M = [ 0 -x(3) x(2);
+ x(3) 0 -x(1);
+ -x(2) x(1) 0 ];
+end
+%
+% Joan's parallel axis theorem:
+%
+function MT = parallelAxis(M, r)
+ if(size(M) ~= [6 6])
+ fprintf('Joan - Error. M must be 6x6.\n');
+ MT = 0*eye(6);
+ return
+ end
+ if(size(r) ~= [3 1])
+ fprintf('Joan - Error. r must be 3x1.\n');
+ MT = 0*eye(6);
+ return
+ end
+ M11 = M(1:3,1:3);
+ M12 = M(1:3,4:6);
+ M21 = M(4:6,1:3);
+ MT = [ 0*eye(3) -M11*S(r);
+ S(r)*M11 -S(r)*M11*S(r)+S(r)*M12-M21*S(r) ];
+ MT = MT + M;
+end
diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml
index 995acc04..daf117db 100644
--- a/docs/mkdocs.yml
+++ b/docs/mkdocs.yml
@@ -3,6 +3,7 @@ site_url: https://example.com/
nav:
- Home: index.md
- Architecture: architecture.md
+ - Buoy Control and Telemetry: ControlAndTelemetry.md
- ROS2 Interface: ros2.md
- Simulation: simulation.md
- At Sea Operation: atseaoperation.md
@@ -12,4 +13,10 @@ nav:
- License: license.md
- How to Cite: citation.md
+extra_javascript:
+ - https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js?config=TeX-AMS-MML_HTMLorMML
+
+markdown_extensions:
+ - mdx_math
+
theme: readthedocs
diff --git a/docs/requirements.txt b/docs/requirements.txt
index 016bb16d..5885f5e8 100644
--- a/docs/requirements.txt
+++ b/docs/requirements.txt
@@ -1 +1,2 @@
mkdocs
+python-markdown-math