Value Types
Overview
Robot Raconteur passes “Value Types” between clients and services by value. The values are “serialized” to a binary format that can be transmitted over a network. The values are then “deserialized” back into the original data type. The serialization and deserialization process is handled transparently by the Robot Raconteur library. Because Robot Raconteur supports multiple programming languages, the value types are defined using Robot Raconteur “Service Definitions,” which provide a common language-independent format for defining data types. The Value Types are carefully designed to support robotics and automation applications.
See also the Robot Raconteur Framework Service Definition Documentation
The following data types are supported by Robot Raconteur:
bool - A boolean value that can be either
trueorfalse. * Arrays and multidimensional arrays of booleans.Numeric types including
uint8,int8,uint16,int16,uint32,int32,uint64,int64,single,double,csingle, andcdouble. * Arrays and multidimensional arrays of numeric types.string - A string of characters.
struct - A structure that contains a collection of fields.
pod - A “Plain Old Data” structure that contains a collection of fields that are stored in contiguous memory. * Arrays and multidimensional arrays of POD types.
namedarray - A structure that contains a collection of fields that are stored as a union between a structure and a numeric array in contiguous memory. * Arrays and multidimensional arrays of namedarray types.
Collection types including
list,map{int32}, andmap{string}. * Any of the above types can be used as the value type in a collection type.
The struct, pod, and namedarray types are defined using the Robot Raconteur “Service Definitions” format.
Object “members” are used to interact with services and pass data between clients and services. The examples on this page use property types to pass data between clients and services. The value types can all be used with all member types.
The example service definition experimental.value_types is used for the examples on this page. The service
definition is shown below:
Numeric Types
Robot Raconteur supports numeric types including uint8, int8, uint16, int16, uint32, int32,
uint64, int64, single, double, csingle, and cdouble. For the purpose of this section,
bool is also considered a numeric type. Scalar numbers are converted to the built-in numeric types in
the client programming language. Numeric types can also be stored in arrays and multidimensional arrays.
The following members from the experimental.value_types.ValueTypesExample object are used in the examples
for numeric types:
# Examples of scalar numeric types
property double a_double
property int32 b_int
property uint8 c_byte
property cdouble d_cdouble
property bool e_bool
property int32 meaning_of_life [readonly]
# Examples of numeric arrays. Any numeric array type
# can be used
property double[] a_double_array
property double[3] a_double_array_fixed
property double[6-] a_double_array_maxlen
property double[3,2] a_double_marray_fixed
property double[*] a_double_marray
property uint8[] c_byte_array
The examples below show how to use the numeric types in Python, MATLAB, LabView, C#, and C++.
1# numeric_value_types.py - Example of using numeric value types
2
3from RobotRaconteur.Client import *
4import numpy as np
5
6c = RRN.ConnectService('rr+tcp://localhost:53223?service=values_example')
7
8# Scalar numbers
9# property double a_double
10a_double_read = c.a_double
11print(a_double_read)
12# assert is used for the rest of the example property read operations
13# to demonstrate the expected values.
14assert (c.a_double == 5.78)
15c.a_double = 49.3
16# property int32 b_int
17assert (c.b_int == 4557)
18c.b_int = 359
19# property uint8 c_byte
20assert (c.c_byte == 0x1A)
21c.c_byte = 31
22# property cdouble d_cdouble
23assert (c.d_cdouble == 23.7 + 1j * 5.3)
24c.d_cdouble = 1.2 + 3.4j
25# property bool e_bool
26assert (c.e_bool == True)
27c.e_bool = False
28# property int32 meaning_of_life [readonly]
29assert (c.meaning_of_life == 42)
30
31# Numeric Arrays
32# Note the use of `dtype` parameter when creating arrays. This must match the
33# type specified in the service definition.
34# property double[] a_double_array
35np.testing.assert_allclose(c.a_double_array, [0.016, 0.226])
36c.a_double_array = np.array([0.582, 0.288, 0.09, 0.213, 0.98], dtype=np.float64)
37# property double[3] a_double_array_fixed
38np.testing.assert_allclose(c.a_double_array_fixed, [0.13, 0.27, 0.15])
39c.a_double_array_fixed = np.array([0.21, 0.12, 0.39], dtype=np.float64)
40# property double[6-] a_double_array_maxlen
41np.testing.assert_allclose(c.a_double_array_maxlen, [0.7, 0.16, 0.16, 0.05, 0.61, 0.9])
42c.a_double_array_maxlen = np.array([0.035, 0.4], dtype=np.float64)
43# property double[3,2] a_double_marray_fixed
44np.testing.assert_allclose(c.a_double_marray_fixed, [[0.29, 0.66], [0.41, 0.6], [0.4, 0.2]])
45c.a_double_marray_fixed = np.array([[0.3, 0.6], [0.4, 0.6], [0.5, 0.2]], dtype=np.float64)
46# property double[*] a_double_marray
47np.testing.assert_allclose(c.a_double_marray, [[0.72, 0.4], [0.05, 0.07]])
48c.a_double_marray = np.array([[0.3], [0.01]], dtype=np.float64)
49# property uint8[] c_byte_array
50np.testing.assert_array_equal(c.c_byte_array, [0x1A, 0x2B])
51c.c_byte_array = np.array([0x3C, 0x4D, 0x5E, 0x6F, 0x70], dtype=np.uint8)
1% numeric_value_types.m - Example of using numeric value types
2
3c = RobotRaconteur.ConnectService('rr+tcp://localhost:53223?service=values_example');
4
5% Scalar numbers
6% property double a_double
7a_double_read = c.a_double;
8disp(a_double_read);
9% assert is used for the rest of the example property read operations
10% to demonstrate the expected values.
11assert(c.a_double == 5.78);
12c.a_double = 49.3;
13% property int32 b_int
14assert (c.b_int == 4557)
15c.b_int = int32(359);
16% property uint8 c_byte
17assert (c.c_byte == 0x1A)
18c.c_byte = uint8(31);
19% property cdouble d_cdouble
20assert (c.d_cdouble == 23.7 + 5.3i)
21c.d_cdouble = 1.2 + 3.4i;
22% property bool e_bool
23assert (c.e_bool == true)
24c.e_bool = false;
25% property int32 meaning_of_life [readonly]
26assert (c.meaning_of_life == 42)
27
28% Numeric Arrays
29% property double[] a_double_array
30assert(isequal(c.a_double_array, [0.016, 0.226]'));
31c.a_double_array = [0.582, 0.288, 0.09, 0.213, 0.98]';
32% property double[3] a_double_array_fixed
33assert(isequal(c.a_double_array_fixed, [0.13, 0.27, 0.15]'));
34c.a_double_array_fixed = [0.21,0.12, 0.39]';
35% property double[6-] a_double_array_maxlen
36assert(isequal(c.a_double_array_maxlen, [0.7, 0.16, 0.16, 0.05, 0.61, 0.9]'));
37c.a_double_array_maxlen = [0.035, 0.4]';
38% property double[3,2] a_double_marray_fixed
39assert(isequal(c.a_double_marray_fixed, [0.29, 0.66; 0.41, 0.6; 0.4, 0.2]));
40c.a_double_marray_fixed = [0.3, 0.6; 0.4, 0.6; 0.5, 0.2];
41% property double[*] a_double_marray
42assert(isequal(c.a_double_marray, [0.72, 0.4; 0.05, 0.07]));
43c.a_double_marray = [0.3; 0.01];
44% property uint8[] c_byte_array
45assert(isequal(c.c_byte_array, [0x1A, 0x2B]'));
46c.c_byte_array = uint8([0x3C, 0x4D, 0x5E, 0x6F, 0x70]');
47
48RobotRaconteur.DisconnectService(c);
1// numeric_value_types.cs - Example of using numeric value types
2
3using RobotRaconteur;
4using System;
5using System.Diagnostics;
6using System.Linq;
7
8using (var node_setup = new ClientNodeSetup(args))
9{
10
11 var c = (experimental.value_types.ValueTypesExample)RobotRaconteurNode.s.ConnectService(
12 "rr+tcp://localhost:53223?service=values_example");
13
14 // Scalar numbers
15 // property double a_double
16 double a_double_read = c.a_double;
17 Console.WriteLine(a_double_read);
18 // Debug.Assert is used for the rest of the example property read operations
19 // to demonstrate the expected values.
20 Debug.Assert(c.a_double == 5.78);
21 c.a_double = 49.3;
22 // property int32 b_int
23 Debug.Assert(c.b_int == 4557);
24 c.b_int = (int)359;
25 // property uint8 c_byte
26 Debug.Assert(c.c_byte == 0x1A);
27 c.c_byte = (byte)31;
28 // property cdouble d_cdouble
29 Debug.Assert(c.d_cdouble == new CDouble(23.7, 5.3));
30 c.d_cdouble = new CDouble(1.2, 3.4);
31 // property bool e_bool
32 Debug.Assert(c.e_bool == true);
33 c.e_bool = false;
34 // property int32 meaning_of_life [readonly]
35 Debug.Assert(c.meaning_of_life == 42);
36
37 // Numeric Arrays
38 // property double[] a_double_array
39 Debug.Assert(Enumerable.SequenceEqual(c.a_double_array, new double[] { 0.016, 0.226 }));
40 c.a_double_array = new double[] { 0.582, 0.288, 0.09, 0.213, 0.98 };
41 // property double[3] a_double_array_fixed
42 Debug.Assert(Enumerable.SequenceEqual(c.a_double_array_fixed, new double[] { 0.13, 0.27, 0.15 }));
43 c.a_double_array_fixed = new double[] { 0.21, 0.12, 0.39 };
44 // % property double[6-] a_double_array_maxlen
45 Debug.Assert(Enumerable.SequenceEqual(c.a_double_array_maxlen, new double[] { 0.7, 0.16, 0.16, 0.05, 0.61, 0.9 }));
46 c.a_double_array_maxlen = new double[] { 0.035, 0.4 };
47 // property double[3,2] a_double_marray_fixed
48 var a_double_marray_fixed_read = c.a_double_marray_fixed;
49 Debug.Assert(Enumerable.SequenceEqual(a_double_marray_fixed_read.Dims, new uint[] { 3, 2 }));
50 Debug.Assert(Enumerable.SequenceEqual((double[])a_double_marray_fixed_read.Array_,
51 new double[] { 0.29, 0.41, 0.4, 0.66, 0.6, 0.2 }));
52 c.a_double_marray_fixed = new MultiDimArray(new uint[] { 3, 2 }, new double[] { 0.3, 0.4, 0.5, 0.6, 0.6, 0.2 });
53 // property double[*] a_double_marray
54 var a_double_marray_read = c.a_double_marray;
55 Debug.Assert(Enumerable.SequenceEqual(a_double_marray_read.Dims, new uint[] { 2, 2 }));
56 Debug.Assert(
57 Enumerable.SequenceEqual((double[])a_double_marray_read.Array_, new double[] { 0.72, 0.05, 0.4, 0.07 }));
58 c.a_double_marray = new MultiDimArray(new uint[] { 2, 1 }, new double[] { 0.3, 0.01 });
59 // property uint8[] c_byte_array
60 Debug.Assert(Enumerable.SequenceEqual(c.c_byte_array, new byte[] { 0x1A, 0x2B }));
61 c.c_byte_array = new byte[] { 0x3C, 0x4D, 0x5E, 0x6F, 0x70 };
62}
1// numeric_value_types.cpp - Example of using numeric value types
2
3#include <stdio.h>
4#include <iostream>
5#include <boost/range/algorithm.hpp>
6#include <RobotRaconteur.h>
7#include "robotraconteur_generated.h"
8
9// Only use the RR alias in cpp files. Do not use it in header files.
10namespace RR = RobotRaconteur;
11namespace vt = experimental::value_types;
12
13template <typename T>
14void assert_array(const RR::RRArrayPtr<T>& a, const std::vector<T>& b)
15{
16 assert(a->size() == b.size());
17 // RRArray supports standard C++ iterator interface.
18 // The intrusive_ptr smart pointer
19 // is dereferenced to access the underlying RRArray.
20 assert(boost::range::equal(*a, b));
21}
22
23int main(int argc, char* argv[])
24{
25 RR::ClientNodeSetup node_setup(ROBOTRACONTEUR_SERVICE_TYPES, argc, argv);
26
27 vt::ValueTypesExamplePtr c = RR::rr_cast<vt::ValueTypesExample>(
28 RR::RobotRaconteurNode::s()->ConnectService("rr+tcp://localhost:53223?service=values_example"));
29
30 // Scalar numbers
31 // property double a_double
32 double a_double_read = c->get_a_double();
33 std::cout << a_double_read << std::endl;
34 // assert used for the rest of the example property read operations
35 // to demonstrate the expected values.
36 assert(c->get_a_double() == 5.78);
37 c->set_a_double(49.3);
38 // property int32 b_int
39 assert(c->get_b_int() == 4557);
40 c->set_b_int(359);
41 // property uint8 c_byte
42 assert(c->get_c_byte() == 0x1A);
43 c->set_c_byte(31);
44 // property cdouble d_cdouble
45 assert(c->get_d_cdouble() == RR::cdouble(23.7, 5.3));
46 c->set_d_cdouble(RR::cdouble(1.2, 3.4));
47 // property bool e_bool
48 // RR::rr_bool is used for Robot Raconteur bool values
49 assert(c->get_e_bool().value != 0);
50 c->set_e_bool(RR::rr_bool(0));
51 // property int32 meaning_of_life [readonly]
52 assert(c->get_meaning_of_life() == 42);
53
54 // Numeric Arrays
55 // property double[] a_double_array
56 assert_array(c->get_a_double_array(), {0.016, 0.226});
57
58 // Examples of different ways to initialize RRArray. Also see Eigen converters in robotraconteur-companion
59
60 // Use AttachRRArrayCopy()
61 double a_double_array_1a[] = {0.582, 0.288, 0.09, 0.213, 0.98};
62 RR::RRArrayPtr<double> a_double_array_1 = RR::AttachRRArrayCopy(a_double_array_1a, 5);
63 c->set_a_double_array(a_double_array_1);
64
65 // Use AllocateRRArray to allocate an uninitialized array
66 RR::RRArrayPtr<double> a_double_array_2 = RR::AllocateRRArray<double>(5);
67 a_double_array_2->at(0) = 0.582;
68 a_double_array_2->at(1) = 0.288;
69 a_double_array_2->at(2) = 0.09;
70 a_double_array_2->at(3) = 0.213;
71 a_double_array_2->at(4) = 0.98;
72 c->set_a_double_array(a_double_array_2);
73
74 RR::RRArrayPtr<double> a_double_array_2b = c->get_a_double_array();
75 assert(a_double_array_2b->size() == 2);
76 assert(a_double_array_2b->at(0) == 0.016);
77 assert((*a_double_array_2b)[1] == 0.226);
78
79 // Use VectorToRRArray to convert a std::vector to RRArray
80 std::vector<double> a_double_array_3a = {0.582, 0.288, 0.09, 0.213, 0.98};
81 RR::RRArrayPtr<double> a_double_array_3 = RR::VectorToRRArray<double, double>(a_double_array_3a);
82 c->set_a_double_array(a_double_array_3);
83
84 // property double[3] a_double_array_fixed
85 assert_array(c->get_a_double_array_fixed(), {0.13, 0.27, 0.15});
86 c->set_a_double_array_fixed(RR::VectorToRRArray<double, double>({0.21, 0.12, 0.39}));
87 // % property double[6-] a_double_array_maxlen
88 assert_array(c->get_a_double_array_maxlen(), {0.7, 0.16, 0.16, 0.05, 0.61, 0.9});
89 c->set_a_double_array_maxlen(RR::VectorToRRArray<double, double>({0.035, 0.4}));
90 // property double[3,2] a_double_marray_fixed
91 RR::RRMultiDimArrayPtr<double> a_double_marray_fixed_read = c->get_a_double_marray_fixed();
92 assert_array(a_double_marray_fixed_read->Dims, {3, 2});
93 assert_array(a_double_marray_fixed_read->Array, {0.29, 0.41, 0.4, 0.66, 0.6, 0.2});
94 RR::RRMultiDimArrayPtr<double> a_double_marray_fixed_1 =
95 RR::AllocateRRMultiDimArray<double>(RR::VectorToRRArray<uint32_t, uint32_t>({3, 2}),
96 RR::VectorToRRArray<double, double>({0.3, 0.4, 0.5, 0.6, 0.6, 0.2}));
97 c->set_a_double_marray_fixed(a_double_marray_fixed_1);
98 // property double[*] a_double_marray
99 RR::RRMultiDimArrayPtr<double> a_double_marray_read = c->get_a_double_marray();
100 assert_array(a_double_marray_read->Dims, {2, 2});
101 assert_array(a_double_marray_read->Array, {0.72, 0.05, 0.4, 0.07});
102 RR::RRMultiDimArrayPtr<double> a_double_marray_1 = RR::AllocateRRMultiDimArray<double>(
103 RR::VectorToRRArray<uint32_t, uint32_t>({2, 1}), RR::VectorToRRArray<double, double>({0.3, 0.01}));
104 // property uint8[] c_byte_array
105 assert_array(c->get_c_byte_array(), {0x1A, 0x2B});
106 c->set_c_byte_array(RR::VectorToRRArray<uint8_t, uint8_t>({0x3C, 0x4D, 0x5E, 0x6F, 0x70}));
107
108 std::cout << "numeric_value_types.cpp example complete" << std::endl;
109 return 0;
110}
String Type
Robot Raconteur uses the built-in string types in the client programming language. Note that strings cannot be stored in arrays since internally strings are already stored as arrays of characters.
The following members from the experimental.value_types.ValueTypesExample object are used in the examples
for numeric types:
property string f_string
The examples below show how to use strings in Python, MATLAB, LabView, C#, and C++.
1# string_value_type.py - Example of using string value types
2
3from RobotRaconteur.Client import *
4import numpy as np
5
6c = RRN.ConnectService('rr+tcp://localhost:53223?service=values_example')
7
8# Strings
9# property string f_string
10f_string_read = c.f_string
11print(f_string_read)
12# assert is used for the rest of the example property read operations
13# to demonstrate the expected values.
14assert (c.f_string == "An example string read from the service")
15c.f_string = "An example string written to the service"
1% string_value_type.m - Example of using string value types
2
3c = RobotRaconteur.ConnectService('rr+tcp://localhost:53223?service=values_example');
4
5% Strings
6% property string f_string
7f_string_read = c.f_string;
8disp(f_string_read);
9% assert is used for the rest of the example property read operations
10% to demonstrate the expected values.
11assert (strcmp(c.f_string, 'An example string read from the service'));
12c.f_string = 'An example string written to the service';
13
14RobotRaconteur.DisconnectService(c);
1// string_value_type.cs - Example of using string value types
2
3using RobotRaconteur;
4using System;
5using System.Diagnostics;
6using System.Linq;
7
8using (var node_setup = new ClientNodeSetup(args))
9{
10
11 var c = (experimental.value_types.ValueTypesExample)RobotRaconteurNode.s.ConnectService(
12 "rr+tcp://localhost:53223?service=values_example");
13
14 // Strings
15 // property string f_string
16 var f_string_read = c.f_string;
17 Console.WriteLine(f_string_read);
18 // assert is used for the rest of the example property read operations
19 // to demonstrate the expected values.
20 Debug.Assert(c.f_string == "An example string read from the service");
21 c.f_string = "An example string written to the service";
22}
1// string_value_type.cpp - Example of using string value types
2
3#include <stdio.h>
4#include <iostream>
5#include <boost/range/algorithm.hpp>
6#include <RobotRaconteur.h>
7#include "robotraconteur_generated.h"
8
9// Only use the RR alias in cpp files. Do not use it in header files.
10namespace RR = RobotRaconteur;
11namespace vt = experimental::value_types;
12
13int main(int argc, char* argv[])
14{
15 RR::ClientNodeSetup node_setup(ROBOTRACONTEUR_SERVICE_TYPES, argc, argv);
16
17 vt::ValueTypesExamplePtr c = RR::rr_cast<vt::ValueTypesExample>(
18 RR::RobotRaconteurNode::s()->ConnectService("rr+tcp://localhost:53223?service=values_example"));
19
20 // Strings
21 // property string f_string
22 std::string f_string_read = c->get_f_string();
23 std::cout << f_string_read << std::endl;
24 // assert is used for the rest of the example property read operations
25 // to demonstrate the expected values.
26 assert(c->get_f_string() == "An example string read from the service");
27 c->set_f_string("An example string written to the service");
28
29 std::cout << "string_value_type.cpp example complete" << std::endl;
30 return 0;
31}
Structure Types
Structures are a collection of fields that can contain any value type, including itself. Structures
are defined using the Robot Raconteur “Service Definitions” format. Structures are nullable. The following examples
demonstrate using the experimental.value_types.MyStructure structure type:
# Structure examples.
struct MyStructure
# struct fields can be any value type
field double a
field uint32[2] b
field string c
field string{list} d
end
The following members from the experimental.value_types.ValueTypesExample object are used in the examples
for structure types:
property MyStructure k_struct
The examples below show how to use structures in Python, MATLAB, LabView, C#, and C++.
1# struct_value_type.py - Simple example of using struct value types
2
3from RobotRaconteur.Client import *
4import numpy as np
5
6c = RRN.ConnectService('rr+tcp://localhost:53223?service=values_example')
7
8# Example using MyStructure type. Also see example
9# using MyStructure for a more complex example.
10
11# Retrieve the structure type. obj is only used
12# for clients. It is omitted for services.
13my_structure_type = RRN.GetStructureType("experimental.value_types.MyStructure", obj=c)
14
15# Create and populate a MyStructure
16s = my_structure_type()
17# field double a
18s.a = 5
19# field uint32[2] b
20s.b = np.array([10, 20], dtype=np.uint32)
21# field string c
22s.c = "String from structure client"
23# field string{list} d
24s.d = [
25 "string a",
26 "string b"
27]
28
29# Set the property using the structure
30# property MyStructure k_struct
31c.k_struct = s
32
33# Retrieve the structure from the service
34u = c.k_struct
35
36# Structures can be None
37assert u is not None
38
39# field double a
40assert (u.a == 52)
41# field uint32[2] b
42np.testing.assert_array_equal(u.b, np.array([110, 120], dtype=np.uint32))
43# field string c
44assert (u.c == "String from structure service")
45# field string{list} d
46assert (len(u.d) == 3)
47assert (u.d[0] == "string c")
48assert (u.d[1] == "string d")
49assert (u.d[2] == "string e")
1% struct_value_type.m - Simple example of using struct value types
2
3c = RobotRaconteur.ConnectService('rr+tcp://localhost:53223?service=values_example');
4
5% Create and populate a MyStructure
6s = RobotRaconteur.CreateStructure(c, 'experimental.value_types.MyStructure');
7% field double a
8s.a = 5;
9% field uint32[2] b
10s.b = uint32([10, 20]');
11% field string c
12s.c = 'String from structure client';
13% field string{list} d
14s.d = {'string a','string b'}';
15
16
17% Set the property using the structure
18% property MyStructure k_struct
19c.k_struct = s;
20
21% Retrieve the structure from the service
22u = c.k_struct;
23
24% Structures can be None
25assert(~ismissing(u));
26
27% field double a
28assert (u.a == 52);
29% field uint32[2] b
30assert(isequal(u.b, [110, 120]'));
31% field string c
32assert (strcmp(u.c, 'String from structure service'));
33% field string{list} d
34assert (length(u.d) == 3);
35assert (strcmp(u.d{1}, 'string c'));
36assert (strcmp(u.d{2}, 'string d'));
37assert (strcmp(u.d{3}, 'string e'));
38
39RobotRaconteur.DisconnectService(c);
1// struct_value_type.cs - Simple example of using struct value types
2
3using RobotRaconteur;
4using System;
5using System.Diagnostics;
6using System.Linq;
7using experimental.value_types;
8
9using (var node_setup = new ClientNodeSetup(args))
10{
11 var c = (experimental.value_types.ValueTypesExample)RobotRaconteurNode.s.ConnectService(
12 "rr+tcp://localhost:53223?service=values_example");
13
14 // Create and populate a MyStructure
15 var s = new MyStructure();
16 // field double a
17 s.a = 5;
18 // field uint32[2] b
19 s.b = new uint[] { 10, 20 };
20 // field string c
21 s.c = "String from structure client";
22 // field string{list} d
23 s.d = new List<string>( { "string a", "string b" });
24
25 // Set the property using the structure
26 // property MyStructure k_struct
27 c.k_struct = s;
28
29 // Retrieve the structure from the service
30 var u = c.k_struct;
31
32 // Structures can be None
33 Debug.Assert(u != null);
34
35 // field double a
36 Debug.Assert(u.a == 52);
37 // field uint32[2] b
38 Debug.Assert(Enumerable.SequenceEqual(u.b, new uint[] { 110, 120 }));
39 // field string c
40 Debug.Assert(u.c == "String from structure service");
41 // field string{list} d
42 Debug.Assert(Enumerable.SequenceEqual(u.d, new List<string>( { "string c", "string d", "string e" })));
43}
1// struct_value_type.cpp - Simple example of using struct value types
2
3#include <stdio.h>
4#include <iostream>
5#include <boost/range/algorithm.hpp>
6#include <RobotRaconteur.h>
7#include "robotraconteur_generated.h"
8
9// Only use the RR alias in cpp files. Do not use it in header files.
10namespace RR = RobotRaconteur;
11namespace vt = experimental::value_types;
12
13template <typename T>
14void assert_array(const RR::RRArrayPtr<T>& a, const std::vector<T>& b)
15{
16 assert(a->size() == b.size());
17 // RRArray supports standard C++ iterator interface.
18 // The intrusive_ptr smart pointer
19 // is dereferenced to access the underlying RRArray.
20 assert(boost::range::equal(*a, b));
21}
22
23int main(int argc, char* argv[])
24{
25 RR::ClientNodeSetup node_setup(ROBOTRACONTEUR_SERVICE_TYPES, argc, argv);
26
27 vt::ValueTypesExamplePtr c = RR::rr_cast<vt::ValueTypesExample>(
28 RR::RobotRaconteurNode::s()->ConnectService("rr+tcp://localhost:53223?service=values_example"));
29
30 // Create and populate a MyStructure
31 vt::MyStructurePtr s(new vt::MyStructure());
32 // field double a
33 s->a = 5;
34 // field uint32[2] b
35 s->b = RR::VectorToRRArray<uint32_t, uint32_t>({10, 20});
36 // field string c
37 s->c = "String from structure client";
38 // field string{list} d
39 // Strings are stored in RRArray<char> when stored in containers
40 RR::RRListPtr<RR::RRArray<char> > d1 = RR::AllocateEmptyRRList<RR::RRArray<char> >();
41 d1->push_back(RR::stringToRRArray("string a"));
42 d1->push_back(RR::stringToRRArray("string b"));
43 s->d = d1;
44
45 // Set the property using the structure
46 // property MyStructure k_struct
47 c->set_k_struct(s);
48
49 // Retrieve the structure from the service
50 vt::MyStructurePtr u = c->get_k_struct();
51
52 // Structures can be None
53 RR::rr_null_check(u);
54
55 // field double a
56 assert(u->a == 52);
57 // field uint32[2] b
58 assert_array(u->b, {110, 120});
59 // field string c
60 assert(u->c == "String from structure service");
61 // field string{list} d
62 // Containers can be null
63 RR::rr_null_check(u->d);
64 assert(u->d->size() == 3);
65 auto d2_iterator = u->d->begin();
66 assert(RR::RRArrayToString(*d2_iterator++) == "string c");
67 assert(RR::RRArrayToString(*d2_iterator++) == "string d");
68 assert(RR::RRArrayToString(*d2_iterator++) == "string e");
69
70 std::cout << "struct_value_types.cpp example complete" << std::endl;
71 return 0;
72}
Pod Types
Pods are a collections of fields that have a fixed memory layout. Pods have a restricted set of allowed
field types including numbers, arrays, namedarrays, and other pods. See the
Robot Raconteur Framework Service Definition Documentation
for more information about the allowed contents of pods. Unlike structures, pods store all their
data within the pod itself in contiguous memory, and do not contain pointers to other data. They are guaranteed
to have a maximum binary size. The following examples
demonstrate using the experimental.value_types.MyPod pod type:
# Pod example. Only numeric types, other pods, and namedarrays can
# be used in a pod. All arrays must have a fixed or maximum length.
# Multidimarrays must be fixed. Pods have a fixed maximum binary
# size to fit in contiguous memory. Pods do not
# have to have the same underlying numeric type for all the
# fields.
pod MyPod
field double a
field int32 b
field uint8[4] c
field uint8[4-] d
field uint16[2,3] e
field MyVector3 f
end
The following members from the experimental.value_types.ValueTypesExample object are used in the examples
for pod types:
# Examples using pods
property MyPod j_pod
property MyPod[] j_pod_array
The examples below show how to use pods in Python, MATLAB, LabView, C#, and C++.
1# pod_value_types.py - Example of using pod value types
2
3from RobotRaconteur.Client import *
4import numpy as np
5
6c = RRN.ConnectService('rr+tcp://localhost:53223?service=values_example')
7
8# Example using Pod numpy dtypes. Pods are represented as NumPy dtypes with fields
9# obj is only used for clients. It is omitted for services.
10my_pod_dtype = RRN.GetPodDType("experimental.value_types.MyPod", obj=c)
11
12# property MyPod j_pod
13a = np.zeros((1,), dtype=my_pod_dtype)
14a[0]["a"] = 0.928
15a[0]["b"] = 8374
16a[0]["c"] = [8, 9, 10, 11]
17# Max length fields are stored with a length field and
18# data field.
19a[0]["d"]["len"] = 1
20a[0]["d"]["array"][0] = 17
21a[0]["e"] = [[1, 2, 3], [4, 5, 6]]
22a[0]["f"]["x"] = 10.1
23a[0]["f"]["y"] = 10.2
24a[0]["f"]["z"] = 10.3
25c.j_pod = a
26
27b = c.j_pod
28assert (b[0]["a"] == 0.791)
29assert (b[0]["b"] == 1077)
30np.testing.assert_array_equal(b[0]["c"], [61, 52, 33, 24])
31assert (b[0]["d"]["len"] == 2)
32np.testing.assert_array_equal(b[0]["d"]["array"][0:2], [1, 2])
33np.testing.assert_array_equal(b[0]["e"], [[7, 8, 9], [10, 11, 12]])
34assert (b[0]["f"]["x"] == 20.1)
35assert (b[0]["f"]["y"] == 20.2)
36assert (b[0]["f"]["z"] == 20.3)
37
38# Now an array of Pods
39# property MyPod[] j_pod_array
40d = np.zeros((2,), dtype=my_pod_dtype)
41d[0]["a"] = 0.928
42d[0]["b"] = 8374
43d[0]["c"] = [8, 9, 10, 11]
44d[0]["d"]["len"] = 1
45d[0]["d"]["array"][0] = 17
46d[0]["e"] = [[1, 2, 3], [4, 5, 6]]
47d[0]["f"]["x"] = 10.1
48d[0]["f"]["y"] = 10.2
49d[0]["f"]["z"] = 10.3
50d[1]["a"] = 0.67
51d[1]["b"] = 123
52d[1]["c"] = [1, 2, 3, 4]
53d[1]["d"]["len"] = 2
54d[1]["d"]["array"][0:2] = [5, 6]
55d[1]["e"] = [[13, 14, 15], [16, 17, 18]]
56d[1]["f"]["x"] = 30.1
57d[1]["f"]["y"] = 30.2
58d[1]["f"]["z"] = 30.3
59c.j_pod_array = d
60
61e = c.j_pod_array
62assert (e[0]["a"] == 0.791)
63assert (e[0]["b"] == 1077)
64np.testing.assert_array_equal(e[0]["c"], [61, 52, 33, 24])
65assert (e[0]["d"]["len"] == 2)
66np.testing.assert_array_equal(e[0]["d"]["array"][0:2], [1, 2])
67np.testing.assert_array_equal(e[0]["e"], [[7, 8, 9], [10, 11, 12]])
68assert (e[0]["f"]["x"] == 20.1)
69assert (e[0]["f"]["y"] == 20.2)
70assert (e[0]["f"]["z"] == 20.3)
71assert (e[1]["a"] == 0.03)
72assert (e[1]["b"] == 693)
73np.testing.assert_array_equal(e[1]["c"], [5, 6, 7, 8])
74assert (e[1]["d"]["len"] == 1)
75np.testing.assert_array_equal(e[1]["d"]["array"][0:1], [3])
76np.testing.assert_array_equal(e[1]["e"], [[19, 20, 21], [22, 23, 24]])
77assert (e[1]["f"]["x"] == 40.1)
78assert (e[1]["f"]["y"] == 40.2)
79assert (e[1]["f"]["z"] == 40.3)
1% pod_value_types.m - Example of using pod value types
2
3c = RobotRaconteur.ConnectService('rr+tcp://localhost:53223?service=values_example');
4
5% Example using Pods. Pods are represented as Matlab struct
6
7% property MyPod j_pod
8a = struct;
9a.a = 0.928;
10a.b = int32(8374);
11a.c = uint8([8, 9, 10, 11]');
12a.d = uint8(17);
13a.e = uint16([1, 2, 3; 4, 5, 6]);
14a.f = [10.1, 10.2, 10.3]';
15c.j_pod = a;
16
17b = c.j_pod;
18assert (b.a == 0.791)
19assert (b.b == 1077)
20assert(isequal(b.c, [61, 52, 33, 24]'));
21assert(isequal(b.d, [1, 2]'));
22assert(isequal(b.e, [7, 8, 9; 10, 11, 12]));
23assert (isequal(b.f, [20.1, 20.2, 20.3]'));
24
25% Now an array of Pods
26% property MyPod[] j_pod_array
27d = struct;
28d.a = 0.928;
29d.b = int32(8374);
30d.c = uint8([8, 9, 10, 11]');
31d.d = uint8(17);
32d.e = uint16([1, 2, 3; 4, 5, 6]);
33d.f = [10.1, 10.2, 10.3]';
34d2 = struct;
35d2.a = 0.67;
36d2.b = int32(123);
37d2.c = uint8([1, 2, 3, 4]');
38d2.d = uint8([5, 6]');
39d2.e = uint16([13, 14, 15; 16, 17, 18]);
40d2.f = [30.1, 30.2, 30.3]';
41d(2,1) = d2;
42c.j_pod_array = d;
43
44e = c.j_pod_array;
45assert(e(1).a == 0.791);
46assert(e(1).b == 1077);
47assert(isequal(e(1).c, [61, 52, 33, 24]'));
48assert(isequal(e(1).d, [1, 2]'));
49assert(isequal(e(1).e, [7, 8, 9; 10, 11, 12]));
50assert(isequal(e(1).f, [20.1, 20.2, 20.3]'));
51assert(e(2).a == 0.03);
52assert(e(2).b == 693);
53assert(isequal(e(2).c, [5, 6, 7, 8]'));
54assert(isequal(e(2).d, 3));
55assert(isequal(e(2).e, [19, 20, 21; 22, 23, 24]));
56assert(isequal(e(2).f, [40.1, 40.2, 40.3]'));
57
58RobotRaconteur.DisconnectService(c);
1// pod_value_types.cs - Example of using pod value types
2
3using RobotRaconteur;
4using System;
5using System.Diagnostics;
6using System.Linq;
7using experimental.value_types;
8
9using (var node_setup = new ClientNodeSetup(args))
10{
11 var c = (experimental.value_types.ValueTypesExample)RobotRaconteurNode.s.ConnectService(
12 "rr+tcp://localhost:53223?service=values_example");
13
14 // Example using Pods
15
16 // property MyPod j_pod
17 var a = new MyPod() { a = 0.928,
18 b = 8374,
19 c = new byte[] { 8, 9, 10, 11 },
20 d = new byte[] { 17 },
21 e = new ushort[] { 1, 4, 2, 5, 3, 6 },
22 f = new MyVector3() { x = 10.1, y = 10.2, z = 10.3 } };
23 c.j_pod = a;
24
25 var b = c.j_pod;
26 Debug.Assert(b.a == 0.791);
27 Debug.Assert(b.b == 1077);
28 Debug.Assert(Enumerable.SequenceEqual(b.c, new byte[] { 61, 52, 33, 24 }));
29 Debug.Assert(Enumerable.SequenceEqual(b.d, new byte[] { 1, 2 }));
30 Debug.Assert(Enumerable.SequenceEqual(b.e, new ushort[] { 7, 10, 8, 11, 9, 12 }));
31 Debug.Assert(b.f.x == 20.1);
32 Debug.Assert(b.f.y == 20.2);
33 Debug.Assert(b.f.z == 20.3);
34
35 // Now an array of Pods
36 // property MyPod[] j_pod_array
37 var d = new MyPod[] { new MyPod() { a = 0.928, b = 8374, c = new byte[] { 8, 9, 10, 11 }, d = new byte[] { 17 },
38 e = new ushort[] { 1, 4, 2, 5, 3, 6 },
39 f = new MyVector3() { x = 10.1, y = 10.2, z = 10.3 } },
40 new MyPod() { a = 0.67, b = 123, c = new byte[] { 1, 2, 3, 4 }, d = new byte[] { 5, 6 },
41 e = new ushort[] { 13, 16, 14, 17, 15, 18 },
42 f = new MyVector3() { x = 30.1, y = 30.2, z = 30.3 } } };
43 c.j_pod_array = d;
44
45 var e = c.j_pod_array;
46 Debug.Assert(e[0].a == 0.791);
47 Debug.Assert(e[0].b == 1077);
48 Debug.Assert(Enumerable.SequenceEqual(e[0].c, new byte[] { 61, 52, 33, 24 }));
49 Debug.Assert(Enumerable.SequenceEqual(e[0].d, new byte[] { 1, 2 }));
50 Debug.Assert(Enumerable.SequenceEqual(e[0].e, new ushort[] { 7, 10, 8, 11, 9, 12 }));
51 Debug.Assert(e[0].f.x == 20.1);
52 Debug.Assert(e[0].f.y == 20.2);
53 Debug.Assert(e[0].f.z == 20.3);
54 Debug.Assert(e[1].a == 0.03);
55 Debug.Assert(e[1].b == 693);
56 Debug.Assert(Enumerable.SequenceEqual(e[1].c, new byte[] { 5, 6, 7, 8 }));
57 Debug.Assert(Enumerable.SequenceEqual(e[1].d, new byte[] { 3 }));
58 Debug.Assert(Enumerable.SequenceEqual(e[1].e, new ushort[] { 19, 22, 20, 23, 21, 24 }));
59 Debug.Assert(e[1].f.x == 40.1);
60 Debug.Assert(e[1].f.y == 40.2);
61 Debug.Assert(e[1].f.z == 40.3);
62}
1// pod_value_types.cpp - Example of using pod value types
2
3#include <stdio.h>
4#include <iostream>
5#include <boost/range/algorithm.hpp>
6#include <RobotRaconteur.h>
7#include "robotraconteur_generated.h"
8
9// Only use the RR alias in cpp files. Do not use it in header files.
10namespace RR = RobotRaconteur;
11namespace vt = experimental::value_types;
12
13template <typename T>
14void assert_array(const RR::RRArrayPtr<T>& a, const std::vector<T>& b)
15{
16 assert(a->size() == b.size());
17 // RRArray supports standard C++ iterator interface.
18 // The intrusive_ptr smart pointer
19 // is dereferenced to access the underlying RRArray.
20 assert(boost::range::equal(*a, b));
21}
22
23int main(int argc, char* argv[])
24{
25 RR::ClientNodeSetup node_setup(ROBOTRACONTEUR_SERVICE_TYPES, argc, argv);
26
27 vt::ValueTypesExamplePtr c = RR::rr_cast<vt::ValueTypesExample>(
28 RR::RobotRaconteurNode::s()->ConnectService("rr+tcp://localhost:53223?service=values_example"));
29
30 // Example using Pods
31
32 // property MyPod j_pod
33 vt::MyPod a;
34 a.a = 0.928;
35 a.b = 8374;
36 a.c[0] = 8;
37 a.c[1] = 9;
38 a.c[2] = 10;
39 a.c[3] = 11;
40 a.d.resize(1);
41 a.d[0] = 17;
42 double a_e[6] = {1, 4, 2, 5, 3, 6};
43 memcpy(&a.e[0], a_e, sizeof(a_e));
44 a.f.s.x = 10.1;
45 a.f.s.y = 10.2;
46 a.f.s.z = 10.3;
47 c->set_j_pod(a);
48
49 vt::MyPod b = c->get_j_pod();
50 assert(b.a == 0.791);
51 assert(b.b == 1077);
52 double b_c[4] = {61, 52, 33, 24};
53 assert(memcmp(&b.c[0], b_c, sizeof(b_c)) == 0);
54 assert(b.d.size() == 2);
55 double b_d[2] = {1, 2};
56 assert(memcmp(&b.d[0], b_d, sizeof(b_d)) == 0);
57 double b_e[6] = {7, 10, 8, 11, 9, 12};
58 assert(memcmp(&b.e[0], b_e, sizeof(b_e)) == 0);
59 vt::MyVector3 b_f = b.f;
60 assert(b_f.s.x == 20.1);
61 assert(b_f.s.y == 20.2);
62 assert(b_f.s.z == 20.3);
63
64 // Now an array of Pods
65 // property MyPod[] j_pod_array
66 RR::RRPodArrayPtr<vt::MyPod> d = RR::AllocateEmptyRRPodArray<vt::MyPod>(2);
67 d->at(0).a = 0.928;
68 d->at(0).b = 8374;
69 double d0_c[] = {8, 9, 10, 11};
70 memcpy(&d->at(0).c[0], d0_c, sizeof(d0_c));
71 d->at(0).d.resize(1);
72 d->at(0).d[0] = 17;
73 double d0_e[6] = {1, 4, 2, 5, 3, 6};
74 memcpy(&d->at(0).e[0], d0_e, sizeof(d0_e));
75 d->at(0).f.s.x = 10.1;
76 d->at(0).f.s.y = 10.2;
77 d->at(0).f.s.z = 10.3;
78
79 d->at(1).a = 0.67;
80 d->at(1).b = 123;
81 double d1_c[] = {1, 2, 3, 4};
82 memcpy(&d->at(1).c[0], d1_c, sizeof(d1_c));
83 d->at(1).d.resize(2);
84 double d1_d[] = {5, 6};
85 memcpy(&d->at(1).d[0], d1_d, sizeof(d1_d));
86 double d1_e[6] = {13, 16, 14, 17, 15, 18};
87 memcpy(&d->at(1).e[0], d1_e, sizeof(d1_e));
88 d->at(1).f.s.x = 30.1;
89 d->at(1).f.s.y = 30.2;
90 d->at(1).f.s.z = 30.3;
91
92 c->set_j_pod_array(d);
93
94 RR::RRPodArrayPtr<vt::MyPod> f = c->get_j_pod_array();
95 assert(f->size() == 2);
96 assert(f->at(0).a == 0.791);
97 assert(f->at(0).b == 1077);
98 double f0_c[4] = {61, 52, 33, 24};
99 assert(memcmp(&f->at(0).c[0], f0_c, sizeof(f0_c)) == 0);
100 assert(f->at(0).d.size() == 2);
101 double f0_d[2] = {1, 2};
102 assert(memcmp(&f->at(0).d[0], f0_d, sizeof(f0_d)) == 0);
103 double f0_e[6] = {7, 10, 8, 11, 9, 12};
104 assert(memcmp(&f->at(0).e[0], f0_e, sizeof(f0_e)) == 0);
105 vt::MyVector3 f0_f = f->at(0).f;
106 assert(f0_f.s.x == 20.1);
107 assert(f0_f.s.y == 20.2);
108 assert(f0_f.s.z == 20.3);
109
110 assert(f->at(1).a == 0.03);
111 assert(f->at(1).b == 693);
112 double f1_c[4] = {5, 6, 7, 8};
113 assert(memcmp(&f->at(1).c[0], f1_c, sizeof(f1_c)) == 0);
114 assert(f->at(1).d.size() == 1);
115 double f1_d[1] = {3};
116 assert(memcmp(&f->at(1).d[0], f1_d, sizeof(f1_d)) == 0);
117 double f1_e[6] = {19, 22, 20, 23, 21, 24};
118 assert(memcmp(&f->at(1).e[0], f1_e, sizeof(f1_e)) == 0);
119 vt::MyVector3 f1_f = f->at(1).f;
120 assert(f1_f.s.x == 40.1);
121 assert(f1_f.s.y == 40.2);
122 assert(f1_f.s.z == 40.3);
123
124 std::cout << "pod_value_types.cpp example complete" << std::endl;
125 return 0;
126}
NamedArray Types
Namedarrays represent a union type between a structure and a numeric array. A vector is an example
of a type that can be represented either as a structure with three fields, or as a numeric array with
three elements. Namedarrays are very efficient compared to the other data types since they can
be transmitted or manipulated as a plain array. All fields in the namedarray must have
the same numeric type. Other namedarrays and arrays may also be used as fields, but they must
have the same underlying numeric type and a fixed size. The following examples demonstrate using the
experimental.value_types.MyVector3, experimental.value_types.MyQuaternion, and experimental.value_types.MyPose
namedarray types:
# Example vector namedarray. Note that all fields must
# have the same underlying numeric type
namedarray MyVector3
field double x
field double y
field double z
end
namedarray MyQuaternion
field double w
field double x
field double y
field double z
end
# Example pose namedarray using composition of other namedarrays.
# All underlying fields must have the same numeric type.
namedarray MyPose
field MyQuaternion orientation
field MyVector3 position
end
The following members from the experimental.value_types.ValueTypesExample object are used in the examples
for namedarray types:
# Examples using namedarray
property MyVector3 g_vector
property MyVector3[] g_vector_array
property MyQuaternion h_quaternion
property MyPose i_pose
The examples below show how to use namedarrays in Python, MATLAB, LabView, C#, and C++.
1# namedarray_value_types.py - Example of using namedarray value types
2
3from RobotRaconteur.Client import *
4import numpy as np
5
6c = RRN.ConnectService('rr+tcp://localhost:53223?service=values_example')
7
8# Retrieve NamedArray numpy dtypes. NamedArrays are represented as NumPy dtypes with fields
9# obj is only used for clients. It is omitted for services.
10my_vector3_dtype = RRN.GetNamedArrayDType("experimental.value_types.MyVector3", obj=c)
11my_quaternion_dtype = RRN.GetNamedArrayDType("experimental.value_types.MyQuaternion", obj=c)
12my_pose_dtype = RRN.GetNamedArrayDType("experimental.value_types.MyPose", obj=c)
13
14# NumPy structures are used to represent NamedArrays.
15# These structures can also be converted to and from plain arrays of the
16# underlying numeric type using RRN.NamedArrayToArray() and RRN.ArrayToNamedArray().
17# Scalar NamedArrays are represented as arrays with a single element.
18
19# property MyVector3 g_vector
20a = np.zeros((1,), dtype=my_vector3_dtype)
21a[0]["x"] = 1.0
22a[0]["y"] = 2.0
23a[0]["z"] = 3.0
24c.g_vector = a
25
26b = c.g_vector
27assert (b[0]["x"] == 4.0)
28assert (b[0]["y"] == 5.0)
29assert (b[0]["z"] == 6.0)
30
31# Use plain arrays and convert to and from NamedArrays
32d = np.array([1.0, 2.0, 3.0], dtype=np.float64)
33c.g_vector = RRN.ArrayToNamedArray(d, named_array_dt=my_vector3_dtype)
34e = RRN.NamedArrayToArray(c.g_vector)
35np.testing.assert_array_equal(e, [[4.0, 5.0, 6.0]])
36
37# Now an array of NamedArrays
38# property MyVector3[] g_vector_array
39f = np.zeros((2,), dtype=my_vector3_dtype)
40f[0]["x"] = 1.0
41f[0]["y"] = 2.0
42f[0]["z"] = 3.0
43f[1]["x"] = 4.0
44f[1]["y"] = 5.0
45f[1]["z"] = 6.0
46c.g_vector_array = f
47
48g = c.g_vector_array
49assert (g[0]["x"] == 7.0)
50assert (g[0]["y"] == 8.0)
51assert (g[0]["z"] == 9.0)
52assert (g[1]["x"] == 10.0)
53assert (g[1]["y"] == 11.0)
54assert (g[1]["z"] == 12.0)
55
56# Use plain arrays and convert to and from NamedArrays
57h = np.array([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]], dtype=np.float64)
58c.g_vector_array = RRN.ArrayToNamedArray(h, named_array_dt=my_vector3_dtype)
59i = RRN.NamedArrayToArray(c.g_vector_array)
60np.testing.assert_array_equal(i, [[7.0, 8.0, 9.0], [10.0, 11.0, 12.0]])
61
62# property MyQuaternion h_quaternion
63j = np.zeros((1,), dtype=my_quaternion_dtype)
64j[0]["w"] = 1.0
65j[0]["x"] = 0.0
66j[0]["y"] = 0.0
67j[0]["z"] = 0.0
68c.h_quaternion = j
69
70k = c.h_quaternion
71assert (k[0]["w"] == 0.707)
72assert (k[0]["x"] == 0.0)
73assert (k[0]["y"] == 0.707)
74assert (k[0]["z"] == 0.0)
75
76# MyPose is a composite NamedArray with fields of other NamedArrays
77# property MyPose l_pose
78l = np.zeros((1,), dtype=my_pose_dtype)
79l[0]["orientation"]["w"] = 1.0
80l[0]["orientation"]["x"] = 0.0
81l[0]["orientation"]["y"] = 0.0
82l[0]["orientation"]["z"] = 0.0
83l[0]["position"]["x"] = 1.0
84l[0]["position"]["y"] = 2.0
85l[0]["position"]["z"] = 3.0
86c.i_pose = l
87
88m = c.i_pose
89assert (m[0]["orientation"]["w"] == 0.707)
90assert (m[0]["orientation"]["x"] == 0.0)
91assert (m[0]["orientation"]["y"] == 0.707)
92assert (m[0]["orientation"]["z"] == 0.0)
93assert (m[0]["position"]["x"] == 4.0)
94assert (m[0]["position"]["y"] == 5.0)
95assert (m[0]["position"]["z"] == 6.0)
96
97# Use plain arrays and convert to and from NamedArrays
98n = np.array([1.0, 0.0, 0.0, 0.0, 1.0, 2.0, 3.0,], dtype=np.float64)
99c.i_pose = RRN.ArrayToNamedArray(n, named_array_dt=my_pose_dtype)
100o = RRN.NamedArrayToArray(c.i_pose)
101np.testing.assert_array_equal(o, [[0.707, 0.0, 0.707, 0.0, 4.0, 5.0, 6.0]])
1% namedarray_value_types.m - Example of using namedarray value types
2
3c = RobotRaconteur.ConnectService('rr+tcp://localhost:53223?service=values_example');
4
5% Robot Raconteur uses the array format for namedarray in Matlab
6
7% property MyVector3 g_vector
8
9c.g_vector = [1.0, 2.0, 3.0]';
10b=c.g_vector;
11assert (isequal(b,[4.0, 5.0, 6.0]'));
12
13% Now an array of NamedArrays
14% property MyVector3[] g_vector_array
15f = [1.0,2.0,3.0;4.0,5.0,6.0]';
16c.g_vector_array = f;
17
18g = c.g_vector_array;
19assert(isequal(g,[7.0,8.0,9.0;10.0,11.0,12.0]'));
20
21% property MyQuaternion h_quaternion
22j = [1.0, 0.0, 0.0, 0.0]';
23c.h_quaternion = j;
24
25k = c.h_quaternion;
26assert(isequal(k, [0.707, 0.0, 0.707, 0.0]'));
27
28% MyPose is a composite NamedArray with fields of other NamedArrays
29% property MyPose l_pose
30l = [1.0, 0.0, 0.0, 0.0, 1.0, 2.0, 3.0]';
31c.i_pose = l;
32
33m = c.i_pose;
34assert(isequal(m, [0.707, 0.0, 0.707, 0.0, 4.0, 5.0, 6.0]'));
35
36RobotRaconteur.DisconnectService(c);
1// namedarray_value_types.cs - Example of using namedarray value types
2
3using RobotRaconteur;
4using System;
5using System.Diagnostics;
6using System.Linq;
7using experimental.value_types;
8
9using (var node_setup = new ClientNodeSetup(args))
10{
11 var c = (experimental.value_types.ValueTypesExample)RobotRaconteurNode.s.ConnectService(
12 "rr+tcp://localhost:53223?service=values_example");
13
14 // property MyVector3 g_vector
15 c.g_vector = new MyVector3 { x = 1.0, y = 2.0, z = 3.0 };
16 var b = c.g_vector;
17 Debug.Assert(b.x == 4.0);
18 Debug.Assert(b.y == 5.0);
19 Debug.Assert(b.z == 6.0);
20
21 // Now an array of NamedArrays
22 // property MyVector3[] g_vector_array
23 var f =
24 new MyVector3[] { new MyVector3 { x = 1.0, y = 2.0, z = 3.0 }, new MyVector3 { x = 4.0, y = 5.0, z = 6.0 } };
25 c.g_vector_array = f;
26
27 var g = c.g_vector_array;
28 Debug.Assert(g.Length == 2);
29 Debug.Assert(g[0].x == 7.0);
30 Debug.Assert(g[0].y == 8.0);
31 Debug.Assert(g[0].z == 9.0);
32 Debug.Assert(g[1].x == 10.0);
33 Debug.Assert(g[1].y == 11.0);
34 Debug.Assert(g[1].z == 12.0);
35
36 // Use plain arrays and convert to and from NamedArrays
37 var d = new MyVector3();
38 var d1 = new ArraySegment<double>(new double[] { 1.0, 2.0, 3.0 });
39 d.AssignFromNumericArray(ref d1);
40 c.g_vector = d;
41 var e = c.g_vector;
42 var e1 = new ArraySegment<double>(new double[3]);
43 e.GetNumericArray(ref e1);
44 Debug.Assert(Enumerable.SequenceEqual(e1.Array, new double[] { 4.0, 5.0, 6.0 }));
45
46 // property MyQuaternion h_quaternion
47 var j = new MyQuaternion() { w = 1.0, x = 0.0, y = 0.0, z = 0.0 };
48 c.h_quaternion = j;
49
50 var k = c.h_quaternion;
51 Debug.Assert(k.w == 0.707);
52 Debug.Assert(k.x == 0.0);
53 Debug.Assert(k.y == 0.707);
54 Debug.Assert(k.z == 0.0);
55
56 // MyPose is a composite NamedArray with fields of other NamedArrays
57 // property MyPose l_pose
58 var l = new MyPose() { orientation = new MyQuaternion() { w = 1.0, x = 0.0, y = 0.0, z = 0.0 },
59 position = new MyVector3() { x = 1.0, y = 2.0, z = 3.0 } };
60
61 c.i_pose = l;
62
63 var m = c.i_pose;
64 Debug.Assert(m.position.x == 4.0);
65 Debug.Assert(m.position.y == 5.0);
66 Debug.Assert(m.position.z == 6.0);
67 Debug.Assert(m.orientation.w == 0.707);
68 Debug.Assert(m.orientation.x == 0.0);
69 Debug.Assert(m.orientation.y == 0.707);
70 Debug.Assert(m.orientation.z == 0.0);
71
72 // Now use plain arrays and convert to and from NamedArrays
73 var n = new MyPose();
74 var n1 = new ArraySegment<double>(new double[] { 1.0, 0.0, 0.0, 0.0, 1.0, 2.0, 3.0 });
75 n.AssignFromNumericArray(ref n1);
76 c.i_pose = n;
77
78 var o = c.i_pose;
79 Debug.Assert(Enumerable.SequenceEqual(o.GetNumericArray(), new double[] { 0.707, 0.0, 0.707, 0.0, 4.0, 5.0, 6.0 }));
80}
1// namedarray_value_types.cpp - Example of using namedarray value types
2
3#include <stdio.h>
4#include <iostream>
5#include <boost/range/algorithm.hpp>
6#include <RobotRaconteur.h>
7#include "robotraconteur_generated.h"
8
9// Only use the RR alias in cpp files. Do not use it in header files.
10namespace RR = RobotRaconteur;
11namespace vt = experimental::value_types;
12
13template <typename T>
14void assert_array(const RR::RRArrayPtr<T>& a, const std::vector<T>& b)
15{
16 assert(a->size() == b.size());
17 // RRArray supports standard C++ iterator interface.
18 // The intrusive_ptr smart pointer
19 // is dereferenced to access the underlying RRArray.
20 assert(boost::range::equal(*a, b));
21}
22
23int main(int argc, char* argv[])
24{
25 RR::ClientNodeSetup node_setup(ROBOTRACONTEUR_SERVICE_TYPES, argc, argv);
26
27 vt::ValueTypesExamplePtr c = RR::rr_cast<vt::ValueTypesExample>(
28 RR::RobotRaconteurNode::s()->ConnectService("rr+tcp://localhost:53223?service=values_example"));
29
30 // property MyVector3 g_vector
31 vt::MyVector3 c1;
32 c1.s.x = 1.0;
33 c1.s.y = 2.0;
34 c1.s.z = 3.0;
35 c->set_g_vector(c1);
36 vt::MyVector3 b = c->get_g_vector();
37 assert(b.s.x == 4.0);
38 assert(b.s.y == 5.0);
39 assert(b.s.z == 6.0);
40
41 // Now an array of NamedArrays
42 // property MyVector3[] g_vector_array
43 RR::RRNamedArrayPtr<vt::MyVector3> f = RR::AllocateEmptyRRNamedArray<vt::MyVector3>(2);
44 f->at(0).s.x = 1.0;
45 f->at(0).s.y = 2.0;
46 f->at(0).s.z = 3.0;
47 f->at(1).s.x = 4.0;
48 f->at(1).s.y = 5.0;
49 f->at(1).s.z = 6.0;
50
51 c->set_g_vector_array(f);
52
53 RR::RRNamedArrayPtr<vt::MyVector3> g = c->get_g_vector_array();
54 assert(g->size() == 2);
55 assert(g->at(0).s.x == 7.0);
56 assert(g->at(0).s.y == 8.0);
57 assert(g->at(0).s.z == 9.0);
58 assert(g->at(1).s.x == 10.0);
59 assert(g->at(1).s.y == 11.0);
60 assert(g->at(1).s.z == 12.0);
61
62 // Use plain arrays and convert to and from NamedArrays
63 vt::MyVector3 d;
64 // d.a has type double[3]
65 d.a[0] = 1.0;
66 d.a[1] = 2.0;
67 d.a[2] = 3.0;
68 c->set_g_vector(d);
69 vt::MyVector3 e = c->get_g_vector();
70 assert(e.a[0] == 4.0);
71 assert(e.a[1] == 5.0);
72 assert(e.a[2] == 6.0);
73
74 // property MyQuaternion h_quaternion
75 vt::MyQuaternion j;
76 j.s.w = 1.0;
77 j.s.x = 0.0;
78 j.s.y = 0.0;
79 j.s.z = 0.0;
80
81 c->set_h_quaternion(j);
82
83 vt::MyQuaternion k = c->get_h_quaternion();
84 assert(k.s.w == 0.707);
85 assert(k.s.x == 0.0);
86 assert(k.s.y == 0.707);
87 assert(k.s.z == 0.0);
88
89 // MyPose is a composite NamedArray with fields of other NamedArrays
90 // property MyPose l_pose
91 vt::MyPose l;
92 l.s.orientation.s.w = 1.0;
93 l.s.orientation.s.x = 0.0;
94 l.s.orientation.s.y = 0.0;
95 l.s.orientation.s.z = 0.0;
96 l.s.position.s.x = 1.0;
97 l.s.position.s.y = 2.0;
98 l.s.position.s.z = 3.0;
99
100 c->set_i_pose(l);
101
102 vt::MyPose m = c->get_i_pose();
103 assert(m.s.position.s.x == 4.0);
104 assert(m.s.position.s.y == 5.0);
105 assert(m.s.position.s.z == 6.0);
106 assert(m.s.orientation.s.w == 0.707);
107 assert(m.s.orientation.s.x == 0.0);
108 assert(m.s.orientation.s.y == 0.707);
109 assert(m.s.orientation.s.z == 0.0);
110
111 // Now use plain arrays and convert to and from NamedArrays
112 double n1[] = {1.0, 0.0, 0.0, 0.0, 1.0, 2.0, 3.0};
113 vt::MyPose n;
114 memcpy(&n.a[0], n1, sizeof(vt::MyPose));
115 c->set_i_pose(n);
116
117 vt::MyPose o = c->get_i_pose();
118 double o1[]{0.707, 0.0, 0.707, 0.0, 4.0, 5.0, 6.0};
119 assert(memcmp(&o.a[0], o1, sizeof(vt::MyPose)) == 0);
120
121 std::cout << "namedarray_value_types.cpp example complete" << std::endl;
122 return 0;
123}
Container Types
Robot Raconteur containers store a collection of values using lists and maps. The available container
types are list, map{int32}, and map{string}. The container types can store any value type,
except for other containers. Containers are nullable.
The following members from the experimental.value_types.ValueTypesExample object are used in the examples
for container types:
# Container examples
# Containers can be int32 key maps, string key maps, or lists
# All types can be stored in containers, but containers cannot
# directly contain other containers. For example
# string{list} is allowed, but string{list}{list} is not.
property double{int32} l_double_map
property double[]{string} l_double_array_map
property string{list} m_string_list
property string{int32} m_string_map_int32
property string{string} m_string_map_string
property MyVector3{int32} n_vector_map
property MyStructure{list} o_struct_list
The examples below show how to use containers in Python, MATLAB, LabView, C#, and C++.
1# container_value_types.py - Example of using container value types (maps and lists)
2
3from RobotRaconteur.Client import *
4import numpy as np
5
6c = RRN.ConnectService('rr+tcp://localhost:53223?service=values_example')
7
8# property double{int32} l_double_map
9# int32 keyed map of scalar doubles
10c.l_double_map = {
11 1: 1.1,
12 2: 2.2,
13 5: 3.3
14}
15
16b = c.l_double_map
17assert (len(b) == 2)
18assert (b[1] == 5.1)
19assert (b[5] == 6.2)
20
21# property double[]{string} l_double_array_map
22# string keyed map of double arrays
23c.l_double_array_map = {
24 "key1": np.array([1.1, 1.2, 1.3], dtype=np.float64),
25 "key2": np.array([2.1, 2.2, 2.3], dtype=np.float64)
26}
27
28d = c.l_double_array_map
29assert (len(d) == 2)
30np.testing.assert_array_equal(d["key3"], [5.1, 5.2, 5.3])
31np.testing.assert_array_equal(d["key4"], [6.1, 6.2, 6.3])
32
33# property string{list} m_string_list
34# list of strings
35c.m_string_list = ["string 1", "string 2", "string 3"]
36
37a = c.m_string_list
38assert (len(a) == 2)
39assert (a[0] == "string 4")
40assert (a[1] == "string 5")
41
42
43# property string{int32} m_string_map_int32
44# int32 keyed map of strings
45c.m_string_map_int32 = {
46 12: "string 1",
47 100: "string 2",
48 17: "string 3"
49}
50
51e = c.m_string_map_int32
52assert (len(e) == 2)
53assert (e[87] == "string 4")
54assert (e[1] == "string 5")
55
56# property string{string} m_string_map_string
57# string keyed map of strings
58c.m_string_map_string = {
59 "key1": "string 1",
60 "key2": "string 2"
61}
62
63f = c.m_string_map_string
64assert (len(f) == 3)
65assert (f["key3"] == "string 3")
66assert (f["key4"] == "string 4")
67assert (f["key5"] == "string 5")
68
69# property MyVector3{int32} n_vector_map
70# int32 keyed map of MyVector3
71my_vector3_dtype = RRN.GetNamedArrayDType("experimental.value_types.MyVector3", obj=c)
72e = np.zeros((1,), dtype=my_vector3_dtype)
73e[0]["x"] = 1.0
74e[0]["y"] = 2.0
75e[0]["z"] = 3.0
76c.n_vector_map = {
77 1: e
78}
79
80g = c.n_vector_map
81assert (len(g) == 1)
82g1 = g[1]
83assert (g1[0]["x"] == 4.0)
84assert (g1[0]["y"] == 5.0)
85assert (g1[0]["z"] == 6.0)
86
87# property MyStructure{list} o_struct_list
88# list of MyStructure
89my_structure_type = RRN.GetStructureType("experimental.value_types.MyStructure", obj=c)
90h = my_structure_type()
91h.a = 5
92h.b = np.array([10, 20], dtype=np.uint32)
93h.c = "String from structure client"
94h.d = [
95 "string a",
96 "string b"
97]
98c.o_struct_list = [h]
99
100i = c.o_struct_list
101assert (len(i) == 1)
102i0 = i[0]
103assert (i0.a == 52)
104np.testing.assert_array_equal(i[0].b, np.array([110, 120], dtype=np.uint32))
105assert (i0.c == "String from structure service")
106assert (len(i[0].d) == 3)
107assert (i0.d[0] == "string c")
108assert (i0.d[1] == "string d")
109assert (i0.d[2] == "string e")
1% container_value_types.m - Example of using container value types (maps and lists)
2
3c = RobotRaconteur.ConnectService('rr+tcp://localhost:53223?service=values_example');
4
5% property double{int32} l_double_map
6% int32 keyed map of scalar doubles
7% Robot Raconteur Matlab uses containers.Map to store maps
8c.l_double_map = containers.Map( ...
9 {int32(1), int32(2), ...
10 int32(5)},{1.1, 2.2, 3.3} ...
11);
12
13b = c.l_double_map;
14assert (length(b) == 2)
15assert (b(1) == 5.1)
16assert (b(5) == 6.2)
17
18% property double[]{string} l_double_array_map
19% string keyed map of double arrays
20c.l_double_array_map = containers.Map( ...
21 {'key1', 'key2'}, ...
22 {[1.1, 1.2, 1.3]', [2.1, 2.2, 2.3]'} ...
23);
24
25d = c.l_double_array_map;
26assert (length(d) == 2)
27assert(isequal(d('key3'), [5.1, 5.2, 5.3]'));
28assert(isequal(d('key4'), [6.1, 6.2, 6.3]'));
29
30% property string{list} m_string_list
31% list of strings
32% Robot Raconteur Matlab uses column cell arrays to store lists
33c.m_string_list = {'string 1', 'string 2', 'string 3'}';
34
35a = c.m_string_list;
36assert (length(a) == 2);
37assert (strcmp(a{1}, 'string 4'));
38assert (strcmp(a{2}, 'string 5'));
39
40
41% property string{int32} m_string_map_int32
42% int32 keyed map of strings
43c.m_string_map_int32 = containers.Map( ...
44 {int32(12), int32(100), int32(17)}, ...
45 {'string 1', 'string 2', 'string 3'} ...
46);
47
48e = c.m_string_map_int32;
49assert (length(e) == 2)
50assert (strcmp(e(87), 'string 4'));
51assert (strcmp(e(1), 'string 5'));
52
53% property string{string} m_string_map_string
54% string keyed map of strings
55c.m_string_map_string = containers.Map( ...
56 {'key1', 'key2'}, ...
57 {'string 1', 'string 2'} ...
58);
59
60f = c.m_string_map_string;
61assert (length(f) == 3)
62assert (strcmp(f('key3'), 'string 3'));
63assert (strcmp(f('key4'), 'string 4'));
64assert (strcmp(f('key5'), 'string 5'));
65
66% property MyVector3{int32} n_vector_map
67% int32 keyed map of MyVector3
68e = [1.0, 2.0, 3.0]';
69c.n_vector_map = containers.Map({int32(1)}, {e});
70
71g = c.n_vector_map;
72assert (length(g) == 1);
73assert(isequal(g(1), [4.0, 5.0, 6.0]'));
74
75% property MyStructure{list} o_struct_list
76% list of MyStructure
77h = RobotRaconteur.CreateStructure(c, "experimental.value_types.MyStructure");
78h.a = 5;
79h.b = uint32([10, 20]');
80h.c = 'String from structure client';
81h.d = {'string a', 'string b'}';
82c.o_struct_list = {h};
83
84i = c.o_struct_list;
85assert (length(i) == 1)
86i0 = i{1};
87assert(i0.a == 52)
88assert(isequal(i0.b, [110, 120]'))
89assert(strcmp(i0.c, 'String from structure service'));
90assert(length(i0.d) == 3);
91assert(strcmp(i0.d{1}, 'string c'));
92assert(strcmp(i0.d{2}, 'string d'));
93assert(strcmp(i0.d{3}, 'string e'));
94
95RobotRaconteur.DisconnectService(c);
1// container_value_types.cs - Example of using container value types (maps and lists)
2
3using RobotRaconteur;
4using System;
5using System.Diagnostics;
6using System.Linq;
7using System.Collections.Generic;
8using experimental.value_types;
9
10using (var node_setup = new ClientNodeSetup(args))
11{
12 var c = (experimental.value_types.ValueTypesExample)RobotRaconteurNode.s.ConnectService(
13 "rr+tcp://localhost:53223?service=values_example");
14
15 // property double{int32} l_double_map
16 // int32 keyed map of scalar doubles
17 c.l_double_map = new Dictionary<int, double>() { { 1, 1.1 }, { 2, 2.2 }, { 5, 3.3 } };
18
19 var b = c.l_double_map;
20 Debug.Assert(b.Count == 2);
21 Debug.Assert(b[1] == 5.1);
22 Debug.Assert(b[5] == 6.2);
23
24 // property double[]{string} l_double_array_map
25 // string keyed map of double arrays
26 c.l_double_array_map = new Dictionary<string, double[]>() { { "key1", new double[] { 1.1, 1.2, 1.3 } },
27 { "key2", new double[] { 2.1, 2.2, 2.3 } } };
28
29 var d = c.l_double_array_map;
30 Debug.Assert(d.Count == 2);
31 Debug.Assert(d["key3"].SequenceEqual(new double[] { 5.1, 5.2, 5.3 }));
32 Debug.Assert(d["key4"].SequenceEqual(new double[] { 6.1, 6.2, 6.3 }));
33
34 // property string{list} m_string_list
35 // list of strings
36 c.m_string_list = new List<string>() { "string 1", "string 2", "string 3" };
37
38 var a = c.m_string_list;
39 Debug.Assert(a.Count == 2);
40 Debug.Assert(a[0] == "string 4");
41 Debug.Assert(a[1] == "string 5");
42
43 // property string{int32} m_string_map_int32
44 // int32 keyed map of strings
45 c.m_string_map_int32 =
46 new Dictionary<int, string>() { { 12, "string 1" }, { 100, "string 2" }, { 17, "string 3" } };
47
48 var e = c.m_string_map_int32;
49 Debug.Assert(e.Count == 2);
50 Debug.Assert(e[87] == "string 4");
51 Debug.Assert(e[1] == "string 5");
52
53 // property string{string} m_string_map_string
54 // string keyed map of strings
55 c.m_string_map_string = new Dictionary<string, string>() { { "key1", "string 1" }, { "key2", "string 2" } };
56
57 var f = c.m_string_map_string;
58 Debug.Assert(f.Count == 3);
59 Debug.Assert(f["key3"] == "string 3");
60 Debug.Assert(f["key4"] == "string 4");
61 Debug.Assert(f["key5"] == "string 5");
62
63 // property MyVector3{int32} n_vector_map
64 // int32 keyed map of MyVector3
65 var g = new MyVector3() { x = 1.0, y = 2.0, z = 3.0 };
66 c.n_vector_map = new Dictionary<int, MyVector3>() { { 1, g } };
67
68 var g1 = c.n_vector_map;
69 Debug.Assert(g1.Count == 1);
70 Debug.Assert(g1[1].x == 4.0);
71 Debug.Assert(g1[1].y == 5.0);
72 Debug.Assert(g1[1].z == 6.0);
73
74 // property MyStructure{list} o_struct_list
75 // list of MyStructure
76 var h = new MyStructure() { a = 5, b = new uint[] { 10, 20 }, c = "String from structure client",
77 d = new List<string>() { "string a", "string b" } };
78 c.o_struct_list = new List<MyStructure>() { h };
79
80 var i = c.o_struct_list;
81 Debug.Assert(i.Count == 1);
82 Debug.Assert(i[0].a == 52);
83 Debug.Assert(Enumerable.SequenceEqual(i[0].b, new uint[] { 110, 120 }));
84 Debug.Assert(i[0].c == "String from structure service");
85 Debug.Assert(Enumerable.SequenceEqual(i[0].d, new List<string>() { "string c", "string d", "string e" }));
86}
1// container_value_types.cpp - Example of using container value types (maps and lists)
2
3#include <stdio.h>
4#include <iostream>
5#include <boost/range/algorithm.hpp>
6#include <RobotRaconteur.h>
7#include "robotraconteur_generated.h"
8
9// Only use the RR alias in cpp files. Do not use it in header files.
10namespace RR = RobotRaconteur;
11namespace vt = experimental::value_types;
12
13template <typename T>
14void assert_array(const RR::RRArrayPtr<T>& a, const std::vector<T>& b)
15{
16 assert(a->size() == b.size());
17 // RRArray supports standard C++ iterator interface.
18 // The intrusive_ptr smart pointer
19 // is dereferenced to access the underlying RRArray.
20 assert(boost::range::equal(*a, b));
21}
22
23int main(int argc, char* argv[])
24{
25 RR::ClientNodeSetup node_setup(ROBOTRACONTEUR_SERVICE_TYPES, argc, argv);
26
27 vt::ValueTypesExamplePtr c = RR::rr_cast<vt::ValueTypesExample>(
28 RR::RobotRaconteurNode::s()->ConnectService("rr+tcp://localhost:53223?service=values_example"));
29
30 // property double{int32} l_double_map
31 // int32 keyed map of scalar doubles
32 RR::RRMapPtr<int32_t, RR::RRArray<double> > l_double_map1 = RR::AllocateEmptyRRMap<int32_t, RR::RRArray<double> >();
33 l_double_map1->insert(std::make_pair(1, RR::ScalarToRRArray<double>(1.1)));
34 l_double_map1->insert(std::make_pair(2, RR::ScalarToRRArray<double>(2.2)));
35 l_double_map1->insert(std::make_pair(5, RR::ScalarToRRArray<double>(3.3)));
36 c->set_l_double_map(l_double_map1);
37
38 RR::RRMapPtr<int32_t, RR::RRArray<double> > b = c->get_l_double_map();
39 // Containers can be null
40 RR::rr_null_check(b);
41 assert(b->size() == 2);
42 // Container elements can be null
43 RR::rr_null_check(b->at(1));
44 RR::rr_null_check(b->at(5));
45 assert_array(b->at(1), {5.1});
46 assert_array(b->at(5), {6.2});
47
48 // property double[]{string} l_double_array_map
49 // string keyed map of double arrays
50 RR::RRMapPtr<std::string, RR::RRArray<double> > l_double_array_map1 =
51 RR::AllocateEmptyRRMap<std::string, RR::RRArray<double> >();
52 l_double_array_map1->insert(std::make_pair("key1", RR::VectorToRRArray<double, double>({1.1, 1.2, 1.3})));
53 l_double_array_map1->insert(std::make_pair("key2", RR::VectorToRRArray<double, double>({2.1, 2.2, 2.3})));
54 c->set_l_double_array_map(l_double_array_map1);
55
56 RR::RRMapPtr<std::string, RR::RRArray<double> > l_double_array_map2 = c->get_l_double_array_map();
57 RR::rr_null_check(l_double_array_map2);
58 assert(l_double_array_map2->size() == 2);
59 RR::rr_null_check(l_double_array_map2->at("key3"));
60 RR::rr_null_check(l_double_array_map2->at("key4"));
61 assert_array(l_double_array_map2->at("key3"), {5.1, 5.2, 5.3});
62 assert_array(l_double_array_map2->at("key4"), {6.1, 6.2, 6.3});
63
64 // property string{list} m_string_list
65 // list of strings
66 RR::RRListPtr<RR::RRArray<char> > m_string_list1 = RR::AllocateEmptyRRList<RR::RRArray<char> >();
67 m_string_list1->push_back(RR::stringToRRArray("string 1"));
68 m_string_list1->push_back(RR::stringToRRArray("string 2"));
69 m_string_list1->push_back(RR::stringToRRArray("string 3"));
70 c->set_m_string_list(m_string_list1);
71
72 RR::RRListPtr<RR::RRArray<char> > a = c->get_m_string_list();
73 // Containers can be null
74 RR::rr_null_check(a);
75 assert(a->size() == 2);
76 // Container elements can be null
77 auto a_iterator = a->begin();
78 RR::rr_null_check(*a_iterator);
79 assert(RR::RRArrayToString(*a_iterator++) == "string 4");
80 RR::rr_null_check(*a_iterator);
81 assert(RR::RRArrayToString(*a_iterator++) == "string 5");
82
83 // property string{int32} m_string_map_int32
84 // int32 keyed map of strings
85 RR::RRMapPtr<int32_t, RR::RRArray<char> > m_string_map_int32_1 =
86 RR::AllocateEmptyRRMap<int32_t, RR::RRArray<char> >();
87 m_string_map_int32_1->insert(std::make_pair(12, RR::stringToRRArray("string 1")));
88 m_string_map_int32_1->insert(std::make_pair(100, RR::stringToRRArray("string 2")));
89 m_string_map_int32_1->insert(std::make_pair(17, RR::stringToRRArray("string 3")));
90 c->set_m_string_map_int32(m_string_map_int32_1);
91
92 RR::RRMapPtr<int32_t, RR::RRArray<char> > e = c->get_m_string_map_int32();
93 // Containers can be null
94 RR::rr_null_check(e);
95 assert(e->size() == 2);
96 // Container elements can be null
97 RR::rr_null_check(e->at(87));
98 RR::rr_null_check(e->at(1));
99 assert(RR::RRArrayToString(e->at(87)) == "string 4");
100 assert(RR::RRArrayToString(e->at(1)) == "string 5");
101
102 // property string{string} m_string_map_string
103 // string keyed map of strings
104 RR::RRMapPtr<std::string, RR::RRArray<char> > m_string_map_string_1 =
105 RR::AllocateEmptyRRMap<std::string, RR::RRArray<char> >();
106 m_string_map_string_1->insert(std::make_pair("key1", RR::stringToRRArray("string 1")));
107 m_string_map_string_1->insert(std::make_pair("key2", RR::stringToRRArray("string 2")));
108 c->set_m_string_map_string(m_string_map_string_1);
109
110 RR::RRMapPtr<std::string, RR::RRArray<char> > f = c->get_m_string_map_string();
111 // Containers can be null
112 RR::rr_null_check(f);
113 assert(f->size() == 3);
114 // Container elements can be null
115 RR::rr_null_check(f->at("key3"));
116 RR::rr_null_check(f->at("key4"));
117 RR::rr_null_check(f->at("key5"));
118 assert(RR::RRArrayToString(f->at("key3")) == "string 3");
119 assert(RR::RRArrayToString(f->at("key4")) == "string 4");
120 assert(RR::RRArrayToString(f->at("key5")) == "string 5");
121
122 // property MyVector3{int32} n_vector_map
123 // int32 keyed map of MyVector3
124 vt::MyVector3 g; // = new MyVector3() { x = 1.0, y = 2.0, z = 3.0 };
125 g.s.x = 1.0;
126 g.s.y = 2.0;
127 g.s.z = 3.0;
128 RR::RRMapPtr<int32_t, RR::RRNamedArray<vt::MyVector3> > n_vector_map_1 =
129 RR::AllocateEmptyRRMap<int32_t, RR::RRNamedArray<vt::MyVector3> >();
130 n_vector_map_1->insert(std::make_pair(1, RR::ScalarToRRNamedArray(g)));
131 c->set_n_vector_map(n_vector_map_1);
132
133 RR::RRMapPtr<int32_t, RR::RRNamedArray<vt::MyVector3> > g1 = c->get_n_vector_map();
134 // Containers can be null
135 RR::rr_null_check(g1);
136 assert(g1->size() == 1);
137 // Container elements can be null
138 RR::rr_null_check(g1->at(1));
139 vt::MyVector3 g2 = RR::RRNamedArrayToScalar(g1->at(1));
140 assert(g2.s.x == 4.0);
141 assert(g2.s.y == 5.0);
142 assert(g2.s.z == 6.0);
143
144 // property MyStructure{list} o_struct_list
145 // list of MyStructure
146 vt::MyStructurePtr h1(new vt::MyStructure());
147 h1->a = 5;
148 h1->b = RR::VectorToRRArray<uint32_t, uint32_t>({10, 20});
149 h1->c = "String from structure client";
150 RR::RRListPtr<RR::RRArray<char> > h1_d = RR::AllocateEmptyRRList<RR::RRArray<char> >();
151 h1_d->push_back(RR::stringToRRArray("string a"));
152 h1_d->push_back(RR::stringToRRArray("string b"));
153 h1->d = h1_d;
154 RR::RRListPtr<vt::MyStructure> h2 = RR::AllocateEmptyRRList<vt::MyStructure>();
155 h2->push_back(h1);
156 c->set_o_struct_list(h2);
157
158 RR::RRListPtr<vt::MyStructure> i = c->get_o_struct_list();
159 // Containers can be null
160 RR::rr_null_check(i);
161 assert(i->size() == 1);
162 // Container elements can be null
163 RR::rr_null_check(*(i->begin()));
164 vt::MyStructurePtr i0 = *(i->begin());
165 assert(i0->a == 52);
166 assert_array(i0->b, {110, 120});
167 assert(i0->c == "String from structure service");
168 // Containers can be null
169 RR::rr_null_check(i0->d);
170 assert(i0->d->size() == 3);
171 auto i0_d_iterator = i0->d->begin();
172 assert(RR::RRArrayToString(*i0_d_iterator++) == "string c");
173 assert(RR::RRArrayToString(*i0_d_iterator++) == "string d");
174 assert(RR::RRArrayToString(*i0_d_iterator++) == "string e");
175
176 std::cout << "container_value_types.cpp example complete" << std::endl;
177 return 0;
178}
varvalue Type
Varvalue is a special type that can store any value type, and is a form of variant. See the language documentation for more details on how the variant is implemented in each language. The varvalue type is nullable.
The following members from the experimental.value_types.ValueTypesExample object are used in the examples
for varvalue types:
# varvalue examples
property varvalue p_varvalue_double_array
property varvalue q_varvalue_string
property varvalue r_varvalue_struct
# varvalue{string} is a string keyed map of varvalues
# It is frequently used for "extended" fields
# to allow for forward compatibility
property varvalue{string} s_varvalue_map2
The examples below show how to use varvalue in Python, MATLAB, LabView, C#, and C++.
1# varvalue_value_types.py - Example of using varvalue wildcard type
2
3from RobotRaconteur.Client import *
4import numpy as np
5
6c = RRN.ConnectService('rr+tcp://localhost:53223?service=values_example')
7
8# Any valid Robot Raconteur data type can be stored in a varvalue
9# In Python, the RR.VarValue() Python structure is used to store
10# the value and type of the data. The type is stored as a string.
11# This is necessary because Python does not carry enough type
12# information
13
14# property varvalue p_varvalue_double_array
15# Example of storing a double array in a varvalue
16a = np.array([1.1, 2.2, 3.3], dtype=np.float64)
17c.p_varvalue_double_array = RR.VarValue(a, "double[]")
18b = c.p_varvalue_double_array
19np.testing.assert_array_equal(b.data, [1.4, 2.5, 3.6])
20assert b.datatype == "double[]"
21
22# property varvalue q_varvalue_string
23# Example of storing a string in a varvalue
24c.q_varvalue_string = RR.VarValue("varvalue string from client", "string")
25d = c.q_varvalue_string
26assert d.data == "varvalue string from service"
27assert d.datatype == "string"
28
29# property varvalue r_varvalue_struct
30# Example of storing a structure in a varvalue
31my_structure_type = RRN.GetStructureType("experimental.value_types.MyStructure", obj=c)
32s = my_structure_type()
33s.a = 5
34s.b = np.array([10, 20], dtype=np.uint32)
35s.c = "String from structure client"
36s.d = [
37 "string a",
38 "string b"
39]
40
41c.r_varvalue_struct = RR.VarValue(s, "experimental.value_types.MyStructure")
42
43t = c.r_varvalue_struct
44t_data = t.data
45
46assert t_data.a == 52
47np.testing.assert_array_equal(t_data.b, np.array([110, 120], dtype=np.uint32))
48assert t_data.c == "String from structure service"
49assert len(t_data.d) == 3
50assert t_data.d[0] == "string c"
51assert t_data.d[1] == "string d"
52assert t_data.d[2] == "string e"
53
54# property varvalue{string} s_varvalue_map2
55# Example of storing a map of strings in a varvalue
56# varvalue{string} is used extensively in structures
57# to allow for additional fields to be added to the
58# structure without changing the structure definition
59c.s_varvalue_map2 = {
60 "key1": RR.VarValue(np.array([2, 3]), "int32[]"),
61 "key2": RR.VarValue("string 2", "string")
62}
63
64u = c.s_varvalue_map2
65assert len(u) == 2
66np.testing.assert_array_equal(u["key3"].data, [4, 5])
67assert u["key3"].datatype == "int32[]"
68assert u["key4"].data == "string 4"
69assert u["key4"].datatype == "string"
1% varvalue_value_types.m - Example of using varvalue wildcard type
2
3c = RobotRaconteur.ConnectService('rr+tcp://localhost:53223?service=values_example');
4
5% Any valid Robot Raconteur data type can be stored in a varvalue
6% In Matlab, the RobotRaconteurVarValue() class is used to store
7% the value and type of the data. The type is stored as a string.
8% This is necessary because Matlab does not carry enough type
9% information
10
11% property varvalue p_varvalue_double_array
12% Example of storing a double array in a varvalue
13a = [1.1, 2.2, 3.3]';
14c.p_varvalue_double_array = RobotRaconteurVarValue(a, "double[]");
15b = c.p_varvalue_double_array;
16assert(isequal(b.data, [1.4, 2.5, 3.6]'));
17assert(strcmp(b.datatype, "double[]"));
18
19% property varvalue q_varvalue_string
20% Example of storing a string in a varvalue
21c.q_varvalue_string = RobotRaconteurVarValue('varvalue string from client', 'string');
22d = c.q_varvalue_string;
23assert(strcmp(d.data, 'varvalue string from service'));
24assert(strcmp(d.datatype, 'string'));
25
26% property varvalue r_varvalue_struct
27% Example of storing a structure in a varvalue
28s = RobotRaconteur.CreateStructure(c, 'experimental.value_types.MyStructure');
29s.a = 5;
30s.b = uint32([10, 20]');
31s.c = 'String from structure client';
32s.d = {'string a', 'string b'}';
33
34c.r_varvalue_struct = RobotRaconteurVarValue(s, "experimental.value_types.MyStructure");
35
36t = c.r_varvalue_struct;
37t_data = t.data;
38
39assert(t_data.a == 52);
40assert(isequal(t_data.b, [110, 120]'));
41assert(strcmp(t_data.c, 'String from structure service'));
42assert(length(t_data.d) == 3);
43assert(strcmp(t_data.d{1}, "string c"));
44assert(strcmp(t_data.d{2}, "string d"));
45assert(strcmp(t_data.d{3}, 'string e'));
46
47% property varvalue{string} s_varvalue_map2
48% Example of storing a map of strings in a varvalue
49% varvalue{string} is used extensively in structures
50% to allow for additional fields to be added to the
51% structure without changing the structure definition
52c.s_varvalue_map2 = containers.Map( ...
53 {'key1', 'key2'}, ...
54 { RobotRaconteurVarValue(int32([2, 3]'), 'int32[]'), ...
55 RobotRaconteurVarValue('string 2', 'string')} ...
56);
57
58u = c.s_varvalue_map2;
59assert(length(u) == 2)
60assert(isequal(u('key3').data, [4, 5]'));
61assert(strcmp(u('key3').datatype, 'int32[]'));
62assert(strcmp(u('key4').data, 'string 4'));
63assert(strcmp(u('key4').datatype, 'string'));
64
65RobotRaconteur.DisconnectService(c);
1// varvalue_value_types.cs - Example of using varvalue wildcard type
2
3using RobotRaconteur;
4using System;
5using System.Diagnostics;
6using System.Linq;
7using System.Collections.Generic;
8using experimental.value_types;
9
10using (var node_setup = new ClientNodeSetup(args))
11{
12 var c = (experimental.value_types.ValueTypesExample)RobotRaconteurNode.s.ConnectService(
13 "rr+tcp://localhost:53223?service=values_example");
14
15 // Any valid Robot Raconteur data type can be stored in a varvalue
16
17 // property varvalue p_varvalue_double_array
18 // Example of storing a double array in a varvalue
19 var a = new double[] { 1.1, 2.2, 3.3 };
20 c.p_varvalue_double_array = a;
21 var b = (double[])c.p_varvalue_double_array;
22 Debug.Assert(Enumerable.SequenceEqual(b, new double[] { 1.4, 2.5, 3.6 }));
23
24 // property varvalue q_varvalue_string
25 // Example of storing a string in a varvalue
26 c.q_varvalue_string = "varvalue string from client";
27 var d = (string)c.q_varvalue_string;
28 Debug.Assert(d == "varvalue string from service");
29
30 // property varvalue r_varvalue_struct
31 // Example of storing a structure in a varvalue
32 var s = new MyStructure() { a = 5, b = new uint[] { 10, 20 }, c = "String from structure client",
33 d = new List<string>() { "string a", "string b" } };
34
35 c.r_varvalue_struct = s;
36
37 var t = (MyStructure)c.r_varvalue_struct;
38 Debug.Assert(t.a == 52);
39 Debug.Assert(Enumerable.SequenceEqual(t.b, new uint[] { 110, 120 }));
40 Debug.Assert(t.c == "String from structure service");
41 Debug.Assert(Enumerable.SequenceEqual(t.d, new List<string>() { "string c", "string d", "string e" }));
42
43 // property varvalue{string} s_varvalue_map2
44 // Example of storing a map of strings in a varvalue
45 // varvalue{string} is used extensively in structures
46 // to allow for additional fields to be added to the
47 // structure without changing the structure definition
48 c.s_varvalue_map2 = new Dictionary<string, object>() { { "key1", new int[] { 2, 3 } }, { "key2", "string 2" } };
49
50 var u = c.s_varvalue_map2;
51 Debug.Assert(u.Count == 2);
52 Debug.Assert(Enumerable.SequenceEqual((int[])u["key3"], new int[] { 4, 5 }));
53 Debug.Assert((string)u["key4"] == "string 4");
54}
1// numeric_value_types.cpp - Example of using numeric value types
2
3#include <stdio.h>
4#include <iostream>
5#include <boost/range/algorithm.hpp>
6#include <RobotRaconteur.h>
7#include "robotraconteur_generated.h"
8
9// Only use the RR alias in cpp files. Do not use it in header files.
10namespace RR = RobotRaconteur;
11namespace vt = experimental::value_types;
12
13template <typename T>
14void assert_array(const RR::RRArrayPtr<T>& a, const std::vector<T>& b)
15{
16 assert(a->size() == b.size());
17 // RRArray supports standard C++ iterator interface.
18 // The intrusive_ptr smart pointer
19 // is dereferenced to access the underlying RRArray.
20 assert(boost::range::equal(*a, b));
21}
22
23int main(int argc, char* argv[])
24{
25 RR::ClientNodeSetup node_setup(ROBOTRACONTEUR_SERVICE_TYPES, argc, argv);
26
27 vt::ValueTypesExamplePtr c = RR::rr_cast<vt::ValueTypesExample>(
28 RR::RobotRaconteurNode::s()->ConnectService("rr+tcp://localhost:53223?service=values_example"));
29
30 // Scalar numbers
31 // property double a_double
32 double a_double_read = c->get_a_double();
33 std::cout << a_double_read << std::endl;
34 // assert used for the rest of the example property read operations
35 // to demonstrate the expected values.
36 assert(c->get_a_double() == 5.78);
37 c->set_a_double(49.3);
38 // property int32 b_int
39 assert(c->get_b_int() == 4557);
40 c->set_b_int(359);
41 // property uint8 c_byte
42 assert(c->get_c_byte() == 0x1A);
43 c->set_c_byte(31);
44 // property cdouble d_cdouble
45 assert(c->get_d_cdouble() == RR::cdouble(23.7, 5.3));
46 c->set_d_cdouble(RR::cdouble(1.2, 3.4));
47 // property bool e_bool
48 // RR::rr_bool is used for Robot Raconteur bool values
49 assert(c->get_e_bool().value != 0);
50 c->set_e_bool(RR::rr_bool(0));
51 // property int32 meaning_of_life [readonly]
52 assert(c->get_meaning_of_life() == 42);
53
54 // Numeric Arrays
55 // property double[] a_double_array
56 assert_array(c->get_a_double_array(), {0.016, 0.226});
57
58 // Examples of different ways to initialize RRArray. Also see Eigen converters in robotraconteur-companion
59
60 // Use AttachRRArrayCopy()
61 double a_double_array_1a[] = {0.582, 0.288, 0.09, 0.213, 0.98};
62 RR::RRArrayPtr<double> a_double_array_1 = RR::AttachRRArrayCopy(a_double_array_1a, 5);
63 c->set_a_double_array(a_double_array_1);
64
65 // Use AllocateRRArray to allocate an uninitialized array
66 RR::RRArrayPtr<double> a_double_array_2 = RR::AllocateRRArray<double>(5);
67 a_double_array_2->at(0) = 0.582;
68 a_double_array_2->at(1) = 0.288;
69 a_double_array_2->at(2) = 0.09;
70 a_double_array_2->at(3) = 0.213;
71 a_double_array_2->at(4) = 0.98;
72 c->set_a_double_array(a_double_array_2);
73
74 RR::RRArrayPtr<double> a_double_array_2b = c->get_a_double_array();
75 assert(a_double_array_2b->size() == 2);
76 assert(a_double_array_2b->at(0) == 0.016);
77 assert((*a_double_array_2b)[1] == 0.226);
78
79 // Use VectorToRRArray to convert a std::vector to RRArray
80 std::vector<double> a_double_array_3a = {0.582, 0.288, 0.09, 0.213, 0.98};
81 RR::RRArrayPtr<double> a_double_array_3 = RR::VectorToRRArray<double, double>(a_double_array_3a);
82 c->set_a_double_array(a_double_array_3);
83
84 // property double[3] a_double_array_fixed
85 assert_array(c->get_a_double_array_fixed(), {0.13, 0.27, 0.15});
86 c->set_a_double_array_fixed(RR::VectorToRRArray<double, double>({0.21, 0.12, 0.39}));
87 // % property double[6-] a_double_array_maxlen
88 assert_array(c->get_a_double_array_maxlen(), {0.7, 0.16, 0.16, 0.05, 0.61, 0.9});
89 c->set_a_double_array_maxlen(RR::VectorToRRArray<double, double>({0.035, 0.4}));
90 // property double[3,2] a_double_marray_fixed
91 RR::RRMultiDimArrayPtr<double> a_double_marray_fixed_read = c->get_a_double_marray_fixed();
92 assert_array(a_double_marray_fixed_read->Dims, {3, 2});
93 assert_array(a_double_marray_fixed_read->Array, {0.29, 0.41, 0.4, 0.66, 0.6, 0.2});
94 RR::RRMultiDimArrayPtr<double> a_double_marray_fixed_1 =
95 RR::AllocateRRMultiDimArray<double>(RR::VectorToRRArray<uint32_t, uint32_t>({3, 2}),
96 RR::VectorToRRArray<double, double>({0.3, 0.4, 0.5, 0.6, 0.6, 0.2}));
97 c->set_a_double_marray_fixed(a_double_marray_fixed_1);
98 // property double[*] a_double_marray
99 RR::RRMultiDimArrayPtr<double> a_double_marray_read = c->get_a_double_marray();
100 assert_array(a_double_marray_read->Dims, {2, 2});
101 assert_array(a_double_marray_read->Array, {0.72, 0.05, 0.4, 0.07});
102 RR::RRMultiDimArrayPtr<double> a_double_marray_1 = RR::AllocateRRMultiDimArray<double>(
103 RR::VectorToRRArray<uint32_t, uint32_t>({2, 1}), RR::VectorToRRArray<double, double>({0.3, 0.01}));
104 // property uint8[] c_byte_array
105 assert_array(c->get_c_byte_array(), {0x1A, 0x2B});
106 c->set_c_byte_array(RR::VectorToRRArray<uint8_t, uint8_t>({0x3C, 0x4D, 0x5E, 0x6F, 0x70}));
107
108 std::cout << "numeric_value_types.cpp example complete" << std::endl;
109 return 0;
110}
Nullable Types
Structures, containers, and varvalues are nullable, meaning they can be set to null. All other
value types are not nullable.
The following members from the experimental.value_types.ValueTypesExample object are used in the examples
for nullable types:
property MyStructure t_struct_null
The examples below show how to use nullable types in Python, MATLAB, LabView, C#, and C++.
1# null_value_types.py - Example of types that can be null
2
3from RobotRaconteur.Client import *
4import numpy as np
5
6c = RRN.ConnectService('rr+tcp://localhost:53223?service=values_example')
7
8# Null values
9# Null values are "None" in Python
10# struct, containers, and varvalue are nullable.
11# Numbers, arrays, strings, pods, and namedarrays are not nullable.
12
13# property MyStructure t_struct_null
14c.t_struct_null = None
15assert c.t_struct_null is None
1% null_value_types.m - Example of types that can be null
2
3c = RobotRaconteur.ConnectService('rr+tcp://localhost:53223?service=values_example');
4
5% Null values
6% Null values are "missing" in Matlab
7% struct, containers, and varvalue are nullable.
8% Numbers, arrays, strings, pods, and namedarrays are not nullable.
9
10% property MyStructure t_struct_null
11c.t_struct_null = missing;
12assert(ismissing(c.t_struct_null));
13
14RobotRaconteur.DisconnectService(c);
1// null_value_types.cs - Example of types that can be null
2
3using RobotRaconteur;
4using System;
5using System.Diagnostics;
6using System.Linq;
7using System.Collections.Generic;
8
9using (var node_setup = new ClientNodeSetup(args))
10{
11 var c = (experimental.value_types.ValueTypesExample)RobotRaconteurNode.s.ConnectService(
12 "rr+tcp://localhost:53223?service=values_example");
13
14 // Null values
15 // Null values are "null" in C#
16 // struct, containers, and varvalue are nullable.
17 // Numbers, arrays, strings, pods, and namedarrays are not nullable.
18
19 // property MyStructure t_struct_null
20 c.t_struct_null = null;
21 Debug.Assert(c.t_struct_null == null);
22}
1// null_value_types.cpp - Example of types that can be null
2
3#include <stdio.h>
4#include <iostream>
5#include <boost/range/algorithm.hpp>
6#include <RobotRaconteur.h>
7#include "robotraconteur_generated.h"
8
9// Only use the RR alias in cpp files. Do not use it in header files.
10namespace RR = RobotRaconteur;
11namespace vt = experimental::value_types;
12
13int main(int argc, char* argv[])
14{
15 RR::ClientNodeSetup node_setup(ROBOTRACONTEUR_SERVICE_TYPES, argc, argv);
16
17 vt::ValueTypesExamplePtr c = RR::rr_cast<vt::ValueTypesExample>(
18 RR::RobotRaconteurNode::s()->ConnectService("rr+tcp://localhost:53223?service=values_example"));
19
20 // Null values
21 // Null values are "nullptr" or empty intrusive_ptr
22 // struct, containers, and varvalue are nullable.
23 // Numbers, arrays, strings, pods, and namedarrays are not nullable.
24
25 // property MyStructure t_struct_null
26 vt::MyStructurePtr s = nullptr;
27 c->set_t_struct_null(s);
28 assert(c->get_t_struct_null() == nullptr);
29}