• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

RobotWebTools / rclnodejs / 14751919636

30 Apr 2025 10:00AM UTC coverage: 85.071%. Remained the same
14751919636

Pull #1112

github

web-flow
Merge 0d09af349 into 131ebf8e1
Pull Request #1112: Add typescript interface for the added new functions

711 of 928 branches covered (76.62%)

Branch coverage included in aggregate %.

1745 of 1959 relevant lines covered (89.08%)

1103.7 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

57.39
/lib/time_source.js
1
// Copyright (c) 2018 Intel Corporation. All rights reserved.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//     http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14

15
'use strict';
16

17
const rclnodejs = require('bindings')('rclnodejs');
78✔
18
const { Clock, ROSClock } = require('./clock.js');
78✔
19
const { ClockType } = Clock;
78✔
20
const { Parameter, ParameterType } = require('./parameter.js');
78✔
21
const Time = require('./time.js');
78✔
22

23
const USE_SIM_TIME_PARAM = 'use_sim_time';
78✔
24
const CLOCK_TOPIC = '/clock';
78✔
25

26
/**
27
 * @class - Class representing a TimeSource in ROS
28
 */
29

30
class TimeSource {
31
  /**
32
   * Create a TimeSource.
33
   * @param {Node} node - The node to be attached.
34
   */
35
  constructor(node) {
36
    this._node = node;
1,707✔
37
    this._associatedClocks = [];
1,707✔
38
    this._clockSubscription = undefined;
1,707✔
39
    this._lastTimeSet = new Time(0n, 0n, ClockType.ROS_TIME);
1,707✔
40
    this._isRosTimeActive = false;
1,707✔
41

42
    if (this._node) {
1,707!
43
      this.attachNode(this._node);
1,707✔
44
    }
45
  }
46

47
  get isRosTimeActive() {
48
    return this._isRosTimeActive;
×
49
  }
50

51
  set isRosTimeActive(enabled) {
52
    if (this.isRosTimeActive === enabled) return;
×
53

54
    this._isRosTimeActive = enabled;
×
55
    for (const clock in this._associatedClocks) {
×
56
      clock.isRosTimeActive = enabled;
×
57
    }
58

59
    if (enabled) {
×
60
      this._subscribeToClockTopic();
×
61
    } else if (this._node && this._clockSubscription) {
×
62
      this._node.destroySubscription(this._clockSubscription);
×
63
      this._node._clockSubscription = null;
×
64
    }
65
  }
66

67
  /**
68
   * Return status that whether the ROS time is active.
69
   * @name TimeSource#get:isRosTimeActive
70
   * @function
71
   * @return {boolean} Return true if the time is active, otherwise return false.
72
   */
73

74
  get isRosTimeActive() {
75
    return this._isRosTimeActive;
1,716✔
76
  }
77

78
  /**
79
   * Set the status of time.
80
   * @param {boolean} enabled - Set the ROS time to be active if enabled is true.
81
   * @name TimeSource#set:isRosTimeActive
82
   * @function
83
   * @return {undefined}
84
   */
85

86
  set isRosTimeActive(enabled) {
87
    if (this._isRosTimeActive === enabled) return;
×
88

89
    this._isRosTimeActive = enabled;
×
90
    this._associatedClocks.forEach((clock) => {
×
91
      clock.isRosTimeActive = enabled;
×
92
    });
93
    if (enabled) {
×
94
      this._subscribeToClockTopic();
×
95
    }
96
  }
97

98
  /**
99
   * Attach the clock to a Node object.
100
   * @param {Node} node - The node to be attached.
101
   * @return {undefined}
102
   */
103
  attachNode(node) {
104
    if ((!node) instanceof rclnodejs.ShadowNode) {
1,710!
105
      throw new TypeError('Invalid argument, must be type of Node');
×
106
    }
107

108
    if (this._node) {
1,710✔
109
      this.detachNode();
1,707✔
110
    }
111

112
    this._node = node;
1,710✔
113

114
    if (!node.hasParameter(USE_SIM_TIME_PARAM)) {
1,710✔
115
      node.declareParameter(
1,683✔
116
        new Parameter(USE_SIM_TIME_PARAM, ParameterType.PARAMETER_BOOL, false)
117
      );
118
    }
119

120
    const useSimTimeParam = node.getParameter(USE_SIM_TIME_PARAM);
1,710✔
121
    if (useSimTimeParam.type !== ParameterType.PARAMETER_NOT_SET) {
1,710!
122
      if (useSimTimeParam.type === ParameterType.PARAMETER_BOOL) {
1,710!
123
        this._isRosTimeActive = useSimTimeParam.value;
1,710✔
124
      } else {
125
        node
×
126
          .getLogger()
127
          .error(
128
            `Invalid type for parameter ${USE_SIM_TIME_PARAM} ${useSimTimeParam.type} should be bool`
129
          );
130
      }
131
    } else {
132
      node
×
133
        .getLogger()
134
        .debug(
135
          `${USE_SIM_TIME_PARAM}' parameter not set, using wall time by default`
136
        );
137
    }
138

139
    if (this.isRosTimeActive) {
1,710✔
140
      this._subscribeToClockTopic();
12✔
141
    }
142

143
    node.addOnSetParametersCallback(this.onParameterEvent.bind(this));
1,710✔
144
  }
145

146
  /**
147
   * Detach the node which the clock have attached.
148
   * @return {undefined}
149
   */
150
  detachNode() {
151
    if (this._clockSubscription) {
1,710✔
152
      if (!this._node) {
3!
153
        throw new Error(
×
154
          'Unable to destroy previously created clock subscription'
155
        );
156
      }
157
      this._node.destroySubscription(this._clockSubscription);
3✔
158
    }
159
    this._clockSubscription = undefined;
1,710✔
160
    this._node = undefined;
1,710✔
161
  }
162

163
  /**
164
   * Attach the clock to a TimeSource object.
165
   * @param {Clock} clock - The node to be attached.
166
   * @return {undefined}
167
   */
168
  attachClock(clock) {
169
    if (!(clock instanceof ROSClock)) {
1,719✔
170
      throw new TypeError('Only clocks with type ROS_TIME can be attached.');
6✔
171
    }
172
    clock.rosTimeOverride = this._lastTimeSet;
1,713✔
173
    clock.isRosTimeActive = this._isRosTimeActive;
1,713✔
174
    this._associatedClocks.push(clock);
1,713✔
175
  }
176

177
  _clockCallback(msg) {
178
    this._lastTimeSet = Time.fromMsg(msg.clock);
12✔
179
    this._associatedClocks.forEach((clock) => {
12✔
180
      clock.rosTimeOverride = this._lastTimeSet;
12✔
181
    });
182
  }
183

184
  _subscribeToClockTopic() {
185
    if (!this._clockSubscription && this._node) {
12!
186
      this._clockSubscription = this._node.createSubscription(
12✔
187
        'rosgraph_msgs/msg/Clock',
188
        CLOCK_TOPIC,
189
        this._clockCallback.bind(this)
190
      );
191
    }
192
  }
193

194
  onParameterEvent(parameters = []) {
×
195
    for (const parameter of parameters) {
135✔
196
      if (parameter.name === USE_SIM_TIME_PARAM) {
135!
197
        if (parameter.type === ParameterType.PARAMETER_BOOL) {
×
198
          this.isRosTimeActive = parameter.value;
×
199
        } else if (this._node) {
×
200
          this._node
×
201
            .getLogger()
202
            .error(
203
              `${USE_SIM_TIME_PARAM} parameter set to something besides a bool`
204
            );
205
        }
206

207
        break;
×
208
      }
209
    }
210

211
    return {
135✔
212
      successful: true,
213
      reason: '',
214
    };
215
  }
216
}
217

218
module.exports = TimeSource;
78✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc