Skip to content

Linear Velocity Plugin Tutorial #2911

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 29 commits into
base: gz-sim9
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
5723fa5
Add files via upload
Pk-Sic May 18, 2025
44ca1bb
Merge branch 'gz-sim9' into gz-sim9
Pk-Sic May 20, 2025
fb312da
Update examples/plugin/velocity_plugin/PluginLinearVelocity.cc
Pk-Sic May 21, 2025
1bac297
Update examples/plugin/velocity_plugin/PluginLinearVelocity.cc
Pk-Sic May 21, 2025
a02af81
Update examples/plugin/velocity_plugin/PluginLinearVelocity.cc
Pk-Sic May 21, 2025
ccd5634
Update examples/plugin/velocity_plugin/PluginLinearVelocity.hh
Pk-Sic May 21, 2025
395d65c
Update examples/plugin/velocity_plugin/PluginLinearVelocity.cc
Pk-Sic May 21, 2025
c288f97
Update examples/plugin/velocity_plugin/PluginLinearVelocity.cc
Pk-Sic May 21, 2025
6843a9f
Update examples/plugin/velocity_plugin/PluginLinearVelocity.cc
Pk-Sic May 21, 2025
2c633d4
Update PluginLinearVelocity.cc
Pk-Sic May 22, 2025
e9922e5
Update velocity_world_plugin.sdf
Pk-Sic May 22, 2025
ffb4098
Update PluginLinearVelocity.hh
Pk-Sic May 22, 2025
56590f6
Update PluginLinearVelocity.cc
Pk-Sic May 22, 2025
36af72c
Update CMakeLists.txt
Pk-Sic May 22, 2025
a375678
Update examples/plugin/velocity_plugin/README.md
Pk-Sic May 25, 2025
f5cf4ff
Update examples/plugin/velocity_plugin/README.md
Pk-Sic May 25, 2025
cce296c
Update examples/plugin/velocity_plugin/README.md
Pk-Sic May 25, 2025
e7d5ccf
Update PluginLinearVelocity.cc
Pk-Sic May 25, 2025
6113ded
Update PluginLinearVelocity.hh
Pk-Sic May 25, 2025
a0495d4
Update velocity_world_plugin.sdf
Pk-Sic May 25, 2025
216515c
Update PluginLinearVelocity.cc
Pk-Sic May 28, 2025
8fc0a83
Update PluginLinearVelocity.cc
Pk-Sic May 28, 2025
ae46bf2
Update velocity_world_plugin.sdf
Pk-Sic May 28, 2025
3a5438e
Update examples/plugin/velocity_plugin/CMakeLists.txt
Pk-Sic May 31, 2025
38ba3a3
Update examples/plugin/velocity_plugin/CMakeLists.txt
Pk-Sic May 31, 2025
c4e5391
Update examples/plugin/velocity_plugin/CMakeLists.txt
Pk-Sic May 31, 2025
c0697ef
Update examples/plugin/velocity_plugin/CMakeLists.txt
Pk-Sic May 31, 2025
1a692ef
Update examples/plugin/velocity_plugin/CMakeLists.txt
Pk-Sic May 31, 2025
c28c39f
Update examples/plugin/velocity_plugin/CMakeLists.txt
Pk-Sic May 31, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions examples/plugin/velocity_plugin/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
cmake_minimum_required(VERSION 3.22.1 FATAL_ERROR)

find_package(gz-cmake3 REQUIRED)

project(Plugin_Linear_Velocity)

gz_find_package(gz-plugin2 REQUIRED COMPONENTS register)
set(GZ_PLUGIN_VER ${gz-plugin2_VERSION_MAJOR})

gz_find_package(gz-sim8 REQUIRED)
set(GZ_SIM_VER ${gz-sim8_VERSION_MAJOR})

add_library(PluginLinearVelocity SHARED PluginLinearVelocity.cc)

set_property(TARGET PluginLinearVelocity PROPERTY CXX_STANDARD 17)
target_link_libraries(PluginLinearVelocity
PRIVATE gz-plugin${GZ_PLUGIN_VER}::gz-plugin${GZ_PLUGIN_VER}
PRIVATE gz-sim${GZ_SIM_VER}::gz-sim${GZ_SIM_VER})

106 changes: 106 additions & 0 deletions examples/plugin/velocity_plugin/PluginLinearVelocity.cc
Copy link
Contributor

Choose a reason for hiding this comment

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

style nit: can you wrap the lines to 80 char in the .cc and .hh files?

Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/*
* Copyright (C) 2025 Open Source Robotics Foundation
*
* 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.
*
*/

#include <string>
#include <iostream>
#include <memory>

#include <gz/common/Console.hh>
#include <gz/plugin/Register.hh>
#include <gz/sim/Link.hh>
#include <gz/sim/Model.hh>
#include <gz/sim/Types.hh>
#include <gz/sim/Util.hh>

// This header is required to register plugins.
// The good practice suggests to recall it in the ".cc" file
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this comment referring to the <gz/plugin/Register.hh> header?


#include <gz/sim/components/Pose.hh>
#include <gz/math/Vector3.hh>

// The next row recalls the plugin's header.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
// The next row recalls the plugin's header.
// The next row includes the plugin's header.


#include "PluginLinearVelocity.hh"

// This is required to register the plugin.
// NOTE: The interfaces shall match what's in the plugin's header (see line 42 to 44).

GZ_ADD_PLUGIN(
plugin_velocity::PluginLinearVelocity,
gz::sim::System,
plugin_velocity::PluginLinearVelocity::ISystemConfigure,
plugin_velocity::PluginLinearVelocity::ISystemPreUpdate)


using namespace plugin_velocity;

// In the next section, all the functions that we need are recalled.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
// In the next section, all the functions that we need are recalled.
// In the next section, all the functions that we need are defined.

// Since the plugin's header (see PluginLinearVelocity.hh file) is used as "function declaration",
// in the following section the core purpose of our plugin will be defined.

// For this plugin I decided to use the "Configure function" to read the field in the .sdf file
// as e.g. the link_name field. Let's dive into the details, analyzing step-by-step the following code.


void plugin_velocity::PluginLinearVelocity::Configure(const gz::sim::Entity &_identity,
const std::shared_ptr<const sdf::Element> &_sdf,
gz::sim::EntityComponentManager &_ecm,
gz::sim::EventManager &_eventMgr)
{
// STEP1) Read property from SDF.
// In this case, I call it "link_name" (see line 71 in the velocity_world_plugin.sdf file)

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

// STEP 2) Store the lName variable the value of the "link_name"

this -> lName = linkName; // Do not forget to declare the lName variable in the plugin's header file (see line 61 in the PluginLinearVelocity.hh file))
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
this -> lName = linkName; // Do not forget to declare the lName variable in the plugin's header file (see line 61 in the PluginLinearVelocity.hh file))
this->lName = linkName; // Do not forget to declare the lName variable in the plugin's header file (see line 61 in the PluginLinearVelocity.hh file))


// Store the _identity value using the "this ->".
Copy link
Contributor

Choose a reason for hiding this comment

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

nit:

Suggested change
// Store the _identity value using the "this ->".
// Store the _identity value in "this->entity" member variable


this -> entity = _identity;
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
this -> entity = _identity;
this->entity = _identity;


// Create the model object to access all the function using as attibute the "entity" variable.
// The function "Model()" enables to get some important details
Comment on lines +77 to +78
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we can simplify this to:

Suggested change
// Create the model object to access all the function using as attibute the "entity" variable.
// The function "Model()" enables to get some important details
// Create a Model object from the "entity" to access all model-related functions


auto model = gz::sim::Model(entity);

// Look for link entity using "LinkByName" into "model" defined above.

this -> linkEntity = model.LinkByName(_ecm, linkName);
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
this -> linkEntity = model.LinkByName(_ecm, linkName);
this->linkEntity = model.LinkByName(_ecm, linkName);

}


void PluginLinearVelocity::PreUpdate(const gz::sim::UpdateInfo &_info,
gz::sim::EntityComponentManager &_ecm)
{

// Define the linear velocity vector using.

gz::math::Vector3d lVel(1,0,0);

// Create an object using the "Link" class.

gz::sim::Link link_n(linkEntity);

// The next row is the main command wich applies the linear velocity vector "lVel" on the link entity.
// For this example we are applying the linear velocity on a simple box that we defined in the sdf file (see line 34 in the velocity_world_plugin.sdf file)

link_n.SetLinearVelocity(_ecm,lVel);
}

// end
65 changes: 65 additions & 0 deletions examples/plugin/velocity_plugin/PluginLinearVelocity.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
Copyright 2025 Open Source Robotics Foundation

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 SYSTEM_PLUGIN_HELLOWORLD_HH_
Copy link
Contributor

Choose a reason for hiding this comment

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

add License header

Copy link
Author

Choose a reason for hiding this comment

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

There is the 2025 license header. Is this wrong? I used the http://www.apache.org/licenses/LICENSE-2.0

#define SYSTEM_PLUGIN_HELLOWORLD_HH_


#include <gz/sim/System.hh>
#include <gz/sim/Model.hh>
#include <gz/sim/Util.hh>
#include <gz/math/Vector3.hh>


// When a plugin's header file is coded, it is a good practice to define a customized namespace.
// In this case we call it "plugin_plugin_velocity".
Copy link
Contributor

Choose a reason for hiding this comment

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

I think there is an extra plugin_ here?

Suggested change
// In this case we call it "plugin_plugin_velocity".
// In this case we call it "plugin_velocity".


namespace plugin_velocity
{

// Under our customized namespace we define and recall all the functions and variables that we need.

// Since our objective is to:
// - Read property from the .sdf file
// - Send the LinearVelovity command to a link entity

// Here we have to use "ISystemConfigure" and "ISystemPreUpdate".

class PluginLinearVelocity:
public gz::sim::System,
public gz::sim::ISystemConfigure,
public gz::sim::ISystemPreUpdate
{
// The PreUpdate callback must be imported by the plugins that are inheriting ISystemPreUpdate.
// Since its nature, the PreUpdate callback is called every simulation iteration before the physics updates the world.
// On the other hand the Configure callback is called only once.

public: void Configure(const gz::sim::Entity &_entity,
const std::shared_ptr<const sdf::Element> &sdf,
gz::sim::EntityComponentManager &_ecm,
gz::sim::EventManager &_eventMgr)override;

public: void PreUpdate(const gz::sim::UpdateInfo &_info,
gz::sim::EntityComponentManager &_ecm) override;

private:
gz::sim::Entity linkEntity;
gz::sim::Entity entity;
std::string lName;
};
}

#endif
39 changes: 39 additions & 0 deletions examples/plugin/velocity_plugin/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Velocity World

This example shows how to set a velocity command on a link.
This example will set the velocity command on a stand-alone link but the same approach can be applied for more complex robots.

In particular, in the world there is a box that is free to move on a ground plane.
The plugin presented will apply a linear speed of 1 m/s along the x-axis.

## Build

From the root of the `gz-sim` repository, do the following to build the example:

~~~
cd gz-sim/examples/plugins/velocity_plugin
mkdir build
cd build
cmake ..
make
~~~

This will generate the `PluginLinearVelocity` library under `build`.

## Run

The plugin must be attached to an entity to be loaded.
This is demonstrated in the `velocity_world_plugin.sdf`.

Before starting Gazebo, we must make sure it can find the plugin by doing:

~~~
cd gz-sim/examples/plugins/velocity_plugin
export GZ_SIM_SYSTEM_PLUGIN_PATH=`pwd`/build
~~~

Then load the example world:

gz sim -v 3 velocity_world_plugin.sdf

Once Gazebo is opened, toggle the `play/pause` buttons to see the box moving along a linear path.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
Once Gazebo is opened, toggle the `play/pause` buttons to see the box moving along a linear path.
Once Gazebo is opened, toggle the `play/pause` button to see the box moving along a linear path.

76 changes: 76 additions & 0 deletions examples/plugin/velocity_plugin/velocity_world_plugin.sdf
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<?xml version="1.0" encoding="UTF-8"?>
<sdf version="1.6">
<world name="default">
<model name="ground_plane">
<pose relative_to="world">0 0 0 0 0 0</pose>
<static>true</static>
<link name="ground">
<collision name="ground">
<geometry>
<plane>
<normal>0 0 1</normal>
</plane>
</geometry>
</collision>
<visual name="ground">
<geometry>
<plane>
<normal>0 0 1</normal>
<size>100 100</size>
</plane>
</geometry>
<material>
<ambient>0.8 0.8 0.8 1</ambient>
<diffuse>0.8 0.8 0.8 1</diffuse>
<specular>0.8 0.8 0.8 1</specular>
</material>
</visual>
</link>
</model>
<model name="model_name">
<pose relative_to="world">0 0 0.1 0 0 0</pose>
<static>false</static>
<!--Here we create a Link called "box"-->
<link name="box">
<!--Visual section-->
<inertial>
<!--inertial properties of the link mass, inertia matix-->
<mass>1.14395</mass>
<inertia>
<ixx>0.095329</ixx>
<ixy>0</ixy>
<ixz>0</ixz>
<iyy>0.381317</iyy>
<iyz>0</iyz>
<izz>0.476646</izz>
</inertia>
</inertial>
<visual name="visual">
<geometry>
<box>
<size>0.5 0.5 0.2</size>
</box>
</geometry>
<!--let's add color to our link-->
<material>
<ambient>0.0 0.0 1.0 1</ambient>
<diffuse>0.0 0.0 1.0 1</diffuse>
<specular>0.0 0.0 1.0 1</specular>
</material>
</visual>
<!--Collision section-->
<collision name="collision_box">
<geometry>
<box>
<size>0.5 0.5 0.2</size>
</box>
</geometry>
</collision>
</link>
<plugin filename="PluginLinearVelocity" name="plugin_velocity::PluginLinearVelocity">
<link_name>box</link_name>
<!--Make sure to insert the smae name given to the link (i.a.w. see line 39)-->
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
<!--Make sure to insert the smae name given to the link (i.a.w. see line 39)-->
<!--Make sure to insert the same name given to the link (i.a.w. see line 34)-->

</plugin>
</model>
</world>
</sdf>