Skip to content

Conversation

@eirisak
Copy link

@eirisak eirisak commented Jan 8, 2026

Added service node:
operation_mode_manager.cpp

Changed joystick interface to make use of the manager

Added Operation mode service request type, aswell as message type to use for the operation mode topic

Changed various dp controls to accomodate these changes.

Added operation mode manager to orca.launch.py

Also added operation mode to stonefish_sim in this pull request:
vortexntnu/vortex-stonefish-sim#18

@eirisak eirisak self-assigned this Jan 8, 2026
@eirisak eirisak linked an issue Jan 8, 2026 that may be closed by this pull request
3 tasks
Copy link
Contributor

Choose a reason for hiding this comment

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

These files should probably not be a part of this PR, as they are part of a separate PR?

Comment on lines 43 to 69
void declare_parameters()
{
this->declare_parameter<std::string>("topics.wrench_input", "");
this->declare_parameter<std::string>("topics.killswitch", "");
this->declare_parameter<std::string>("topics.operation_mode", "");

wrench_input_topic_ =
this->get_parameter("topics.wrench_input").as_string();
killswitch_topic_ =
this->get_parameter("topics.killswitch").as_string();
operation_mode_topic_ =
this->get_parameter("topics.operation_mode").as_string();
}

void setup_publishers()
{
wrench_pub_ =
this->create_publisher<geometry_msgs::msg::WrenchStamped>(
wrench_input_topic_, rclcpp::SensorDataQoS());

killswitch_pub_ =
this->create_publisher<std_msgs::msg::Bool>(
killswitch_topic_, rclcpp::QoS(2).reliable());

mode_pub_ =
this->create_publisher<vortex_msgs::msg::OperationMode>(
operation_mode_topic_, rclcpp::QoS(2).reliable());
Copy link
Contributor

Choose a reason for hiding this comment

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

Instead of keeping the topics as member variables I would just get them in the setup_publishers method

    void declare_parameters()
    {
      this->declare_parameter<std::string>("topics.wrench_input");
      this->declare_parameter<std::string>("topics.killswitch");
      this->declare_parameter<std::string>("topics.operation_mode");
    }

    void setup_publishers()
    {
      const auto wrench_input_topic =
        this->get_parameter("topics.wrench_input").as_string();
      const auto killswitch_topic =
        this->get_parameter("topics.killswitch").as_string();
      const auto operation_mode_topic =
        this->get_parameter("topics.operation_mode").as_string();

      wrench_pub_ =
        this->create_publisher<geometry_msgs::msg::WrenchStamped>(
          wrench_input_topic, rclcpp::SensorDataQoS());

      killswitch_pub_ =
        this->create_publisher<std_msgs::msg::Bool>(
          killswitch_topic, rclcpp::QoS(2).reliable());

      mode_pub_ =
        this->create_publisher<vortex_msgs::msg::OperationMode>(
          operation_mode_topic, rclcpp::QoS(2).reliable());
...

Also, there are some QoS definitions in vortex utils ros 👍

Copy link
Contributor

@jorgenfj jorgenfj left a comment

Choose a reason for hiding this comment

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

First round of review.

Consider splitting into header and source file, and move declarations into the header file.

Also use spdlog for logging instead of rclcpp. Spdlog gives more readable timestamps. You can look at the dp_adapt_backs_controller package for how to import and use spdlog.


void declare_parameters()
{
this->declare_parameter<std::string>("topics.wrench_input", "");
Copy link
Contributor

Choose a reason for hiding this comment

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

Should avoid using default values for ros parameters

Comment on lines 27 to 29
std::string wrench_input_topic_;
std::string killswitch_topic_;
std::string operation_mode_topic_;
Copy link
Contributor

Choose a reason for hiding this comment

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

These should not be member varaibles since they are only used once

Comment on lines 15 to 16
killswitch_(true),
mode_(vortex_msgs::srv::OperationModeSRV::Request::MANUAL)
Copy link
Contributor

Choose a reason for hiding this comment

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

Can these values be set from ros parameters and retrieved from the config file in this package?

Comment on lines 71 to 79
// Initial killswitch = true
std_msgs::msg::Bool msg;
msg.data = true;
killswitch_pub_->publish(msg);

// Initial mode = MANUAL
vortex_msgs::msg::OperationMode mode_msg;
mode_msg.mode = vortex_msgs::srv::OperationModeSRV::Request::MANUAL;
mode_pub_->publish(mode_msg);
Copy link
Contributor

Choose a reason for hiding this comment

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

This should read from the member variables

Comment on lines 147 to 155
// Publish killswitch status
std_msgs::msg::Bool killswitch_msg;
killswitch_msg.data = killswitch_;
killswitch_pub_->publish(killswitch_msg);

// Publish operation mode
vortex_msgs::msg::OperationMode mode_msg;
mode_msg.mode = mode_;
mode_pub_->publish(mode_msg);
Copy link
Contributor

Choose a reason for hiding this comment

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

make these helper functions

Comment on lines 63 to 73
output="screen",
output="screen",killswitch
Copy link
Contributor

Choose a reason for hiding this comment

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

What is this?

Comment on lines -93 to +94
std::string software_mode_{};
uint8_t software_mode_{};
Copy link
Contributor

Choose a reason for hiding this comment

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

To make mode more strongly typed I would consider making an enum class for it, and make a convertion which can be used in the callback. Something like

enum class Mode : uint8_t {manual, autonomous, reference};

// Mode type instead of raw uint8
Mode software_mode_{};

// Free function (not part of the node class)
Mode convert_from_ros(const vortex_msgs::msg::OperationMode& mode_msg) {
    switch (mode_msg.mode) {
        case vortex_msgs::msg::OperationMode::MANUAL:
            return Mode::manual;
        case vortex_msgs::msg::OperationMode::AUTONOMOUS:
            return Mode::autonomous;
        case vortex_msgs::msg::OperationMode::REFERENCE:
            return Mode::reference;
    }
    assert(false && "Unknown operation mode");
}

// Callback
void DPAdaptBacksControllerNode::software_mode_callback(
    const vortex_msgs::msg::OperationMode::SharedPtr msg) {
    software_mode_ = convert_from_ros(*msg);
    // Either A) make a to_string helper function or B) use magic_enum to convert enum to string
    spdlog::info("Software mode: {}", magic_enum::enum_name(software_mode_));

    if (software_mode_ == Mode::autonomous || software_mode_ == Mode::reference) {
        pose_d_ = pose_;
    }
}

Note the part about printing enum name. This feedback goes for other places in the code as well where mode is just stored as a raw integer

Comment on lines +35 to +43
self.operation_mode_client = self.create_client(OperationModeSRV, 'set_operation_mode')

while not self.operation_mode_client.wait_for_service(timeout_sec=1.0):
self.get_logger().info('Operation Mode service not available, waiting...')

self.toggle_killswitch_client = self.create_client(ToggleKillswitch, 'toggle_killswitch')

while not self.toggle_killswitch_client.wait_for_service(timeout_sec=1.0):
self.get_logger().info('Toggle Killswitch service not available, waiting...')
Copy link
Contributor

Choose a reason for hiding this comment

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

make a set_services (to keep the naming consistent). Alternatively find a more fitting prefix than "set" for both that and self.set_publishers_and_subscribers()

Comment on lines +9 to 10
modes = {OperationMode.AUTONOMOUS:"Autonomous", OperationMode.MANUAL:"Manual", OperationMode.REFERENCE:"Reference"}

Copy link
Contributor

Choose a reason for hiding this comment

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

Better to rely on Enum here than dictionary + string

Comment on lines +48 to +49
self._killswitch = 0
self._mode = 0
Copy link
Contributor

Choose a reason for hiding this comment

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

use bool for killswitch, and would advise use the enum (see comment in utils, and the comment in dp controller) for mode

Comment on lines +41 to +42
wrench_input_topic, rclcpp::SensorDataQoS());

Copy link
Contributor

Choose a reason for hiding this comment

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

sensor_data_profile in vortex_utils_ros?

Comment on lines +67 to +71
[this](
const std::shared_ptr<vortex_msgs::srv::ToggleKillswitch::Request> request,
std::shared_ptr<vortex_msgs::srv::ToggleKillswitch::Response> response)
{
(void)request;
Copy link
Contributor

Choose a reason for hiding this comment

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

prefer

      const std::shared_ptr<vortex_msgs::srv::ToggleKillswitch::Request> /*request*/,
      std::shared_ptr<vortex_msgs::srv::ToggleKillswitch::Response> response

when not using a parameter, instead of (void).... Alternatively follow F.9

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[TASK] Operation Mode Manager

5 participants