source("../../osr_common.R")6 Create Parts Description
6.1 Initialize OML File
outputdir <- paste0(omlrepo,"src/oml/opencaesar.io/open-source-rover/description/assembly/")
outputfile <- paste0(outputdir, "parts.oml")
init_oml_file <-
"description <http://opencaesar.io/open-source-rover/description/assembly/parts#> as parts {\n}\n"
cat(file=outputfile, init_oml_file)6.2 Modeling Mechanical Parts
6.2.1 Import from github
url <- "https://raw.githubusercontent.com/nasa-jpl/open-source-rover/master/parts_list/parts_list.csv"
df_csv <- read.csv(url)6.2.2 Tidy Data
colnames(df_csv) <- c("assembly","short name","part number","long name","link","cost","number req in assy","assembly multiplier")6.2.3 These are parts list but its more about a shopping cart list.
The list contains “cost”, “number req in assy”, “assembly multiplier”.
“number req in assy” and “assembly” information are used to create descriptions of parts.
df_parts_list <- df_csv
# このリストがCSVオリジナル。
# ここからパーツモデルに変換する場合には、アセンブリ必要数分だけインスタンスを用意する。
# ではダッシュボードとインスタンスの関係性は?
# インスタンスの情報にコストを埋め込む?インスタンス数とパーツリストの必要数は必ずしも一致しない
# これの扱いを考える必要がある。いずれにせよインスタンスはアセンブリで必要とする数だけ必要。
# アセンブリのインスタンス数✖️"number req in assy"がパーツの総数となる。df_instance_assembly <- data.frame(
name = c("Body Assembly",
"Drive Wheel Assembly-1",
"Drive Wheel Assembly-2",
"Corner Wheel Assembly-1",
"Corner Wheel Assembly-2",
"Corner Wheel Assembly-3",
"Corner Wheel Assembly-4",
"Rocker Bogie Suspension Assembly-1",
"Rocker Bogie Suspension Assembly-2",
"Mechanical Harness"),
instancename = c("body-assembly",
"drive-wheel-assembly-1",
"drive-wheel-assembly-2",
"corner-wheel-assembly-1",
"corner-wheel-assembly-2",
"corner-wheel-assembly-3",
"corner-wheel-assembly-4",
"rocker-bogie-suspension-assembly-1",
"rocker-bogie-suspension-assembly-2",
"mechanical-harness"
)
) %>%
mutate(type = "assembly") %>%
mutate(hasDescription = "")6.2.4 Function to generate structure:Part descriptions
generatePartDescriptions <- function(df, header, instancenameindex, index){
df_in <- df
text <- paste0("// ", header, "\n")
text_instance <- ""
text_ref <- paste0("\n", "// ref ", header, "\n")
id_count <- 1
type <- "structure:Part"
ref_instance <- paste0("assembly:",df_in$hasAssembly[1])
text_ref <- paste0(text_ref,
" ref instance ", ref_instance, " [","\n"
)
for (i in 1:nrow(df_in)){
for (j in 1:df_in$num[i]) {
id <- paste0(index, ".", formatC(id_count, width = 3, flag="0"))
id_count <- id_count + 1
instancekey <- paste0(df_in$instancename[i], instancenameindex, "-", j)
text_instance <- paste0(text_instance,
" instance ", instancekey, " : ", type, " [","\n",
" base:hasIdentifier \"", id,"\"\n",
" base:hasCanonicalName \"",df_in$name[i],"-",j,"\"\n",
" base:hasShortName \"",df_in$name[i],"-",j,"\"\n",
" structure:hasPartsNumber \"",df_in$partsnumber[i],"\"\n",
" ]\n"
)
text_ref <- paste0(text_ref,
" ^structure:hasPart ", instancekey,"\n"
)
}
}
text_ref <- paste0(text_ref,
" ]\n\n"
)
text <- paste0(text, text_instance, text_ref)
return(text)
}ref instance assembly:body-assembly [
^structure:hasPart 2-hole-flat-beam-2
]
6.2.5 Output OML FILE
#outputdir <- "~/Workspaces/gitlab/OSR_local/open-source-rover/src/oml/opencaesar.io/open-source-rover/description/assembly/"
#outputdir <-"./open-source-rover/src/oml/opencaesar.io/open-source-rover/description/assembly/"
# outputdir <-"./"
outputfile <- paste0(outputdir, "parts.oml")6.3 Generate framework of parts.oml
omldescriptions <-
"description <http://opencaesar.io/open-source-rover/description/assembly/parts#> as parts {
uses <http://imce.jpl.nasa.gov/foundation/base#> as base
uses <http://opencaesar.io/open-source-rover/vocabulary/structure#> as ^structure
extends <http://opencaesar.io/open-source-rover/description/assembly/assembly#> as assembly
"6.4 For Body
key <- 1
targetassembly <- df_instance_assembly$instancename[key]
df <- df_parts_list %>%
filter(assembly=="body") %>%
mutate(name = `short name`) %>%
mutate(hasAssembly = df_instance_assembly$instancename[1]) %>%
mutate(num = as.integer(`number req in assy`)) %>%
mutate(partsnumber = `part number`) %>%
select(name,hasAssembly,num,partsnumber) %>%
mutate(instancename = c(
"120mm-open-gorail",
"2hole-uchannel",
"32mm-bearing",
"32mm-6mm-spacer-2-pack",
"29-hole-beam",
"41-hole-beam",
"12-hole-beam",
"41-hole-ubeam",
"7-hole-flat-beam-2pack",
"dual-block-mount",
"90deg-threaded-gusset-4pack",
"50mm-threaded-rod",
"ball-linkage-2pack",
"idler-bearing-hub",
"plastic-hinges",
"8mm-standoffs",
"22mm-standoffs",
"plastic-spacer",
"3-5-grid-plate",
"2-hole-flat-beam")
)header <- c("Part - Body")
part_instance <- generatePartDescriptions(df, header, instancenameindex="", index="P0")
omldescriptions <- paste0(omldescriptions, part_instance,"\n")6.5 For drive-wheel-assembly-1
key <- 2
targetassembly <- df_instance_assembly$instancename[key]
df <- df_parts_list %>%
filter(assembly=="drive wheel") %>%
mutate(name = `short name`) %>%
mutate(hasAssembly = df_instance_assembly$instancename[key]) %>%
mutate(num = as.integer(`number req in assy`)) %>%
mutate(partsnumber = `part number`) %>%
select(name,hasAssembly,num,partsnumber) %>%
mutate(instancename = c(
"wheel",
"clamping-mount",
"motor",
"rex-bore-hub",
"2-hole-u-channel")
)
header <- c("Part - drive-wheel-assembly-1")
part_instance <- generatePartDescriptions(df, header, instancenameindex="-1", index="P1")
omldescriptions <- paste0(omldescriptions, part_instance,"\n")6.6 For drive-wheel-assembly-2
key <- 3
targetassembly <- df_instance_assembly$instancename[key]
df <- df_parts_list %>%
filter(assembly=="drive wheel") %>%
mutate(name = `short name`) %>%
mutate(hasAssembly = df_instance_assembly$instancename[key]) %>%
mutate(num = as.integer(`number req in assy`)) %>%
mutate(partsnumber = `part number`) %>%
select(name,hasAssembly,num,partsnumber) %>%
mutate(instancename = c(
"wheel",
"clamping-mount",
"motor",
"rex-bore-hub",
"2-hole-u-channel")
)
header <- c("Part - drive-wheel-assembly-2")
part_instance <- generatePartDescriptions(df, header, instancenameindex="-2", index="P2")
omldescriptions <- paste0(omldescriptions, part_instance,"\n")6.7 For corner-wheel-assembly-1/2/3/4
key <- 4
for(i in 1:4){
targetassembly <- df_instance_assembly$instancename[key]
df <- df_parts_list %>%
filter(assembly %in% c("drive wheel", "corner")) %>%
mutate(name = `short name`) %>%
mutate(hasAssembly = df_instance_assembly$instancename[key]) %>%
mutate(num = as.integer(`number req in assy`)) %>%
mutate(partsnumber = `part number`) %>%
select(name,hasAssembly,num,partsnumber) %>%
mutate(instancename = c(
"wheel",
"clamping-mount",
"motor",
"rex-bore-hub",
"2-hole-u-channel",
"144mm-gorail",
"4-hole-u-channel")
)
header <- c(paste0("Part - ", targetassembly))
part_instance <- generatePartDescriptions(df, header, instancenameindex=paste0("-", 2+i), index=paste0("P",2+i))
omldescriptions <- paste0(omldescriptions, part_instance,"\n")
key <- key + 1
}6.8 For rocker-bogie-suspension-assembly-1/2
key <- 8
for(i in 1:2){
targetassembly <- df_instance_assembly$instancename[key]
df <- df_parts_list %>%
filter(assembly=="rocker bogie") %>%
mutate(name = `short name`) %>%
mutate(hasAssembly = df_instance_assembly$instancename[key]) %>%
mutate(num = as.integer(`number req in assy`)) %>%
mutate(partsnumber = `part number`) %>%
select(name,hasAssembly,num,partsnumber) %>%
mutate(instancename = c(
"1-hole-uchannel",
"servoblock",
"servo",
"8mm-sonic-hub",
"flanged-bearing-2pack",
"joint-pattern-spacer",
"joint-8mm-shaft",
"joint-3hole-flat-beam-2pack",
"joint-pattern-mount",
"steel-flat-bracket",
"3-5-grid-plate",
"angle-bracket",
"96mm-open-gorail",
"288mm-open-goRail",
"45deg-bracket",
"90deg-steel-bracket-2pack",
"control-arm",
"8mm-id-spacer-6mm-length",
"8mm-id-spacer-4mm-length")
)
# if number of req is 0.5, we create one part instance.
df <- df %>%
mutate_at(vars(num), ~ ifelse(. == 0, 1, .))
header <- c(paste0("Part - ", targetassembly))
part_instance <- generatePartDescriptions(df, header, instancenameindex=paste0("-", 7+i), index=paste0("P",7+i))
omldescriptions <- paste0(omldescriptions, part_instance,"\n")
key <- key + 1
}6.9 For mechanical-harness
instancenametext <- c(
"hurricane-nuts",
"wire-grommets",
"M4-washers",
"M4-uts",
"M4-locknuts",
"M4-6-button-screws",
"M4-10-button-screws",
"M4-16-button-screws",
"M4-8-socket-screws",
"M4-10-socket-screws",
"M4-12-socket-screws",
"M4-16-socket-screws",
"M4-20-socket-screws"
)
key <- 10
targetassembly <- df_instance_assembly$instancename[key]
df <- df_parts_list %>%
filter(assembly=="general") %>%
mutate(name = `short name`) %>%
mutate(hasAssembly = df_instance_assembly$instancename[key]) %>%
mutate(num = as.integer(`number req in assy`)) %>%
mutate(partsnumber = `part number`) %>%
select(name,hasAssembly,num,partsnumber) %>%
mutate(instancename = instancenametext)
header <- c(paste0("Part - ", targetassembly))
part_instance <- generatePartDescriptions(df, header, instancenameindex=paste0("-", 10), index=paste0("P",10))
omldescriptions <- paste0(omldescriptions, part_instance,"\n")6.10 Generate OML File
omldescriptions <- paste0(omldescriptions,"\n}\n")
cat(file=outputfile, omldescriptions)6.11 Validate Model
Before we check the model, add below codes to the description bundle.
includes <http://opencaesar.io/open-source-rover/description/assembly/parts#>oml_repository <- omlrepo
omlhashiR::oml_refresh()[1] "kill success for pid=24476"
omlhashiR::oml_stop_Daemon(oml_repository)[1] "Stopping Daemon(s)" "1 Daemon stopped"
omlhashiR::oml_build(oml_repository) [1] "Starting a Gradle Daemon, 28 stopped Daemons could not be reused, use --status for details"
[2] "> Task :omlZip"
[3] "> Task :assemble"
[4] "> Task :downloadDependencies UP-TO-DATE"
[5] "> Task :omlToOwl"
[6] "> Task :owlReason"
[7] "> Task :check"
[8] "> Task :build"
[9] ""
[10] "BUILD SUCCESSFUL in 7s"
[11] "4 actionable tasks: 3 executed, 1 up-to-date"
omlhashiR::oml_startFuseki(oml_repository)[1] "> Task :startFuseki UP-TO-DATE" ""
[3] "BUILD SUCCESSFUL in 601ms" "1 actionable task: 1 up-to-date"
omlhashiR::oml_owlLoad(oml_repository)[1] "> Task :downloadDependencies UP-TO-DATE"
[2] "> Task :omlToOwl UP-TO-DATE"
[3] "> Task :owlReason UP-TO-DATE"
[4] ""
[5] "> Task :owlLoad"
[6] "Loaded 22 owl file(s), unloaded 0 owl file(s)"
[7] ""
[8] "BUILD SUCCESSFUL in 1s"
[9] "4 actionable tasks: 1 executed, 3 up-to-date"
6.12 Query
library(tansakusuR)
endpoint_url <- "http://localhost:3030/open-source-rover/sparql"query_string <-'
PREFIX base: <http://imce.jpl.nasa.gov/foundation/base#>
PREFIX mission: <http://imce.jpl.nasa.gov/foundation/mission#>
PREFIX structure: <http://opencaesar.io/open-source-rover/vocabulary/structure#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT DISTINCT ?c1_localname ?c1_name ?c1_type ?c2_localname ?c2_name
WHERE {
?c1 a mission:Component ;
base:hasCanonicalName ?c1_name .
OPTIONAL{
?c1 base:isContainedIn ?c2 .
OPTIONAL{
?c2 base:hasCanonicalName ?c2_name .
}
}
# Extract the local name
BIND(STRAFTER(STR(?c1), "#") AS ?c1_localname) .
BIND(STRAFTER(STR(?c2), "#") AS ?c2_localname) .
OPTIONAL {
?c1 a structure:System ;
BIND("structure:System" AS ?c1_type) .
}
OPTIONAL {
?c1 a structure:Subsystem ;
BIND("structure:Subsystem" AS ?c1_type) .
}
OPTIONAL {
?c1 a structure:Assembly ;
BIND("structure:Assembly" AS ?c1_type) .
}
OPTIONAL {
?c1 a structure:Part ;
BIND("structure:Part" AS ?c1_type) .
}
}
ORDER BY ?c1_localname
'
df_query <- tansakusuR::send_query(endpoint_url,query_string)
datatable(df_query, options = list(pageLength = 20))df2 <- df_query %>%
arrange(desc(c2_name))
plotCollapsibleTreeFromDataframe(df2, palette="BluYl", parent="c2_name", child="c1_name",type="c1_type")df2<- df_query %>%
mutate(owner=c2_name) %>%
mutate(name=c1_name) %>%
select("owner","name") %>%
arrange(desc(owner)) %>%
slice(-n())
library(networkD3)
networkD3::simpleNetwork(df2)library(data.tree)
nd3 <- ToListExplicit(FromDataFrameNetwork(df2), unname = T)
networkD3::diagonalNetwork(List = nd3, fontSize = 10, opacity = 0.9)networkD3::radialNetwork(nd3, nodeColour="seagreen")