Skip to content

Commit

Permalink
add support for pblog (#140)
Browse files Browse the repository at this point in the history
* add support for pblog

Signed-off-by: Michael Anderson <anderson@mbari.org>

* change default pblog root; add latest_rosbag symlink

Signed-off-by: Michael Anderson <anderson@mbari.org>

* Fixed issue by which wave-random seed wasn't being passed to Incident
wave generator

* Fix logging rates (#146)

* add sim-time-aware Rate to controllers for publishing

Signed-off-by: Michael Anderson <anderson@mbari.org>

* forgot shutdowns to stop hanging

Signed-off-by: Michael Anderson <anderson@mbari.org>

* add copyright

Signed-off-by: Michael Anderson <anderson@mbari.org>

* linters

Signed-off-by: Michael Anderson <anderson@mbari.org>

* add async proxy to await future for pack rate calls (#147)

Signed-off-by: Michael Anderson <anderson@mbari.org>

* use sim time from postupdate instead of imu time

Signed-off-by: Michael Anderson <anderson@mbari.org>

* enable use_sim_time for AHRS

Signed-off-by: Michael Anderson <anderson@mbari.org>

---------

Signed-off-by: Michael Anderson <anderson@mbari.org>

* linters

Signed-off-by: Michael Anderson <anderson@mbari.org>

* moved tf sensors to heavecone link; rotated imu to match physical

Signed-off-by: Michael Anderson <anderson@mbari.org>

* add gps

Signed-off-by: Michael Anderson <anderson@mbari.org>

---------

Signed-off-by: Michael Anderson <anderson@mbari.org>
Co-authored-by: Andrew Hamilton <hamilton@mbari.org>
  • Loading branch information
andermi and hamilton8415 authored May 29, 2023
1 parent 1d3c034 commit d572280
Show file tree
Hide file tree
Showing 15 changed files with 391 additions and 69 deletions.
2 changes: 1 addition & 1 deletion buoy_description/models/mbari_wec/model.sdf.em
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ except NameError:
try:
inc_wave_seed
except NameError:
inc_wave_seed = 42 # not defined so default
inc_wave_seed = 0 # not defined so default to 0 which changes seed every run

# Check if battery state (battery_soc or battery_emf) was passed in via empy
try:
Expand Down
45 changes: 28 additions & 17 deletions buoy_description/models/mbari_wec_base/model.sdf.em
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,15 @@ buoyancy_radius = ((3*buoyancy_disp)/(4*math.pi))**(1/3)
<always_on>1</always_on>
<visualize>true</visualize>
</sensor>
<sensor name='xbow_gps' type='navsat'>
<topic>Buoy_link/xbow_gps</topic>
<update_rate>50</update_rate>
<navsat>
<!-- add noise? -->
</navsat>
<always_on>1</always_on>
<visualize>true</visualize>
</sensor>
</link>

<link name="PTO">
Expand Down Expand Up @@ -483,6 +492,25 @@ buoyancy_radius = ((3*buoyancy_disp)/(4*math.pi))**(1/3)
</box>
</geometry>
</collision>
<sensor name='tf_imu' type='imu'>
<!-- Physical IMU rotated 90 with y/z horizontal -->
<pose>0.0 0.0 0.0 0.0 1.570796 0.0</pose>
<topic>HeaveCone_link/tf_imu</topic>
<update_rate>50</update_rate>
<imu>
<orientation_reference_frame>
<localization>ENU</localization>
</orientation_reference_frame>
</imu>
<always_on>1</always_on>
<visualize>true</visualize>
</sensor>
<sensor name='tf_mag' type='magnetometer'>
<topic>HeaveCone_link/tf_mag</topic>
<update_rate>50</update_rate>
<always_on>1</always_on>
<visualize>true</visualize>
</sensor>
</link>

<link name="Trefoil">
Expand Down Expand Up @@ -512,23 +540,6 @@ buoyancy_radius = ((3*buoyancy_disp)/(4*math.pi))**(1/3)
<specular>0.1 0.1 .1 1</specular>
</material>
</visual>
<sensor name='trefoil_imu' type='imu'>
<topic>Trefoil_link/trefoil_imu</topic>
<update_rate>50</update_rate>
<imu>
<orientation_reference_frame>
<localization>ENU</localization>
</orientation_reference_frame>
</imu>
<always_on>1</always_on>
<visualize>true</visualize>
</sensor>
<sensor name='trefoil_mag' type='magnetometer'>
<topic>Trefoil_link/trefoil_mag</topic>
<update_rate>50</update_rate>
<always_on>1</always_on>
<visualize>true</visualize>
</sensor>
</link>

<joint name="Universal" type="universal">
Expand Down
5 changes: 5 additions & 0 deletions buoy_gazebo/gazebo/server.config
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@
filename="gz-sim-imu-system"
name="gz::sim::systems::Imu">
</plugin>
<plugin entity_name="*"
entity_type="world"
filename="gz-sim-navsat-system"
name="gz::sim::systems::NavSat">
</plugin>
<plugin entity_name="*"
entity_type="world"
filename="gz-sim-magnetometer-system"
Expand Down
22 changes: 22 additions & 0 deletions buoy_gazebo/launch/mbari_wec.launch.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,19 @@ def generate_launch_description():
description='regenerate template models using defaults'
)

pblog_loghome_launch_arg = DeclareLaunchArgument(
'pbloghome', default_value=['~/.pblogs'],
description='root pblog directory'
)

pblog_logdir_launch_arg = DeclareLaunchArgument(
'pblogdir', default_value=[''],
description='specific pblog directory in pbloghome'
)

pkg_ros_gz_sim = get_package_share_directory('ros_gz_sim')
pkg_buoy_gazebo = get_package_share_directory('buoy_gazebo')
pkg_pblog = get_package_share_directory('sim_pblog')
pkg_buoy_description = get_package_share_directory('buoy_description')
model_dir = 'mbari_wec_ros'
model_name = 'MBARI_WEC_ROS'
Expand Down Expand Up @@ -137,6 +148,14 @@ def generate_launch_description():
output='screen'
)

pblog = IncludeLaunchDescription(
PythonLaunchDescriptionSource(
os.path.join(pkg_pblog, 'launch', 'sim_pblog.launch.py'),
),
launch_arguments={'loghome': LaunchConfiguration('pbloghome'),
'logdir': LaunchConfiguration('pblogdir')}.items(),
)

# Get the parser plugin convert sdf to urdf using robot_description topic
robot_state_publisher = Node(
package='robot_state_publisher',
Expand All @@ -162,12 +181,15 @@ def generate_launch_description():

dependent_nodes = [gazebo,
bridge,
pblog,
robot_state_publisher,
rviz]

return LaunchDescription([
gazebo_world_file_launch_arg,
gazebo_world_name_launch_arg,
pblog_loghome_launch_arg,
pblog_logdir_launch_arg,
rviz_launch_arg,
gazebo_debugger_arg,
extra_gz_args,
Expand Down
1 change: 1 addition & 0 deletions buoy_gazebo/package.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

<depend>buoy_description</depend>
<depend>buoy_interfaces</depend>
<depend>sim_pblog</depend>
<depend>gz-sim7</depend>
<depend>rclcpp</depend>
<depend>robot_state_publisher</depend>
Expand Down
21 changes: 15 additions & 6 deletions buoy_gazebo/scripts/mbari_wec_batch
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,7 @@ def generate_simulations(sim_params_yaml):
os.path.join(batch_results_dir, 'batch_runs.log'))
with open(os.path.join(batch_results_dir, 'batch_runs.log'), 'w') as fd:
fd.write(f'# Generated {len(batch_params)} simulation runs\n')
fd.write('RunIndex, SimReturnCode, StartTime, rosbag2FileName' +
fd.write('RunIndex, SimReturnCode, StartTime, rosbag2Filename, pblogFilename' +
', PhysicsStep, PhysicsRTF' +
', Seed, Duration, DoorState, ScaleFactor, BatteryState' +
', MeanPistonPosition, IncWaveSpectrumType;IncWaveSpectrumParams\n')
Expand Down Expand Up @@ -446,11 +446,17 @@ def generate_simulations(sim_params_yaml):

# Dynamically create launch file
start_time = time.strftime("%Y%m%d%H%M%S")
rosbag2_name = 'rosbag2'
rosbag2_dir = 'rosbag2'
pblog_dir = 'pblog'
run_results_dir = f'results_run_{idx}_{start_time}'
# TODO(anyone) also path for pblog when ready
os.makedirs(os.path.join(batch_results_dir, run_results_dir))

# python workaround for 'ln -sf'
os.symlink(os.path.join(run_results_dir, rosbag2_dir),
os.path.join(batch_results_dir, f'latest_rosbag_{start_time}'), target_is_directory=True)
os.replace(os.path.join(batch_results_dir, f'latest_rosbag_{start_time}'),
os.path.join(batch_results_dir, f'latest_rosbag'))

def generate_launch_description():
mbari_wec = IncludeLaunchDescription(
PythonLaunchDescriptionSource(
Expand All @@ -459,13 +465,15 @@ def generate_simulations(sim_params_yaml):
launch_arguments={'extra_gz_args': '-r' if enable_gui else '-rs' +
f' --iterations {iterations}',
'world_file': 'mbari_wec_batch.sdf',
'regenerate_models': 'false'}.items(),
'regenerate_models': 'false',
'pbloghome': batch_results_dir,
'pblogdir': os.path.join(run_results_dir, pblog_dir)}.items(),
)

# record all topics with rosbag2
rosbag2 = ExecuteProcess(
cmd=['ros2', 'bag', 'record',
'-o', os.path.join(batch_results_dir, run_results_dir, rosbag2_name), '-a'],
'-o', os.path.join(batch_results_dir, run_results_dir, rosbag2_dir), '-a'],
output='screen'
)

Expand All @@ -484,7 +492,8 @@ def generate_simulations(sim_params_yaml):
# Write to log
with open(os.path.join(batch_results_dir, 'batch_runs.log'), 'a') as fd:
fd.write(f'{idx}, {result}, {start_time}' +
f', {os.path.join(run_results_dir, rosbag2_name)}' +
f', {os.path.join(run_results_dir, rosbag2_dir)}' +
f', {os.path.join(run_results_dir, pblog_dir)}' +
f', {print_optional(ps)}, {print_optional(physics_rtf)}' +
f', {print_optional(seed)}, {duration}, {ds}, {sf}' +
f', {print_optional(bs)}' +
Expand Down
5 changes: 5 additions & 0 deletions buoy_gazebo/src/IncidentWaves/IncidentWaves.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,11 @@ void IncidentWaves::Configure(
return;
}

double seed = SdfParamDouble(_sdf, "IncWaveSeed", 0.0);
this->dataPtr->Inc->SetSeed(seed);

auto linkName = _sdf->Get<std::string>("LinkName");

auto SpectrumType = _sdf->Get<std::string>("IncWaveSpectrumType");

// double beta = SdfParamDouble(_sdf, "WaveDir", 180.0); // Not yet implemented
Expand Down
111 changes: 111 additions & 0 deletions buoy_gazebo/src/buoy_utils/Rate.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
// Copyright 2022 Open Source Robotics Foundation, Inc. and Monterey Bay Aquarium Research Institute
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef BUOY_UTILS__RATE_HPP_
#define BUOY_UTILS__RATE_HPP_


#include <chrono>

#include <rclcpp/macros.hpp>
#include <rclcpp/rate.hpp>


namespace buoy_utils
{

using std::chrono::duration;
using std::chrono::duration_cast;
using std::chrono::nanoseconds;

class SimRate : public rclcpp::RateBase
{
public:
RCLCPP_SMART_PTR_DEFINITIONS(SimRate);

explicit SimRate(const double & rate, rclcpp::Clock::SharedPtr _clock)
: SimRate(
duration_cast<nanoseconds>(duration<double>(1.0 / rate)),
_clock
)
{}

explicit SimRate(
const std::chrono::nanoseconds & period,
rclcpp::Clock::SharedPtr _clock)
: clock(_clock),
period_(period),
last_interval_(
rclcpp::Time(_clock->now(),
_clock->get_clock_type())
)
{}

virtual bool sleep()
{
// Time coming into sleep
auto now = clock->now();
// Time of next interval
auto next_interval = last_interval_ + period_;
// Detect backwards time flow
if (now < last_interval_) {
// Best thing to do is to set the next_interval to now + period
next_interval = now + period_;
}
// Calculate the time to sleep
auto time_to_sleep = next_interval - now;
// Update the interval
last_interval_ += period_;
// If the time_to_sleep is negative or zero, don't sleep
if (time_to_sleep <= rclcpp::Duration(0, 0U)) {
// If an entire cycle was missed then reset next interval.
// This might happen if the loop took more than a cycle.
// Or if time jumps forward.
if (now > next_interval + period_) {
last_interval_ = now + period_;
}
// Either way do not sleep and return false
return false;
}
// Sleep (will get interrupted by ctrl-c, may not sleep full time)
clock->sleep_for(time_to_sleep);
return true;
}

virtual bool is_steady() const
{
return false;
}

virtual void reset()
{
last_interval_ = clock->now();
}

rclcpp::Duration period() const
{
return period_;
}

private:
RCLCPP_DISABLE_COPY(SimRate)

rclcpp::Clock::SharedPtr clock = nullptr;
rclcpp::Duration period_;
rclcpp::Time last_interval_;
};

} // namespace buoy_utils

#endif // BUOY_UTILS__RATE_HPP_
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,11 @@

#include <buoy_interfaces/msg/bc_record.hpp>

#include "buoy_utils/Rate.hpp"
#include "ElectroHydraulicPTO/BatteryState.hpp"
#include "BatteryController.hpp"


using namespace std::chrono_literals;

namespace buoy_gazebo
Expand All @@ -48,7 +50,7 @@ struct BatteryControllerROS2
bool use_sim_time_{true};

rclcpp::Publisher<buoy_interfaces::msg::BCRecord>::SharedPtr bc_pub_{nullptr};
std::unique_ptr<rclcpp::Rate> pub_rate_{nullptr};
std::unique_ptr<buoy_utils::SimRate> pub_rate_{nullptr};
buoy_interfaces::msg::BCRecord bc_record_;
double pub_rate_hz_{10.0};
};
Expand Down Expand Up @@ -122,7 +124,9 @@ struct BatteryControllerPrivate
std::unique_lock next(next_access_mutex_);
std::unique_lock data(data_mutex_);
next.unlock();
ros_->pub_rate_ = std::make_unique<rclcpp::Rate>(ros_->pub_rate_hz_);
ros_->pub_rate_ = std::make_unique<buoy_utils::SimRate>(
ros_->pub_rate_hz_,
ros_->node_->get_clock());
data.unlock();
}
}
Expand Down Expand Up @@ -155,6 +159,10 @@ BatteryController::BatteryController()
BatteryController::~BatteryController()
{
// Stop ros2 threads
if (rclcpp::ok()) {
rclcpp::shutdown();
}

this->dataPtr->stop_ = true;
if (this->dataPtr->ros_->executor_) {
this->dataPtr->ros_->executor_->cancel();
Expand Down
Loading

0 comments on commit d572280

Please sign in to comment.