Skip to content

Commit

Permalink
Use 'append' convention for list Sockets and Inputs
Browse files Browse the repository at this point in the history
  • Loading branch information
nickbianco committed Jan 8, 2024
1 parent f2d93a0 commit 744c441
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 21 deletions.
2 changes: 1 addition & 1 deletion Bindings/Python/tests/test_sockets_inputs_outputs.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ def test_connecting_and_iterate_inputs(self):
coord = j.get_coordinates(0)
rep.updInput('inputs').connect(coord.getOutput('value'))
rep.connectInput_inputs(coord.getOutput('speed'), 'spd')
rep.connectInput_inputs(
rep.appendInputChannel_inputs(
source.getOutput('column').getChannel('col1'))
rep.addToReport(
source.getOutput('column').getChannel('col2'), 'second_col')
Expand Down
34 changes: 25 additions & 9 deletions OpenSim/Common/ComponentSocket.h
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,7 @@ class Socket : public AbstractSocket {
}

/** Return a const reference to the Object connected to this Socket. */
const T& getConnecteeAsObject(int index = -1) const override {
const Object& getConnecteeAsObject(int index = -1) const override {
if (index < 0) {
if (!isListSocket()) { index = 0; }
else {
Expand Down Expand Up @@ -471,7 +471,7 @@ class Socket : public AbstractSocket {

private:

const T& getConnecteeAsObjectInternal(int index) const {
const Object& getConnecteeAsObjectInternal(int index) const {
OPENSIM_THROW_IF(!isConnected(), Exception,
"Socket '{}' not connected.", getName());
using SimTK::isIndexInRange;
Expand Down Expand Up @@ -1135,13 +1135,25 @@ class Input : public AbstractInput {
/** @endcond */ \
/** @name Socket-related functions */ \
/** @{ */ \
/** Connect the '##cname##' Socket to an object of type T##. */ \
/** Append an object of type T## to the list of connectees in the */ \
/** list Socket. */ \
/** Call finalizeConnections() afterwards to update the socket's */ \
/** connectee path property. The reference to the connectee set here */ \
/** takes precedence over the connectee path property. */ \
void connectSocket_##cname(const OpenSim::Object& object) { \
void appendSocketConnectee_##cname(const OpenSim::Object& object) { \
this->updSocket(#cname).connect(object); \
} \
/** Connect the '##cname##' Socket to a list of objects of type T##. */ \
/** Call finalizeConnections() afterwards to update the socket's */ \
/** connectee path property. The reference to the connectee set here */ \
/** takes precedence over the connectee path property. */ \
void connectSocket_##cname( \
const std::vector< \
SimTK::ReferencePtr<const OpenSim::Object>>& objects) { \
for (const auto& object : objects) { \
this->updSocket(#cname).connect(object.getRef()); \
} \
} \
/** @} */

// The following doxygen-like description does NOT actually appear in doxygen.
Expand Down Expand Up @@ -1315,13 +1327,15 @@ OpenSim::PropertyIndex Class::constructSocket_##cname() { \
updInput(#iname).connect(output, alias); \
} \
/** Connect this Input to an output channel of type T##. */ \
/** This overrides any existing channel connections. */ \
/** You can optionally provide an alias that will be used by this */ \
/** component to refer to the channel. */ \
/** Call finalizeConnections() afterwards to update the input's */ \
/** connectee path property. The reference to the channel set here */ \
/** takes precedence over the connectee path property. */ \
void connectInput_##iname(const OpenSim::AbstractChannel& channel, \
const std::string& alias = "") { \
void connectInputChannel_##iname( \
const OpenSim::AbstractChannel& channel, \
const std::string& alias = "") { \
updInput(#iname).connect(channel, alias); \
} \
/** @} */
Expand Down Expand Up @@ -1382,14 +1396,16 @@ OpenSim::PropertyIndex Class::constructSocket_##cname() { \
const std::string& alias = "") { \
updInput(#iname).connect(output, alias); \
} \
/** Connect this Input to an output channel of type T##. */ \
/** Append an output channel to the list of connectees in the list */ \
/** Input. */ \
/** You can optionally provide an alias that will be used by this */ \
/** component to refer to the channel. */ \
/** Call finalizeConnections() afterwards to update the input's */ \
/** connectee path property. The reference to the channel set here */ \
/** takes precedence over the connectee path property. */ \
void connectInput_##iname(const OpenSim::AbstractChannel& channel, \
const std::string& alias = "") { \
void appendInputChannel_##iname( \
const OpenSim::AbstractChannel& channel, \
const std::string& alias = "") { \
updInput(#iname).connect(channel, alias); \
} \
/** @} */
Expand Down
4 changes: 2 additions & 2 deletions OpenSim/Common/Reporter.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,10 +145,10 @@ class Reporter : public AbstractReporter {
reporter->addToReport(src->getOutput("column").getChannel("ankle"));
@endcode
This method is equivalent to
connectInput_inputs(const AbstractChannel&, const std::string&). */
appendInputChannel_inputs(const AbstractChannel&, const std::string&). */
void addToReport(const AbstractChannel& channel,
const std::string& alias = "") {
connectInput_inputs(channel, alias);
appendInputChannel_inputs(channel, alias);
}

protected:
Expand Down
18 changes: 9 additions & 9 deletions OpenSim/Common/Test/testComponentInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -583,13 +583,13 @@ TEST_CASE("Component Interface Misc.")
foo3.setName("Foo3");
theWorld.add(&foo3);
foo3.set_mass(4.0);
bar.connectSocket_listFoo(foo3);
bar.appendSocketConnectee_listFoo(foo3);

Foo& foo4 = *new Foo();
foo4.setName("Foo4");
theWorld.add(&foo4);
foo4.set_mass(5.0);
bar.connectSocket_listFoo(foo4);
bar.appendSocketConnectee_listFoo(foo4);

std::cout << "Iterate over Foo's after adding Foo2, Foo3, and Foo4." << std::endl;
for (auto& component : theWorld.getComponentList<Foo>()) {
Expand Down Expand Up @@ -754,7 +754,7 @@ TEST_CASE("Component Interface Misc.")
compFoo.getRelativePathString(bar2));

bar2.connectSocket_childFoo(compFoo.get_Foo1());
bar2.connectSocket_listFoo(compFoo.get_Foo3());
bar2.appendSocketConnectee_listFoo(compFoo.get_Foo3());
compFoo.upd_Foo1().updInput("input1")
.connect(bar2.getOutput("PotentialEnergy"));

Expand Down Expand Up @@ -1018,18 +1018,18 @@ TEST_CASE("Component Interface Sockets")
CHECK(bar.getSocket<Foo>("listFoo").getNumConnectees() == 0);

// Connect to list socket.
bar.connectSocket_listFoo(foo1);
bar.connectSocket_listFoo(foo2);
bar.appendSocketConnectee_listFoo(foo1);
bar.appendSocketConnectee_listFoo(foo2);
theWorld.connect();
theWorld.buildUpSystem(system);
CHECK(bar.getSocket<Foo>("listFoo").getNumConnectees() == 2);

// Check that connecting to the same component throws an Exception.
CHECK_THROWS_WITH(bar.connectSocket_listFoo(foo2),
CHECK_THROWS_WITH(bar.appendSocketConnectee_listFoo(foo2),
Catch::Matchers::Contains("Socket 'listFoo' already has a "
"connectee of type 'Foo' named 'foo2'."));

bar.connectSocket_listFoo(foo3);
bar.appendSocketConnectee_listFoo(foo3);
theWorld.connect();
theWorld.buildUpSystem(system);
CHECK(bar.getSocket<Foo>("listFoo").getNumConnectees() == 3);
Expand Down Expand Up @@ -2201,9 +2201,9 @@ TEST_CASE("Component Interface Single Value Input Connectee Serialization Behavi
// Connect, finalize, etc.
const auto& output = source->getOutput("column");
// See if we preserve the ordering of the channels.
foo->connectInput_input1(output.getChannel("b"));
foo->appendInputChannel_listInput1(output.getChannel("b"));
// We want to make sure aliases are preserved.
foo->connectInput_fiberLength(output.getChannel("d"), "desert");
foo->connectInputChannel_fiberLength(output.getChannel("d"), "desert");
// Ensure that re-finalizing from properties does not cause Inputs
// to hold onto stale references to the outputs' channels.
world.finalizeFromProperties();
Expand Down

0 comments on commit 744c441

Please sign in to comment.