Skip to content

Commit 9ed5605

Browse files
authored
RSDK-10936 introduce RobotFrameSystem interface (#5101)
1 parent b9cbdda commit 9ed5605

File tree

21 files changed

+343
-206
lines changed

21 files changed

+343
-206
lines changed

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ require (
8181
go.uber.org/atomic v1.11.0
8282
go.uber.org/multierr v1.11.0
8383
go.uber.org/zap v1.27.0
84-
go.viam.com/api v0.1.452
84+
go.viam.com/api v0.1.455
8585
go.viam.com/test v1.2.4
8686
go.viam.com/utils v0.1.150
8787
goji.io v2.0.2+incompatible

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1513,8 +1513,8 @@ go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI=
15131513
go.uber.org/zap v1.23.0/go.mod h1:D+nX8jyLsMHMYrln8A0rJjFt/T/9/bGgIhAqxv5URuY=
15141514
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
15151515
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
1516-
go.viam.com/api v0.1.452 h1:/rexbvi6Bfva/iqNEu2ftS6NrrQICg5CPnj1PKgTAi4=
1517-
go.viam.com/api v0.1.452/go.mod h1:gwJriv6EVWe97uFzzzWjzP3NPfpCrKtRAdWtYglUpqs=
1516+
go.viam.com/api v0.1.455 h1:WY++sFAydRGcg/E1va85BFPi9U7IuEf2Dk0JrPZ1Wzs=
1517+
go.viam.com/api v0.1.455/go.mod h1:gwJriv6EVWe97uFzzzWjzP3NPfpCrKtRAdWtYglUpqs=
15181518
go.viam.com/test v1.2.4 h1:JYgZhsuGAQ8sL9jWkziAXN9VJJiKbjoi9BsO33TW3ug=
15191519
go.viam.com/test v1.2.4/go.mod h1:zI2xzosHdqXAJ/kFqcN+OIF78kQuTV2nIhGZ8EzvaJI=
15201520
go.viam.com/utils v0.1.150 h1:45r/HlGxeAaOQgHakjUhOKFUitOiN0vRlTxkXmzA7iA=

module/modmanager/module.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,8 @@ func (m *module) dial() error {
6767
if !rutils.TCPRegex.MatchString(addrToDial) {
6868
addrToDial = "unix:" + addrToDial
6969
}
70-
conn, err := grpc.Dial( //nolint:staticcheck
70+
//nolint:staticcheck
71+
conn, err := grpc.Dial(
7172
addrToDial,
7273
grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(rpc.MaxMessageSize)),
7374
grpc.WithTransportCredentials(insecure.NewCredentials()),

module/module_test.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,8 @@ func TestModuleFunctions(t *testing.T) {
186186

187187
test.That(t, m.Start(ctx), test.ShouldBeNil)
188188

189-
conn, err := grpc.Dial( //nolint:staticcheck
189+
//nolint:staticcheck
190+
conn, err := grpc.Dial(
190191
"unix://"+addr,
191192
grpc.WithTransportCredentials(insecure.NewCredentials()),
192193
grpc.WithStreamInterceptor(grpc_retry.StreamClientInterceptor()),
@@ -477,7 +478,8 @@ func TestAttributeConversion(t *testing.T) {
477478
test.That(t, m.AddModelFromRegistry(ctx, shell.API, modelWithReconfigure), test.ShouldBeNil)
478479

479480
test.That(t, m.Start(ctx), test.ShouldBeNil)
480-
conn, err := grpc.Dial( //nolint:staticcheck
481+
//nolint:staticcheck
482+
conn, err := grpc.Dial(
481483
"unix://"+addr,
482484
grpc.WithTransportCredentials(insecure.NewCredentials()),
483485
grpc.WithStreamInterceptor(grpc_retry.StreamClientInterceptor()),

robot/client/client.go

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -973,6 +973,33 @@ func (rc *RobotClient) FrameSystemConfig(ctx context.Context) (*framesystem.Conf
973973
return &framesystem.Config{Parts: result}, nil
974974
}
975975

976+
// GetPose returns the pose of the specified component in the given destination frame.
977+
func (rc *RobotClient) GetPose(
978+
ctx context.Context,
979+
componentName, destinationFrame string,
980+
supplementalTransforms []*referenceframe.LinkInFrame,
981+
extra map[string]interface{},
982+
) (*referenceframe.PoseInFrame, error) {
983+
ext, err := protoutils.StructToStructPb(extra)
984+
if err != nil {
985+
return nil, err
986+
}
987+
transforms, err := referenceframe.LinkInFramesToTransformsProtobuf(supplementalTransforms)
988+
if err != nil {
989+
return nil, err
990+
}
991+
resp, err := rc.client.GetPose(ctx, &pb.GetPoseRequest{
992+
ComponentName: componentName,
993+
DestinationFrame: destinationFrame,
994+
SupplementalTransforms: transforms,
995+
Extra: ext,
996+
})
997+
if err != nil {
998+
return nil, err
999+
}
1000+
return referenceframe.ProtobufToPoseInFrame(resp.Pose), nil
1001+
}
1002+
9761003
// TransformPose will transform the pose of the requested poseInFrame to the desired frame in the robot's frame system.
9771004
//
9781005
// import (
@@ -986,9 +1013,9 @@ func (rc *RobotClient) TransformPose(
9861013
ctx context.Context,
9871014
query *referenceframe.PoseInFrame,
9881015
destination string,
989-
additionalTransforms []*referenceframe.LinkInFrame,
1016+
supplementalTransforms []*referenceframe.LinkInFrame,
9901017
) (*referenceframe.PoseInFrame, error) {
991-
transforms, err := referenceframe.LinkInFramesToTransformsProtobuf(additionalTransforms)
1018+
transforms, err := referenceframe.LinkInFramesToTransformsProtobuf(supplementalTransforms)
9921019
if err != nil {
9931020
return nil, err
9941021
}
@@ -1036,6 +1063,27 @@ func (rc *RobotClient) TransformPointCloud(ctx context.Context, srcpc pointcloud
10361063
return output, nil
10371064
}
10381065

1066+
// CurrentInputs returns a map of the current inputs for each component of a machine's frame system
1067+
// and a map of statuses indicating which of the machine's components may be actuated through input values.
1068+
func (rc *RobotClient) CurrentInputs(ctx context.Context) (referenceframe.FrameSystemInputs, error) {
1069+
input := make(referenceframe.FrameSystemInputs)
1070+
for _, name := range rc.ResourceNames() {
1071+
res, err := rc.ResourceByName(name)
1072+
if err != nil {
1073+
return nil, err
1074+
}
1075+
inputEnabled, ok := res.(framesystem.InputEnabled)
1076+
if ok {
1077+
pos, err := inputEnabled.CurrentInputs(ctx)
1078+
if err != nil {
1079+
return nil, err
1080+
}
1081+
input[name.ShortName()] = pos
1082+
}
1083+
}
1084+
return input, nil
1085+
}
1086+
10391087
// StopAll cancels all current and outstanding operations for the machine and stops all actuators and movement.
10401088
//
10411089
// err := machine.StopAll(ctx.Background())

robot/client/client_test.go

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2008,6 +2008,67 @@ func TestShutDown(t *testing.T) {
20082008
test.That(t, shutdownCalled, test.ShouldBeTrue)
20092009
}
20102010

2011+
func TestCurrentInputs(t *testing.T) {
2012+
logger := logging.NewTestLogger(t)
2013+
listener, err := net.Listen("tcp", "localhost:0")
2014+
test.That(t, err, test.ShouldBeNil)
2015+
gServer := grpc.NewServer()
2016+
2017+
testAPI := resource.APINamespaceRDK.WithComponentType(arm.SubtypeName)
2018+
testName := resource.NewName(testAPI, "arm1")
2019+
testName2 := resource.NewName(testAPI, "arm2")
2020+
2021+
expectedInputs := referenceframe.FrameSystemInputs{
2022+
testName.ShortName(): []referenceframe.Input{{0}, {math.Pi}, {-math.Pi}, {0}, {math.Pi}, {-math.Pi}},
2023+
testName2.ShortName(): []referenceframe.Input{{math.Pi}, {-math.Pi}, {0}, {math.Pi}, {-math.Pi}, {0}},
2024+
}
2025+
injectArm := &inject.Arm{
2026+
JointPositionsFunc: func(ctx context.Context, extra map[string]any) ([]referenceframe.Input, error) {
2027+
return expectedInputs[testName.ShortName()], nil
2028+
},
2029+
KinematicsFunc: func(ctx context.Context) (referenceframe.Model, error) {
2030+
return referenceframe.ParseModelJSONFile(rutils.ResolveFile("components/arm/example_kinematics/ur5e.json"), "")
2031+
},
2032+
}
2033+
injectArm2 := &inject.Arm{
2034+
JointPositionsFunc: func(ctx context.Context, extra map[string]any) ([]referenceframe.Input, error) {
2035+
return expectedInputs[testName2.ShortName()], nil
2036+
},
2037+
KinematicsFunc: func(ctx context.Context) (referenceframe.Model, error) {
2038+
return referenceframe.ParseModelJSONFile(rutils.ResolveFile("components/arm/example_kinematics/xarm6_kinematics_test.json"), "")
2039+
},
2040+
}
2041+
resourceNames := []resource.Name{testName, testName2}
2042+
resources := map[resource.Name]arm.Arm{testName: injectArm, testName2: injectArm2}
2043+
injectRobot := &inject.Robot{
2044+
ResourceNamesFunc: func() []resource.Name { return resourceNames },
2045+
ResourceByNameFunc: func(n resource.Name) (resource.Resource, error) { return resources[n], nil },
2046+
MachineStatusFunc: func(ctx context.Context) (robot.MachineStatus, error) {
2047+
return robot.MachineStatus{State: robot.StateRunning}, nil
2048+
},
2049+
ResourceRPCAPIsFunc: func() []resource.RPCAPI { return nil },
2050+
}
2051+
2052+
armSvc, err := resource.NewAPIResourceCollection(arm.API, resources)
2053+
test.That(t, err, test.ShouldBeNil)
2054+
gServer.RegisterService(&armpb.ArmService_ServiceDesc, arm.NewRPCServiceServer(armSvc))
2055+
pb.RegisterRobotServiceServer(gServer, server.New(injectRobot))
2056+
2057+
go gServer.Serve(listener)
2058+
defer gServer.Stop()
2059+
2060+
client, err := New(context.Background(), listener.Addr().String(), logger)
2061+
test.That(t, err, test.ShouldBeNil)
2062+
defer func() {
2063+
test.That(t, client.Close(context.Background()), test.ShouldBeNil)
2064+
}()
2065+
2066+
inputs, err := client.CurrentInputs(context.Background())
2067+
test.That(t, err, test.ShouldBeNil)
2068+
test.That(t, len(inputs), test.ShouldEqual, 2)
2069+
test.That(t, inputs, test.ShouldResemble, expectedInputs)
2070+
}
2071+
20112072
func TestUnregisteredResourceByName(t *testing.T) {
20122073
logger := logging.NewTestLogger(t)
20132074
listener, err := net.Listen("tcp", "localhost:0")

0 commit comments

Comments
 (0)