Skip to content

Commit

Permalink
Add extensions for IssacSim targetting Space ROS
Browse files Browse the repository at this point in the history
Related to space-ros#18

 - Add new extension - Rover Simple Controller
 - Add example omnigraph extension - Negate Number
  • Loading branch information
franklinselva committed Sep 9, 2024
1 parent 4e29501 commit ff93198
Show file tree
Hide file tree
Showing 20 changed files with 319 additions and 0 deletions.
36 changes: 36 additions & 0 deletions extensions/omni.new.extension/config/extension.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@

[package]
# Semantic Versioning is used: https://semver.org/
version = "0.1.0"

# Lists people or organizations that are considered the "authors" of the package.
authors = []

# The title and description fields are primarly for displaying extension info in UI
title = "Omniverse Graph Extension Example"
description="Example extension for OmniGraph nodes."

# Path (relative to the root) or content of readme markdown file for UI.
readme = "docs/README.md"

# URL of the extension source repository.
repository="https://gitlab-master.nvidia.com/omniverse/kit-extensions/example"

# Categories for UI.
category = "Example"

# Keywords for the extension
keywords = ["kit", "omnigraph"]

# Watch the .ogn files for hot reloading (only works for Python files)
[fswatcher.patterns]
include = ["*.ogn", "*.py"]
exclude = ["Ogn*Database.py"]

[dependencies]
"omni.kit.test" = {}
"omni.graph" = {}

# Main python module this extension provides, it will be publicly available as "import omni.new.extension".
[[python.module]]
name = "omni.new.extension"
4 changes: 4 additions & 0 deletions extensions/omni.new.extension/docs/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
### 0.1.0

- Initial release of Omni New Extension
- Added simple steer and move based controller
3 changes: 3 additions & 0 deletions extensions/omni.new.extension/docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@

# OmniGraph Extension [omni.new.extension]
Extension with implementation of some OmniGraph nodes
14 changes: 14 additions & 0 deletions extensions/omni.new.extension/omni/new/extension/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@

import omni.ext

# Any class derived from `omni.ext.IExt` in a top level module (defined in `python.modules` of `extension.toml`) will be
# instantiated when the extension is enabled and `on_startup(ext_id)` will be called. Later when extension gets disabled
# on_shutdown() will be called.
class OmniNewExtensionExtension(omni.ext.IExt):
# ext_id is the current extension id. It can be used with the extension manager to query additional information,
# such as where this extension is located in the filesystem.
def on_startup(self, ext_id):
print("[omni.new.extension] OmniNewExtensionExtension startup", flush=True)

def on_shutdown(self):
print("[omni.new.extension] OmniNewExtensionExtension shutdown", flush=True)
Binary file not shown.
Empty file.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"NegateNumber": {
"version": 1,
"description": "Negates a number",
"language": "Python",
"metadata": {
"uiName": "Negate Number"
},
"inputs": {
"a": {
"type": "int",
"description": "Input",
"default": 0,
"metadata": {
"uiName": "A"
}
}
},
"outputs": {
"b": {
"type": "int",
"description": "Ouput",
"metadata": {
"uiName": "B"
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
"""
This is the implementation of the OGN node defined in NegateNumber.ogn
"""

# Array or tuple values are accessed as numpy arrays so you probably need this import
import numpy


class NegateNumber:
"""
Negates a number
"""

@staticmethod
def compute(db) -> bool:
"""Compute the outputs from the current input"""
db.outputs.b = -db.inputs.a
return True
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@

[package]
# Semantic Versioning is used: https://semver.org/
version = "0.1.0"

# Lists people or organizations that are considered the "authors" of the package.
authors = ["https://github.com/franklinselva"]

# The title and description fields are primarly for displaying extension info in UI
description = "Rover Simple Controller for Space ROS"
title = "Rover Simple Controller"

# Path (relative to the root) or content of readme markdown file for UI.
changelog = "docs/CHANGELOG.md"
preview_image = "data/node-preview.png"
readme = "docs/README.md"

# URL of the extension source repository.
repository = "https://github.com/space-ros/simulation"

# Categories for UI.
category = "Space ROS"

# Keywords for the extension
keywords = ["ros2", "omnigraph", "space-ros"]

# Watch the .ogn files for hot reloading (only works for Python files)
[fswatcher.patterns]
exclude = ["Ogn*Database.py"]
include = ["*.ogn", "*.py"]

[dependencies]
"omni.graph" = {}
"omni.kit.test" = {}

# Main python module this extension provides, it will be publicly available as "import omni.spaceros.roversimplecontroller".
[[python.module]]
name = "omni.spaceros.roversimplecontroller"
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions extensions/omni.spaceros.roversimplecontroller/docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
### Rover Simple Controller

This extension provides a simple controller for the rover. This is an omnigraph node extension.
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@

import omni.ext

# Any class derived from `omni.ext.IExt` in a top level module (defined in `python.modules` of `extension.toml`) will be
# instantiated when the extension is enabled and `on_startup(ext_id)` will be called. Later when extension gets disabled
# on_shutdown() will be called.
class OmniSpacerosRoversimplecontrollerExtension(omni.ext.IExt):
# ext_id is the current extension id. It can be used with the extension manager to query additional information,
# such as where this extension is located in the filesystem.
def on_startup(self, ext_id):
print("[omni.spaceros.roversimplecontroller] OmniSpacerosRoversimplecontrollerExtension startup", flush=True)

def on_shutdown(self):
print("[omni.spaceros.roversimplecontroller] OmniSpacerosRoversimplecontrollerExtension shutdown", flush=True)
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
{
"RoverSimpleController": {
"version": 1,
"description": "Receives Linear and Angular Velocity for rover and translates to wheel and steering outputs",
"language": "Python",
"metadata": {
"uiName": "Rover Simple Controller"
},
"inputs": {
"chassis_length": {
"type": "float",
"description": "Chassis Length in meters (L)",
"default": 0,
"metadata": {
"uiName": "Chassis Length"
}
},
"chassis_width": {
"type": "float",
"description": "Chassis Width in meters (T)",
"default": 0,
"metadata": {
"uiName": "Chassis Width"
}
},
"linear_velocity": {
"type": "float[3]",
"description": "Linear Velocity Vector in m/s (x, y, z)",
"default": [
0.0,
0.0,
0.0
],
"metadata": {
"uiName": "Linear Velocity Vector"
}
},
"angular_velocity": {
"type": "float[3]",
"description": "Angular Velocity Vector in rad/s (x, y, z)",
"default": [
0.0,
0.0,
0.0
],
"metadata": {
"uiName": "Angular Velocity Vector"
}
}
},
"outputs": {
"wheel_velocity": {
"type": "double[]",
"description": "Wheel Velocity for six wheels of rover",
"metadata": {
"uiName": "Wheel Velocity"
},
"default": [
0.0,
0.0,
0.0,
0.0,
0.0,
0.0
]
},
"steering_position": {
"type": "double[]",
"description": "Steering angle in radians",
"default": [
0.0,
0.0,
0.0,
0.0
],
"metadata": {
"uiName": "Steering Position"
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
"""
This is the implementation of the OGN node defined in RoverSimpleController.ogn
"""

# Array or tuple values are accessed as numpy arrays so you probably need this import
import math


def map_angular_to_steering(angular_speed) -> float:
"""Map angular speed to steering angle."""
if abs(angular_speed) < 1e-3:
return 0.0

# max 0.6 min -0.6
angular_speed = min(0.6, max(angular_speed, -0.6))
return (angular_speed / abs(angular_speed)) * (-25 * abs(angular_speed) + 17.5)


class RoverSimpleController:
"""
Receives Linear and Angular Velocity for rover and translates to wheel and steering
outputs
"""

@staticmethod
def compute(db) -> bool:
"""Compute the outputs from the current input"""
# Get the inputs
chassis_length = db.inputs.chassis_length
chassis_width = db.inputs.chassis_width
linear_velocity = db.inputs.linear_velocity
angular_velocity = db.inputs.angular_velocity

# Compute wheel velocity
linear_velocity_x = linear_velocity[0]
wheel_velocity = [
linear_velocity_x,
linear_velocity_x * 1.5,
linear_velocity_x,
-linear_velocity_x,
-linear_velocity_x * 1.5,
-linear_velocity_x,
]

# Compute steering angle
steer_position = []
turn_rad = map_angular_to_steering(angular_velocity[2])

if abs(turn_rad) < 1e-3:
steer_position = [0.0, 0.0, 0.0, 0.0]
else:
turning_radius = abs(turn_rad) # R

chassis_length = 2.08157 # L
chassis_width = 1.53774 # T

alpha_i = math.atan(chassis_length / (turning_radius - (chassis_width / 2)))
alpha_o = math.atan(chassis_length / (turning_radius + (chassis_width / 2)))

if alpha_i > 0.6:
alpha_i = 0.6

if alpha_o > 0.6:
alpha_o = 0.6

alpha_i = round(alpha_i, 2)
alpha_o = round(alpha_o, 2)

if turn_rad > 0.0:
steer_position = [alpha_i, -alpha_i, alpha_o, -alpha_o]
else:
steer_position = [-alpha_o, alpha_o, -alpha_i, alpha_i]

# Assign the outputs
db.outputs.wheel_velocity = wheel_velocity
db.outputs.steering_position = steer_position

return True
Binary file not shown.

0 comments on commit ff93198

Please sign in to comment.