Skip to content
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

Updating ruby script to use standalone executable #1489

Open
wants to merge 2 commits into
base: scpeters/gz_sdf_executable
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
10 changes: 5 additions & 5 deletions src/cmd/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ if (NOT HAVE_GZ_TOOLS)
endif()

# Make a small static lib of command line functions
add_library(gz STATIC gz.cc)
add_library(gz STATIC gz.cc ../FrameSemantics.cc)
target_link_libraries(gz
${PROJECT_LIBRARY_TARGET_NAME}
)
Expand Down Expand Up @@ -47,14 +47,14 @@ endif()
# Generate the ruby script for internal testing.
# Note that the major version of the library is included in the name.
# Ex: cmdsdformat0.rb
set(cmd_script_generated_test
set(cmd_script_generated_test
"${CMAKE_BINARY_DIR}/test/lib/$<CONFIG>/ruby/gz/cmd${PROJECT_NAME}.rb")
set(cmd_script_configured_test
set(cmd_script_configured_test
"${CMAKE_CURRENT_BINARY_DIR}/test_cmd${PROJECT_NAME}.rb.configured")

# Set the library_location variable to the full path of the library file within
# the build directory.
set(library_location "$<TARGET_FILE:${PROJECT_NAME}>")
set(library_location "$<TARGET_FILE:${sdf_executable}>")

configure_file(
"cmd${PROJECT_NAME_NO_VERSION_LOWER}.rb.in"
Expand Down Expand Up @@ -82,7 +82,7 @@ else()
set(library_location_prefix "${CMAKE_INSTALL_LIBDIR}")
endif()

set(library_location "../../../${library_location_prefix}/$<TARGET_FILE_NAME:${PROJECT_NAME}>")
set(library_location "../../../${CMAKE_INSTALL_LIBEXECDIR}/gz/${GZ_DESIGNATION}${PROJECT_VERSION_MAJOR}/$<TARGET_FILE_NAME:${sdf_executable}>")

configure_file(
"cmd${PROJECT_NAME_NO_VERSION_LOWER}.rb.in"
Expand Down
248 changes: 12 additions & 236 deletions src/cmd/cmdsdformat.rb.in
Original file line number Diff line number Diff line change
Expand Up @@ -14,263 +14,39 @@
# See the License for the specific language governing permissions and
# limitations under the License.

# We use 'dl' for Ruby <= 1.9.x and 'fiddle' for Ruby >= 2.0.x
if RUBY_VERSION.split('.')[0] < '2'
require 'dl'
require 'dl/import'
include DL
else
require 'fiddle'
require 'fiddle/import'
include Fiddle
end

require 'optparse'
require 'pathname'


# Constants.
LIBRARY_NAME = '@library_location@'
LIBRARY_VERSION = '@PROJECT_VERSION_FULL@'
COMMON_OPTIONS =
" -h [ --help ] Print this help message.\n"\
" --force-version <VERSION> Use a specific library version.\n"\
' --versions Show the available versions.'
COMMANDS = { 'sdf' =>
"Utilities for SDF files.\n\n"\
" gz sdf [options]\n\n"\
"Options:\n\n"\
" -k [ --check ] arg Check if an SDFormat file is valid.\n" +
" -d [ --describe ] [SPEC VERSION] Print the aggregated SDFormat spec description. Default version (@SDF_PROTOCOL_VERSION@).\n" +
" -g [ --graph ] <pose, frame> arg Print the PoseRelativeTo or FrameAttachedTo graph. (WARNING: This is for advanced\n" +
" use only and the output may change without any promise of stability)\n" +
" --inertial-stats arg Prints moment of inertia, centre of mass, and total mass from a model sdf file.\n" +
" -p [ --print ] arg Print converted arg. Note the quaternion representation of the\n" +
" rotational part of poses and unit vectors will be normalized.\n" +
" -i [ --preserve-includes ] Preserve included tags when printing converted arg (does not preserve merge-includes).\n" +
" --degrees Pose rotation angles are printed in degrees.\n" +
" --expand-auto-inertials Prints auto-computed inertial values for simple shapes. For meshes and other unsupported\n" +
" shapes, the default inertial values will be printed.\n" +
" --snap-to-degrees arg Snap pose rotation angles to this specified interval in degrees. This value must be\n" +
" larger than 0, less than or equal to 360, and larger than the defined snap tolerance.\n" +
" --snap-tolerance arg Used in conjunction with --snap-to-degrees, specifies the tolerance at which snapping\n" +
" occurs. This value must be larger than 0, less than 360, and less than the defined\n" +
" degrees value to snap to. If unspecified, its default value is 0.01.\n" +
" --precision arg Set the output stream precision for floating point numbers. The arg must be a positive integer.\n" +

COMMON_OPTIONS
}
COMMANDS = {
'sdf' => '@library_location@'
}

#
# Class for the SDF command line tools.
#
class Cmd

#
# Return a structure describing the options.
#
def parse(args)
options = {}
options['degrees'] = 0
options['expand_auto_inertials'] = 0
options['snap_tolerance'] = 0.01
options['preserve_includes'] = 0

usage = COMMANDS[args[0]]

# Read the command line arguments.
opt_parser = OptionParser.new do |opts|
opts.banner = usage

opts.on('-h', '--help", "Print this help message') do
puts usage
exit(0)
end

opts.on('-k arg', '--check arg', String,
'Check if an SDFormat file is valid.') do |arg|
options['check'] = arg
end
opts.on('--inertial-stats arg', String,
'Prints moment of inertia, centre of mass, and total mass from a model sdf file.') do |arg|
options['inertial_stats'] = arg
end
opts.on('-d', '--describe [VERSION]', 'Print the aggregated SDFormat spec description. Default version (@SDF_PROTOCOL_VERSION@)') do |v|
options['describe'] = v
end
opts.on('-p', '--print', 'Print converted arg') do
options['print'] = 1
end
opts.on('-i', '--preserve-includes', 'Preserve included tags when printing converted arg (does not preserve merge-includes)') do
options['preserve_includes'] = 1
end
opts.on('--degrees', 'Printed pose rotations are will be in degrees') do |degrees|
options['degrees'] = 1
end
opts.on('--expand-auto-inertials', 'Auto-computed inertial values will be printed') do
options['expand_auto_inertials'] = 1
end
opts.on('--snap-to-degrees arg', Integer,
'Printed rotations are snapped to specified degree intervals') do |arg|
if arg == 0 || arg > 360
puts "Degree interval to snap to must be more than 0, and less than or equal to 360."
exit(-1)
end
options['snap_to_degrees'] = arg
end
opts.on('--snap-tolerance arg', Float,
'Printed rotations are snapped if they are within this specified tolerance') do |arg|
if arg < 0 || arg > 360
puts "Rotation snapping tolerance must be more than 0, and less than 360."
exit(-1)
end
options['snap_tolerance'] = arg
end
opts.on('--precision arg', Integer,
'Set the output stream precision for floating point numbers.') do |arg|
options['precision'] = arg
end
opts.on('-g arg', '--graph type', String,
'Print PoseRelativeTo or FrameAttachedTo graph') do |graph_type|
options['graph'] = {:type => graph_type}
end
end
begin
opt_parser.parse!(args)
rescue
puts usage
exit(-1)
end

# Check that there is at least one command and there is a plugin that knows
# how to handle it.
if ARGV.empty? || !COMMANDS.key?(ARGV[0]) ||
options.empty?
puts usage
exit(-1)
end

options['command'] = ARGV[0]

if (options['preserve_includes'] != 0 and not options['print']) ||
(options['precision'] and not options['print'])
puts usage
exit(-1)
end

if options['print']
filename = args.pop
if filename
options['print'] = filename
else
puts usage
exit(-1)
end
end

options
end

#
# Execute the command
#
def execute(args)
options = parse(args)
command = args[0]
exe_name = COMMANDS[command]

# Debugging:
# puts 'Parsed:'
# puts options

# Read the plugin that handles the command.
if Pathname.new(LIBRARY_NAME).absolute?
plugin = LIBRARY_NAME
else
unless Pathname.new(exe_name).absolute?
# We're assuming that the library path is relative to the current
# location of this script.
plugin = File.expand_path(File.join(File.dirname(__FILE__), LIBRARY_NAME))
exe_name = File.expand_path(File.join(File.dirname(__FILE__), exe_name))
end
conf_version = LIBRARY_VERSION

if defined? RubyInstaller
# RubyInstaller does not search for dlls in PATH or the directory that tests are running from,
# so we'll add the parent directory of the plugin to the search path.
# https://github.com/oneclick/rubyinstaller2/wiki/For-gem-developers#-dll-loading
RubyInstaller::Runtime.add_dll_directory(File.dirname(plugin))
end

begin
Importer.dlload plugin
rescue DLError => error
puts "Library error: [#{plugin}] not found."
puts "DLError: #{error.message}"
exit(-1)
end

# Read the library version.
Importer.extern 'char* gzVersion()'
begin
plugin_version = Importer.gzVersion.to_s
rescue DLError
puts "Library error: Problem running 'gzVersion()' from #{plugin}."
exit(-1)
end
exe_version = `#{exe_name} --version`.strip

# Sanity check: Verify that the version of the yaml file matches the version
# of the library that we are using.
unless plugin_version.eql? conf_version
unless exe_version.eql? conf_version
puts "Error: Version mismatch. Your configuration file version is
[#{conf_version}] but #{plugin} version is [#{plugin_version}]."
[#{conf_version}] but #{exe_name} version is [#{exe_version}]."
exit(-1)
end

begin
case options['command']
when 'sdf'
if options.key?('check')
Importer.extern 'int cmdCheck(const char *)'
exit(Importer.cmdCheck(File.expand_path(options['check'])))
elsif options.key?('inertial_stats')
Importer.extern 'int cmdInertialStats(const char *)'
exit(Importer.cmdInertialStats(options['inertial_stats']))
elsif options.key?('describe')
Importer.extern 'int cmdDescribe(const char *)'
exit(Importer.cmdDescribe(options['describe']))
elsif options.key?('print')
snap_to_degrees = 0
precision = 0

if options.key?('snap_to_degrees')
if options['snap_to_degrees'] < options['snap_tolerance']
puts "Rotation snapping tolerance must be larger than the snapping tolerance."
exit(-1)
end
snap_to_degrees = options['snap_to_degrees']
end
if options.key?('precision')
precision = options['precision']
end
Importer.extern 'int cmdPrint(const char *, int in_degrees, int snap_to_degrees, float snap_tolerance, int, int, int)'
exit(Importer.cmdPrint(File.expand_path(options['print']),
options['degrees'],
snap_to_degrees,
options['snap_tolerance'],
options['preserve_includes'],
precision,
options['expand_auto_inertials']))
elsif options.key?('graph')
Importer.extern 'int cmdGraph(const char *, const char *)'
exit(Importer.cmdGraph(options['graph'][:type], File.expand_path(ARGV[1])))
else
puts 'Command error: I do not have an implementation '\
'for this command.'
end
else
puts 'Command error: I do not have an implementation for '\
"command [gz #{options['command']}]."
end
rescue
puts "Library error: Problem running [#{options['command']}]() "\
"from #{plugin}."
end
# Drop command from list of arguments
exec(exe_name, *args[1..-1])
end
end
Loading